pax_global_header00006660000000000000000000000064132371254170014517gustar00rootroot0000000000000052 comment=68c9cb254071e18e9d782bdd4f3ae5c6ab0815b5 Jellyfish-2.2.8/000077500000000000000000000000001323712541700134615ustar00rootroot00000000000000Jellyfish-2.2.8/.gitignore000066400000000000000000000002501323712541700154460ustar00rootroot00000000000000Makefile.in aclocal.m4 autom4te.cache config.h.in configure depcomp install-sh missing compile config.guess config.h.in~ config.sub ltmain.sh *_cmdline.hpp test-driver Jellyfish-2.2.8/.gitmod000066400000000000000000000000101323712541700147340ustar00rootroot00000000000000develop Jellyfish-2.2.8/.travis.yml000066400000000000000000000005471323712541700156000ustar00rootroot00000000000000language: cpp before_install: - mkdir -p ~/bin - curl -L -o ~/bin/yaggo https://github.com/gmarcais/yaggo/releases/download/v1.5.9/yaggo - chmod a+rx ~/bin/yaggo script: autoreconf -i && ./configure YAGGO=~/bin/yaggo && make && make check addons: artifacts: paths: - $(git ls-files -o | grep '\.log$' | tr "\n" ":") s3_region: "us-east-1" Jellyfish-2.2.8/CHANGES000066400000000000000000000006001323712541700144500ustar00rootroot00000000000000Version 1.1 =========== * Read input from pipes. For example, to count DNA from zipped files, run: % gunzip -c *.fa.gz | jellyfish [options] /dev/fd/0 * Support fasta and fastq formats. * Support for counting 'q-mers', as defined by the Quake error correcting software (http://www.cbcb.umd.edu/software/quake/). * New dump subcommands which replaces 'stats -f' and 'stats -c'. Jellyfish-2.2.8/HalfLICENSE000066400000000000000000000032411323712541700152610ustar00rootroot00000000000000Copyright (c) 2006, Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. Portions contributed and copyright held by others as indicated. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Industrial Light & Magic nor the names of any other contributors to this software may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Jellyfish-2.2.8/LICENSE000066400000000000000000001045131323712541700144720ustar00rootroot00000000000000 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 . Jellyfish-2.2.8/Makefile.am000066400000000000000000000227471323712541700155310ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = doc/jellyfish.pdf doc/jellyfish.man README LICENSE # jellyfish.spec man1_MANS = doc/jellyfish.man pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = jellyfish-2.0.pc AM_LDFLAGS = -pthread $(HTSLIB_LIBS) $(HTSLIB_RPATH) # $(VALGRIND_LIBS) AM_CPPFLAGS = -Wall -Wnon-virtual-dtor -I$(srcdir) -I$(srcdir)/include $(VALGRIND_CFLAGS) AM_CXXFLAGS = $(ALL_CXXFLAGS) $(HTSLIB_CFLAGS) #AM_LDADD = $(HTSLIB_LIBS) -lpthread noinst_HEADERS = $(YAGGO_SOURCES) bin_PROGRAMS = dist_bin_SCRIPTS = data_DATA = BUILT_SOURCES = $(YAGGO_SOURCES) CLEANFILES = DISTCLEANFILES = $(BUILT_SOURCES) # Yaggo automatic rules with silencing V_YAGGO = $(V_YAGGO_$(V)) V_YAGGO_ = $(V_YAGGO_$(AM_DEFAULT_VERBOSITY)) V_YAGGO_0 = @echo " YAGGO " $@; .yaggo.hpp: $(V_YAGGO)$(YAGGO) --license $(srcdir)/header-license -o $@ $< YAGGO_SOURCES = # Append all file to be built by yaggo # What to build bin_PROGRAMS += bin/jellyfish lib_LTLIBRARIES = libjellyfish-2.0.la LDADD = libjellyfish-2.0.la # $(VALGRIND_LIBS) check_PROGRAMS = bin/generate_sequence bin/fastq2sam ############################ # Build Jellyfish the exec # ############################ bin_jellyfish_SOURCES = sub_commands/jellyfish.cc \ sub_commands/count_main.cc \ sub_commands/info_main.cc \ sub_commands/dump_main.cc \ sub_commands/histo_main.cc \ sub_commands/stats_main.cc \ sub_commands/merge_main.cc \ sub_commands/bc_main.cc \ sub_commands/query_main.cc \ sub_commands/cite_main.cc \ sub_commands/mem_main.cc \ jellyfish/merge_files.cc bin_jellyfish_LDFLAGS = $(AM_LDFLAGS) $(STATIC_FLAGS) YAGGO_SOURCES += sub_commands/count_main_cmdline.hpp \ sub_commands/info_main_cmdline.hpp \ sub_commands/dump_main_cmdline.hpp \ sub_commands/histo_main_cmdline.hpp \ sub_commands/stats_main_cmdline.hpp \ sub_commands/merge_main_cmdline.hpp \ sub_commands/bc_main_cmdline.hpp \ sub_commands/query_main_cmdline.hpp \ sub_commands/cite_main_cmdline.hpp \ sub_commands/mem_main_cmdline.hpp ###################################### # Build Jellyfish the shared library # ###################################### libjellyfish_2_0_la_LDFLAGS = -version-info 2:0:0 libjellyfish_2_0_la_SOURCES = lib/rectangular_binary_matrix.cc \ lib/mer_dna.cc lib/storage.cc \ lib/allocators_mmap.cc lib/misc.cc \ lib/int128.cc lib/thread_exec.cc \ lib/jsoncpp.cpp lib/time.cc \ lib/generator_manager.cc library_includedir=$(includedir)/jellyfish-@PACKAGE_VERSION@/jellyfish JFI = include/jellyfish library_include_HEADERS = $(JFI)/allocators_mmap.hpp \ $(JFI)/backtrace.hpp $(JFI)/atomic_gcc.hpp \ $(JFI)/large_hash_array.hpp $(JFI)/err.hpp \ $(JFI)/misc.hpp \ $(JFI)/offsets_key_value.hpp \ $(JFI)/int128.hpp \ $(JFI)/rectangular_binary_matrix.hpp \ $(JFI)/mer_dna.hpp $(JFI)/storage.hpp \ $(JFI)/simple_circular_buffer.hpp \ $(JFI)/circular_buffer.hpp \ $(JFI)/atomic_field.hpp \ $(JFI)/compare_and_swap.hpp \ $(JFI)/divisor.hpp \ $(JFI)/large_hash_iterator.hpp \ $(JFI)/jellyfish.hpp $(JFI)/thread_exec.hpp \ $(JFI)/stream_iterator.hpp \ $(JFI)/mer_overlap_sequence_parser.hpp \ $(JFI)/whole_sequence_parser.hpp \ $(JFI)/parser_common.hpp \ $(JFI)/sam_format.hpp \ $(JFI)/binary_dumper.hpp \ $(JFI)/sorted_dumper.hpp \ $(JFI)/text_dumper.hpp $(JFI)/dumper.hpp \ $(JFI)/time.hpp $(JFI)/mer_heap.hpp \ $(JFI)/token_ring.hpp \ $(JFI)/locks_pthread.hpp \ $(JFI)/file_header.hpp \ $(JFI)/generic_file_header.hpp \ $(JFI)/json.h $(JFI)/hash_counter.hpp \ $(JFI)/mapped_file.hpp \ $(JFI)/mer_dna_bloom_counter.hpp \ $(JFI)/bloom_common.hpp \ $(JFI)/bloom_counter2.hpp \ $(JFI)/bloom_filter.hpp \ $(JFI)/cooperative_pool.hpp \ $(JFI)/cooperative_pool2.hpp \ $(JFI)/stream_manager.hpp \ $(JFI)/generator_manager.hpp \ $(JFI)/cpp_array.hpp \ $(JFI)/mer_iterator.hpp \ $(JFI)/atomic_bits_array.hpp \ $(JFI)/stdio_filebuf.hpp \ $(JFI)/mer_qual_iterator.hpp noinst_HEADERS += jellyfish/fstream_default.hpp jellyfish/dbg.hpp \ jellyfish/randomc.h jellyfish/merge_files.hpp ############### # Build tests # ############### bin_generate_sequence_SOURCES = jellyfish/generate_sequence.cc \ jellyfish/mersenne.cpp \ jellyfish/backtrace.cc \ jellyfish/dbg.cc YAGGO_SOURCES += jellyfish/generate_sequence_cmdline.hpp bin_fastq2sam_SOURCES = jellyfish/fastq2sam.cc YAGGO_SOURCES += jellyfish/fastq2sam_cmdline.hpp ######### # Tests # ######### TEST_EXTENSIONS = .sh SH_LOG_COMPILER = $(SHELL) AM_SH_LOG_FLAGS = TESTS = tests/generate_sequence.sh tests/parallel_hashing.sh \ tests/merge.sh tests/bloom_filter.sh tests/big.sh \ tests/subset_hashing.sh tests/multi_file.sh \ tests/bloom_counter.sh tests/large_key.sh tests/sam.sh \ tests/small_mers.sh EXTRA_DIST += $(TESTS) clean-local: clean-local-check .PHONY: clean-local-check clean-local-check: -cd tests; rm -f * tests/parallel_hashing.log: tests/generate_sequence.log tests/subset_hashing.log: tests/generate_sequence.log tests/bloom_filter.log: tests/generate_sequence.log tests/bloom_counter.log: tests/generate_sequence.log tests/multi_file.log: tests/generate_sequence.log tests/merge.log: tests/generate_sequence.log tests/min_qual.log: tests/generate_fastq_sequence.log tests/large_key.log: tests/generate_sequence.log tests/quality_filter.log: tests/generate_sequence.log tests/sam.log: tests/generate_sequence.log tests/small_mers.log: tests/generate_sequence.log # SWIG tests TESTS += tests/swig_python.sh tests/swig_ruby.sh tests/swig_perl.sh tests/swig_python.log: tests/generate_sequence.log tests/swig_ruby.log: tests/generate_sequence.log tests/swig_perl.log: tests/generate_sequence.log EXTRA_DIST += swig/python/test_mer_file.py swig/python/test_hash_counter.py swig/python/test_string_mers.py EXTRA_DIST += swig/ruby/test_mer_file.rb swig/ruby/test_hash_counter.rb swig/ruby/test_string_mers.rb EXTRA_DIST += swig/perl5/t/test_mer_file.t swig/perl5/t/test_hash_counter.t swig/perl5/t/test_string_mers.t ############## # Unit tests # ############## TESTS += unit_tests/unit_tests.sh check_PROGRAMS += bin/test_all bin_test_all_SOURCES = unit_tests/test_main.cc \ unit_tests/test_misc.cc \ unit_tests/test_offsets_key_value.cc \ unit_tests/test_simple_circular_buffer.cc \ unit_tests/test_rectangular_binary_matrix.cc \ unit_tests/test_mer_dna.cc \ unit_tests/test_large_hash_array.cc \ unit_tests/test_mer_overlap_sequence_parser.cc \ unit_tests/test_file_header.cc \ unit_tests/test_mer_iterator.cc \ unit_tests/test_hash_counter.cc \ unit_tests/test_mer_heap.cc \ unit_tests/test_stream_iterator.cc \ unit_tests/test_token_ring.cc \ unit_tests/test_text_dumper.cc \ unit_tests/test_dumpers.cc \ unit_tests/test_mapped_file.cc \ unit_tests/test_int128.cc \ unit_tests/test_mer_dna_bloom_counter.cc \ unit_tests/test_whole_sequence_parser.cc \ unit_tests/test_allocators_mmap.cc \ unit_tests/test_cooperative_pool2.cc \ unit_tests/test_generator_manager.cc \ unit_tests/test_atomic_bits_array.cc \ unit_tests/test_stdio_filebuf.cc bin_test_all_SOURCES += jellyfish/backtrace.cc bin_test_all_CPPFLAGS = -DJSON_IS_AMALGAMATION=1 bin_test_all_CXXFLAGS = $(AM_CXXFLAGS) -I$(srcdir)/unit_tests/gtest/include -I$(srcdir)/unit_tests -I$(srcdir)/include bin_test_all_LDADD = libgtest.la $(LDADD) YAGGO_SOURCES += unit_tests/test_main_cmdline.hpp noinst_HEADERS += unit_tests/test_main.hpp ################# # SWIG bindings # ################# include swig/Makefile.am include gtest.mk -include $(srcdir)/development.mk # Print the value of a variable print-%: @echo -n $($*) Jellyfish-2.2.8/Makefile.simple000066400000000000000000000023501323712541700164110ustar00rootroot00000000000000# This Makefile is meant to be run in the traget directories. There # name start with a '_' by convention and contain a config.h. CC = g++ CPPFLAGS = -Wall -Werror -g -O2 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -I. # Uncomment following to use SSE # CPPFLAGS += -msse -msse2 -DSSE LDFLAGS = -lpthread TARGETS = jellyfish # old TARGETS = mer_counter dump_stats dump_stats_compacted hash_merge SOURCES = $(patsubst %,%.cc,$(TARGETS)) mer_count_thread.cc .SECONDARY: #VPATH=..:../lib %.d: %.cc $(CC) -M -MM -MG -MP $(CPPFLAGS) $< > $@.tmp sed -e 's/$*.o/& $@/g' $@.tmp > $@ && rm $@.tmp all: $(TARGETS) jellyfish: dump_stats_compacted.o square_binary_matrix.o hash_merge.o storage.o misc.o mer_count_thread.o mer_counter.o # compare_dump3: compare_dump3.o # dump_stats_compacted: dump_stats_compacted.o square_binary_matrix.o total_mers_single_fasta: total_mers_single_fasta.o mer_counter_C: mer_counter_C.o # hash_merge: hash_merge.o storage.o misc.o # mer_counter: mer_counter.o mer_count_thread.o storage.o misc.o # dump_mers: dump_mers.o storage.o misc.o dump_stats: dump_stats.o storage.o misc.o clean: rm -f $(TARGETS) *.o *.d # Is the following OK? Shouldn't we include more than that? include $(SOURCES:.cc=.d) -include local.mk Jellyfish-2.2.8/README000066400000000000000000000060651323712541700143500ustar00rootroot00000000000000Installation ============ % ./configure % make # As root: % make install To install in a custom directory: % ./configure --prefix=/my/dir % make % make install Then make sure the following environment variables contain the correct paths: PATH -> /my/dir/bin LD_LIBRARY_PATH -> /my/dir/lib MANPATH -> /my/dir/share/man PKG_CONFIG_PATH -> /my/dir/lib/pkgconfig Only the PATH environment variables is necessary to run jellyfish. MANPATH is used by the man command. PKG_CONFIG_PATH and LD_LIBRARY_PATH are used to compile software against the jellyfish shared library. GCC requirement =============== GCC version 4.4 or higher is required to compile Jellyfish. Most current Linux distribution provides a version of gcc current enough. On RedHat 5.x, install the packages gcc44 and gcc44-c++. To install on Mac OS X: Jellyfish 2.0 does not compile with Apple's Xcode GCC 4.2. Instead, the easiest thing to do is to install GCC 4.8 using MacPorts (http://www.macports.org) using the following commands: sudo port install gcc48 sudo port install gcc_select sudo port select -set gcc mp-gcc48 The first command installs GCC version 4.8. The third command makes that version of GCC the default, and the second installs a package that makes the third command work. After the above, you should be able to run './configure ; make' as normal. Tests ===== To run the built-in tests, do: % make check All tests should pass and 1 test should be skipped (big.sh). Running 'make check' will use about 50MB of disk space and will use every CPUs found on the machine. On our test machine with 32 cores, it takes a few minutes to run. To tests also on large data set, do: % make check BIG=1 WARNING: this uses >40GB of disk space and takes 30 minutes to run (20 to create the data, 10 to run jellyfish). Notes ===== * Jellyfish has been developed and tested on x86-64 GNU/Linux. It compiles and runs correctly the tests on MacOS X (Intel) and FreeBSD. It should be fairly easy to port on other *NIX platform with the gcc compiler, but no guarantee is made. Support for 32-bits platform has not been tested. License ======= * The Mersenne Twister random generator is copyrighted by Agner Fog and distributed under the GPL version 3 or higher. http://www.agner.org. * The Half float implementation is copyrighted by Industrial Light & Magic and is distributed under the license described in the HalfLICENSE file. * 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 . Jellyfish-2.2.8/README.md000066400000000000000000000077241323712541700147520ustar00rootroot00000000000000Jellyfish ========= Overview -------- Jellyfish is a tool for fast, memory-efficient counting of k-mers in DNA. A k-mer is a substring of length k, and counting the occurrences of all such substrings is a central step in many analyses of DNA sequence. Jellyfish can count k-mers using an order of magnitude less memory and an order of magnitude faster than other k-mer counting packages by using an efficient encoding of a hash table and by exploiting the "compare-and-swap" CPU instruction to increase parallelism. JELLYFISH is a command-line program that reads FASTA and multi-FASTA files containing DNA sequences. It outputs its k-mer counts in a binary format, which can be translated into a human-readable text format using the "jellyfish dump" command, or queried for specific k-mers with "jellyfish query". See the UserGuide provided on [Jellyfish's home page][1] for more details. If you use Jellyfish in your research, please cite: Guillaume Marcais and Carl Kingsford, A fast, lock-free approach for efficient parallel counting of occurrences of k-mers. Bioinformatics (2011) 27(6): 764-770 ([first published online January 7, 2011](http://bioinformatics.oxfordjournals.org/cgi/content/abstract/27/6/764 "Paper on Oxford Bioinformatics website")) doi:10.1093/bioinformatics/btr011 Installation ------------ To get an easier to compiled packaged tar ball of the source code, download a release from the [github release][3]. You need make and g++ version 4.4 or higher. To install in your home directory, do: ```Shell ./configure --prefix=$HOME make -j 4 make install ``` To compile from the git tree, you will also need autoconf/automake, and [yaggo](https://github.com/gmarcais/yaggo/releases "Yaggo release on github"). Then to compile and install (in `/usr/local` in that example) with: ```Shell autoreconf -i ./configure make -j 4 sudo make install ``` If the software is installed in system directories (hint: you needed to use `sudo` to install), like the example above, then the system library cache must be updated like such: ```Shell sudo ldconfig ``` Extra / Examples ---------------- In the examples directory are potentially useful extra programs to query/manipulates output files of Jellyfish, using the shared library of Jellyfish in C++ or with scripting languages. The examples are not compiled by default. Each subdirectory of examples is independent and is compiled with a simple invocation of 'make'. Binding to script languages --------------------------- Bindings to Ruby, Python and Perl are provided. This binding allows to read the output file of Jellyfish directly in a scripting language. Compilation of the bindings is easier from the [release tarball][3]. The development files of the target scripting language are required. Compilation of the bindings from the git tree requires [SWIG][2] version 3 and adding the switch `--enable-swig` to the configure command lines show below. To compile all three bindings, configure and compile with: ```Shell ./configure --enable-ruby-binding --enable-python-binding --enable-perl-binding make -j 4 sudo make install ``` By default, Jellyfish is installed in `/usr/local` and the bindings are installed in the proper system location. When the `--prefix` switch is passed, the bindings are installed in the given directory. For example: ```Shell ./configure --prefix=$HOME --enable-python-binding make -j 4 make install ``` This will install the python binding in `$HOME/lib/python2.7/site-packages` (adjust based on your Python version). Then, for Python, Ruby or Perl to find the binding, an environment variable may need to be adjusted (`PYTHONPATH`, `RUBYLIB` and `PERL5LIB` respectively). For example: ```Shell export PYTHONPATH=$HOME/lib/python2.7/site-packages ``` See the [swig directory](../../tree/master/swig) for examples on how to use the bindings. [1]: http://www.genome.umd.edu/jellyfish.html "Genome group at University of Maryland" [2]: http://www.swig.org/ [3]: https://github.com/gmarcais/Jellyfish/releases "Jellyfish release" Jellyfish-2.2.8/config.rpath000066400000000000000000000351061323712541700157730ustar00rootroot00000000000000#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2003 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # 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 2 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, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; mingw* | pw32* | os2*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; newsos6) ;; linux*) case $CC in icc|ecc) wl='-Wl,' ;; ccc) wl='-Wl,' ;; esac ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; sco3.2v5*) ;; solaris*) wl='-Wl,' ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) wl='-Wl,' ;; sysv4*MP*) ;; uts4*) ;; esac fi # Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then case "$host_os" in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris* | sysv5*) if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi4*) ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then hardcode_direct=no fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd2.2*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; freebsd2*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10* | hpux11*) if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=no ;; ia64*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; *) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; openbsd*) hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4.2uw2*) hardcode_direct=yes hardcode_minus_L=no ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) ;; sysv5*) hardcode_libdir_flag_spec= ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. libname_spec='lib$name' case "$host_os" in aix3*) ;; aix[4-9]*) ;; amigaos*) ;; beos*) ;; bsdi4*) ;; cygwin* | mingw* | pw32*) shrext=.dll ;; darwin* | rhapsody*) shrext=.dylib ;; dgux*) ;; freebsd*) ;; gnu*) ;; hpux9* | hpux10* | hpux11*) case "$host_cpu" in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac ;; irix5* | irix6* | nonstopux*) case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux*) ;; netbsd*) ;; newsos6) ;; nto-qnx) ;; openbsd*) ;; os2*) libname_spec='$name' shrext=.dll ;; osf3* | osf4* | osf5*) ;; sco3.2v5*) ;; solaris*) ;; sunos4*) ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) ;; sysv4*MP*) ;; uts4*) ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <= 1.8.0])]) # Check that type __int128 is supported and if the # std::numeric_limits<__int128> specialization exists AC_ARG_WITH([int128], [AS_HELP_STRING([--with-int128], [enable int128])], [], [with_int128=yes]) AS_IF([test "x$with_int128" != xno], [AC_CHECK_TYPE([__int128], [AC_DEFINE([HAVE_INT128], [1], [Define if type __int128 is supported])]) AC_MSG_CHECKING([for std::numeric_limits<__int128>]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include template struct StaticAssert; template<> struct StaticAssert { static void assert() { } };]], [[StaticAssert::is_specialized>::assert();]])], [AC_MSG_RESULT([yes])] [AC_DEFINE([HAVE_NUMERIC_LIMITS128], [1], [Define if numeric limits specialization exists for __int128])], [AC_MSG_RESULT([no])])]) # On MacOS X, use _NSGetExecutablePath to find path to own executable AC_MSG_CHECKING([for _NSGetExecutablePath]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[_NSGetExecutablePath(0, 0);]])], [AC_MSG_RESULT([yes])] [AC_DEFINE([HAVE_NSGETEXECUTABLEPATH], [1], [Used to find executable path on MacOS X])], [AC_MSG_RESULT([no])]) AC_CHECK_HEADERS_ONCE([execinfo.h ext/stdio_filebuf.h sys/syscall.h]) AC_CHECK_MEMBER([siginfo_t.si_int], [AC_DEFINE([HAVE_SI_INT], [1], [Define if siginfo_t.si_int exists])], [], [[#include ]]) # --enable-all-static # Do not use libtool if building all static AC_ARG_ENABLE([all-static], [AC_HELP_STRING([--enable-all-static], [create statically linked executable])]) STATIC_FLAGS= AS_IF([test x$enable_all_static = xyes], [AC_SUBST([STATIC_FLAGS], [-all-static])]) # # SWIG and bindings # maybe_swig= # --enable-python-binding AC_ARG_ENABLE([python-binding], [AC_HELP_STRING([--enable-python-binding@<:@=PATH@:>@], [create SWIG python module and install in PATH])]) # --enable-ruby-binding AC_ARG_ENABLE([ruby-binding], [AC_HELP_STRING([--enable-ruby-binding@<:@=PATH@:>@], [create SWIG ruby module and install in PATH])]) # --enable-perl-binding AC_ARG_ENABLE([perl-binding], [AC_HELP_STRING([--enable-perl-binding@<:@=PATH@:>@], [create SWIG perl module and install in PATH])]) # --enable-all-binding AC_ARG_ENABLE([all-binding], [AC_HELP_STRING([--enable-all-binding@<:@=PATH@:>@], [create SWIG module for all languages and install in PATH])]) # --enable-swig AC_ARG_ENABLE([swig], [AC_HELP_STRING([--enable-swig], [enable development of swig binding])]) AS_IF([test x$enable_swig = xyes], [AX_PKG_SWIG([3.0.0], [], [AC_MSG_ERROR([SWIG version 3 is required])])]) AS_IF([test -n "$SWIG"], [SWIG_ENABLE_CXX]) AM_CONDITIONAL([HAVE_SWIG], [test -n "$SWIG"]) # Python binding setup AS_IF([test -z "$enable_python_binding"], [enable_python_binding="$enable_all_binding"]) AM_CONDITIONAL(PYTHON_BINDING, [test -n "$enable_python_binding" -a x$enable_python_binding != xno]) AM_COND_IF([PYTHON_BINDING], [AS_IF([test x$enable_python_binding != xyes], [PYTHON_SITE_PKG=$enable_python_binding])] [AX_PYTHON_DEVEL([], [$prefix])]) AC_ARG_ENABLE([python-deprecated], [AC_HELP_STRING([--enable-python-deprecated], [enable the deprecated 'jellyfish' module (in addition to 'dna_jellyfish')])]) AM_CONDITIONAL([PYTHON_DEPRECATED], [test -z "$enable_python_deprecated" -o x$enable_python_deprecated != xno]) # Ruby binding setup AS_IF([test -z "$enable_ruby_binding"], [enable_ruby_binding="$enable_all_binding"]) AM_CONDITIONAL([RUBY_BINDING], [test -n "$enable_ruby_binding" -a x$enable_ruby_binding != xno]) AM_COND_IF([RUBY_BINDING], [AS_IF([test x$enable_ruby_binding != xyes], [RUBY_EXT_LIB=$enable_ruby_binding])] [AX_RUBY_EXT([$prefix])]) # Perl binding setup AS_IF([test -z "$enable_perl_binding"], [enable_perl_binding="$enable_all_binding"]) AM_CONDITIONAL([PERL_BINDING], [test -n "$enable_perl_binding" -a x$enable_perl_binding != xno]) AM_COND_IF([PERL_BINDING], [AS_IF([test x$enable_perl_binding != xyes], [PERL_EXT_LIB=$enable_perl_binding])] [AX_PERL_EXT([$prefix])]) AC_OUTPUT Jellyfish-2.2.8/development.mk000066400000000000000000000012451323712541700163360ustar00rootroot00000000000000AM_CXXFLAGS += -Werror # Count lines of code .PHONY: cloc cloc_jellyfish cloc: cloc --force-lang="Ruby,yaggo" --force-lang="make,am" --force-lang="make,mk" \ --exclude-dir="gtest" --ignored=cloc_ignored_src_files \ $(srcdir)/jellyfish $(srcdir)/include $(srcdir)/lib $(srcdir)/sub_commands $(srcdir)/tests $(srcdir)/unit_tests \ $(srcdir)/Makefile.am $(srcdir)/*.mk cloc_jellyfish: cloc $(srcdir)/jellyfish $(srcdir)/include $(srcdir)/lib $(srcdir)/sub_commands cloc_library: cloc $(srcdir)/include $(srcdir)/lib # Make a dependency on yaggo the software $(YAGGO_SOURCES): $(YAGGO) # Launch unit tests unittests: @$(MAKE) check TESTS=unit_tests/unit_tests.sh Jellyfish-2.2.8/doc/000077500000000000000000000000001323712541700142265ustar00rootroot00000000000000Jellyfish-2.2.8/doc/Makefile000066400000000000000000000010221323712541700156610ustar00rootroot00000000000000L2M = latex2man -t transfile MI = makeinfo PDFLATEX = pdflatex M4 = m4 TARGETS = jellyfish.man jellyfish.html jellyfish.pdf all: $(TARGETS) man: jellyfish.man man ./$< options.tex: generate_options_tex.sh sh $< > $@ %-full.tex: %.tex options.tex $(M4) $< > $@ %.man: %-full.tex $(L2M) $< $@ %.html: %-full.tex $(L2M) -H $< $@ %.texi: %-full.tex $(L2M) -T $< $@ %.info: %.texi $(MI) --force $< $@ %.latex: %-full.tex $(L2M) -L $< $@ %.pdf: %.latex $(PDFLATEX) $< clean: rm -f $(TARGETS) *-full.tex options.tex Jellyfish-2.2.8/doc/UserGuide.lyx000066400000000000000000000632551323712541700166730ustar00rootroot00000000000000#LyX 2.0 created this file. For more info see http://www.lyx.org/ \lyxformat 413 \begin_document \begin_header \textclass report \begin_preamble \usepackage[letterpaper]{geometry} \usepackage{siunitx} \end_preamble \use_default_options true \begin_modules theorems-ams eqs-within-sections figs-within-sections \end_modules \maintain_unincluded_children false \language english \language_package default \inputencoding auto \fontencoding global \font_roman default \font_sans default \font_typewriter default \font_default_family default \use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default \default_output_format default \output_sync 0 \bibtex_command default \index_command default \paperfontsize default \spacing single \use_hyperref false \papersize default \use_geometry false \use_amsmath 1 \use_esint 1 \use_mhchem 1 \use_mathdots 1 \cite_engine basic \use_bibtopic false \use_indices false \paperorientation portrait \suppress_date false \use_refstyle 1 \index Index \shortcut idx \color #008000 \end_index \secnumdepth 2 \tocdepth 2 \paragraph_separation indent \paragraph_indentation default \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict false \end_header \begin_body \begin_layout Title Jellyfish 2 User Guide \end_layout \begin_layout Standard \begin_inset CommandInset toc LatexCommand tableofcontents \end_inset \end_layout \begin_layout Standard \begin_inset FormulaMacro \newcommand{\switch}[1]{\texttt{-\@-#1}} \end_inset \begin_inset FormulaMacro \newcommand{\opt}[1]{\texttt{-#1}} \end_inset \end_layout \begin_layout Chapter Getting started \end_layout \begin_layout Section Counting all \begin_inset Formula $k$ \end_inset -mers \end_layout \begin_layout Standard The basic command to count all \begin_inset Formula $k$ \end_inset -mers is as follows: \end_layout \begin_layout LyX-Code jellyfish count -m 21 -s 100M -t 10 -C reads.fasta \end_layout \begin_layout Standard This will count canonical ( \begin_inset Formula $\opt C$ \end_inset ) \begin_inset Formula $21$ \end_inset -mers ( \family sans \begin_inset Formula $\opt m\,21$ \end_inset \family default ), using a hash with 100 million elements ( \family sans \begin_inset Formula $\opt s\,\unit[100]{M}$ \end_inset \family default ) and 10 threads ( \family sans \begin_inset Formula $\opt t\,10$ \end_inset \family default ) in the sequences in the file \family sans reads.fasta \family default . The output is written in the file ' \family sans mer_counts.jf \family default ' by default (change with \family sans \begin_inset Formula $\opt o$ \end_inset \family default switch). \end_layout \begin_layout Standard To compute the histogram of the \begin_inset Formula $k$ \end_inset -mer occurrences, use the \family sans histo \family default subcommand (see section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sec:histo" \end_inset ): \end_layout \begin_layout LyX-Code jellyfish histo mer_counts.jf \end_layout \begin_layout Standard To query the counts of a particular \begin_inset Formula $k$ \end_inset -mer, use the \family sans query \family default subcommand (see section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sec:query" \end_inset ): \end_layout \begin_layout LyX-Code jellyfish query mer_counts.jf AACGTTG \end_layout \begin_layout Standard To output all the counts for all the \begin_inset Formula $k$ \end_inset -mers in the file, use the \family sans dump \family default subcommand (see section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sec:dump" \end_inset ): \end_layout \begin_layout LyX-Code jellyfish dump mer_counts.jf > mer_counts_dumps.fa \end_layout \begin_layout Standard To get some information on how, when and where this jellyfish file was generated , use the \family sans info \family default subcommand (see section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sec:info" \end_inset ): \end_layout \begin_layout LyX-Code jellyfish info mer_counts.jf \end_layout \begin_layout Standard For more detail information, see the relevant sections in this document. All commands understand \begin_inset Formula $\switch{help}$ \end_inset and will produce some information about the switches available. \end_layout \begin_layout Subsection Counting \begin_inset Formula $k$ \end_inset -mers in sequencing reads \end_layout \begin_layout Standard In sequencing reads, it is unknown which strands of the DNA is sequenced. As a consequence, a \begin_inset Formula $k$ \end_inset -mer or its reverse complement are essentially equivalent. The canonical representative of a \begin_inset Formula $k$ \end_inset -mer \begin_inset Formula $m$ \end_inset is by definition \begin_inset Formula $m$ \end_inset or the reverse complement of \begin_inset Formula $m$ \end_inset , whichever comes first lexicographically. The \family sans \begin_inset Formula $\opt C$ \end_inset \family default switch instructs to save in the hash only canonical \begin_inset Formula $k$ \end_inset -mers, while the count is the number of occurrences of both a \begin_inset Formula $k$ \end_inset -mer and it reverse complement. \end_layout \begin_layout Standard The size parameter (given with \begin_inset Formula $\opt s$ \end_inset ) is an indication of the number \begin_inset Formula $k$ \end_inset -mers that will be stored in the hash. For sequencing reads, one this size should be the size of the genome plus the \begin_inset Formula $k$ \end_inset -mers generated by sequencing errors. For example, if the error rate is \begin_inset Formula $e$ \end_inset (e.g. \begin_inset ERT status open \begin_layout Plain Layout \backslash @ \end_layout \end_inset Illumina reads, usually \begin_inset Formula $e\approx1\%$ \end_inset ), with an estimated genome size of \begin_inset Formula $G$ \end_inset and a coverage of \begin_inset Formula $c$ \end_inset , the number of expected \begin_inset Formula $k$ \end_inset -mers is \begin_inset Formula $G+Gcek$ \end_inset . This assume \end_layout \begin_layout Quote NOTE: unlike in Jellyfish 1, this \family sans -s \family default parameter is only an estimation. If the size given is too small to fit all the \begin_inset Formula $k$ \end_inset -mers, the hash size will be increased automatically or partial results will be written to disk and finally merged automatically. Running ' \family sans jellyfish merge \family default ' should never be necessary, as now jellyfish now takes care of this task on its own. \end_layout \begin_layout Standard If the low frequency \begin_inset Formula $k$ \end_inset -mers ( \begin_inset Formula $k$ \end_inset -mers occurring only once), which are mostly due to sequencing errors, are not of interest, one might consider counting only high-frequency \begin_inset Formula $k$ \end_inset -mers (see section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sec:Counting-high-frequency--mers" \end_inset ), which uses less memory and is potentially faster. \end_layout \begin_layout Subsection Counting \begin_inset Formula $k$ \end_inset -mers in a genome \end_layout \begin_layout Standard In an actual genome or finished sequence, a \begin_inset Formula $k$ \end_inset -mer and its reverse complement are not equivalent, hence using the \family sans \begin_inset Formula $\opt C$ \end_inset \family default switch does not make sense. In addition, the size for the hash can be set directly to the size of the genome. \end_layout \begin_layout Section Counting high-frequency \begin_inset Formula $k$ \end_inset -mers \begin_inset CommandInset label LatexCommand label name "sec:Counting-high-frequency--mers" \end_inset \end_layout \begin_layout Standard Jellyfish offers two way to count only high-frequency \begin_inset Formula $k$ \end_inset -mers (meaning only \begin_inset Formula $k$ \end_inset -mers with count \begin_inset Formula $>1$ \end_inset ), which reduces significantly the memory usage. Both methods are based on using Bloom filters. The first method is a one pass method, which provides approximate count for some percentage of the \begin_inset Formula $k$ \end_inset -mers. The second method is a two pass method which provides exact count. In both methods, most of the low-frequency \begin_inset Formula $k$ \end_inset -mers are not reported. \end_layout \begin_layout Subsection One pass method \begin_inset CommandInset label LatexCommand label name "sub:One-pass-method" \end_inset \end_layout \begin_layout Standard Adding the \family sans \begin_inset Formula $\switch{bf-size}$ \end_inset \family default switch make jellyfish first insert all \begin_inset Formula $k$ \end_inset -mers first into a Bloom filter and only insert into the hash the \begin_inset Formula $k$ \end_inset -mers which have already been seen at least once. The argument to \begin_inset Formula $\switch{bf-size}$ \end_inset should the total number of \begin_inset Formula $k$ \end_inset -mer expected in the data set while the \family sans \begin_inset Formula $\switch{size}$ \end_inset argument should be the number of \begin_inset Formula $k$ \end_inset -mers occurring more than once. For example: \end_layout \begin_layout LyX-Code jellyfish count -m 25 -s 3G --bf-size 100G -t 16 homo_sapiens.fa \end_layout \begin_layout Standard would be appropriate for counting \begin_inset Formula $25$ \end_inset -mers in human reads at \begin_inset Formula $30\times$ \end_inset coverage. The approximate memory usage is \begin_inset Formula $\SI{9}{bits}$ \end_inset per \begin_inset Formula $k$ \end_inset -mer in the Bloom filter. \end_layout \begin_layout Standard The count reported for each \begin_inset Formula $k$ \end_inset -mer (by ' \family sans jellyfish dump \family default ' or ' \family sans jellyfish query \family default ') is one less than the actual count. Meaning, the count \begin_inset Formula $1$ \end_inset \begin_inset Formula $k$ \end_inset -mer are not reported, count \begin_inset Formula $2$ \end_inset \begin_inset Formula $k$ \end_inset -mer are reported to have count \begin_inset Formula $1$ \end_inset , etc. \end_layout \begin_layout Standard The drawback of this method is some percentage of the \begin_inset Formula $k$ \end_inset -mer that should not be reported (because they occur only once) are reported. This is due to the random nature of the Bloom filter data structure. The percentage is \begin_inset Formula $<1\%$ \end_inset by default and can be changed with the \begin_inset Formula $\switch{bf-fp}$ \end_inset switch. \end_layout \begin_layout Subsection Two pass method \end_layout \begin_layout Standard In the two pass method, first a Bloom counter is created from the reads with ' \family sans jellyfish bc \family default '. Then this Bloom counter is given to the ' \family sans jelllyfish count \family default ' command and only the \begin_inset Formula $k$ \end_inset -mers which have been seen twice in the first pass will be inserted in the hash. For example, with a human data set similar that in section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sub:One-pass-method" \end_inset : \end_layout \begin_layout LyX-Code jellyfish bc -m 25 -s 100G -t 16 -o homo_sapiens.bc homo_sapiens.fa \end_layout \begin_layout LyX-Code jellyfish count -m 25 -s 3G -t 16 --bc homo_sapiens.bc homo_sapiens.fa \end_layout \begin_layout Standard The advantage of this method is that the counts reported for the \begin_inset Formula $k$ \end_inset -mers are all correct. Most count \begin_inset Formula $1$ \end_inset \begin_inset Formula $k$ \end_inset -mer are not reported, except for a small percentage (set by the \family sans \begin_inset Formula $\opt f$ \end_inset \family default switch of the \family sans bc \family default subcommand) of them which are reported (correctly with count \begin_inset Formula $1$ \end_inset ). All other \begin_inset Formula $k$ \end_inset -mers are reported with the correct count. \end_layout \begin_layout Standard The drawback of this method is that it requires to parse the entire reads data set twice and the memory usage of the Bloom counter is greater than that of the Bloom filter (slightly less than twice as much). \end_layout \begin_layout Chapter FAQ \end_layout \begin_layout Section How to read compressed files (or other format)? \end_layout \begin_layout Standard Jellyfish only reads FASTA or FASTQ formatted input files. By reading from pipes, jellyfish can read compressed files, like this: \end_layout \begin_layout LyX-Code zcat *.fastq.gz | jellyfish count /dev/fd/0 ... \end_layout \begin_layout Standard or by using the \family sans '<() \family default ' \family sans redirection \family default provided by the shell (e.g. \begin_inset ERT status open \begin_layout Plain Layout \backslash @ \end_layout \end_inset bash, zsh): \end_layout \begin_layout LyX-Code jellyfish count <(zcat file1.fastq.gz) <(zcat file2.fasta.gz) ... \end_layout \begin_layout Section How to read multiple files at once? \end_layout \begin_layout Standard Often, jellyfish can parse an input sequence file faster than \family sans gzip \family default or \family sans fastq-dump \family default (to parse SRA files) can output the sequence. This leads to many threads in jellyfish going partially unused. Jellyfish can be instructed to open multiple file at once. For example, to read two short read archive files simultaneously: \end_layout \begin_layout LyX-Code jellyfish count -F 2 <(fastq-dump -Z file1.sra) <(fastq-dump -Z file2.sra) ... \end_layout \begin_layout Standard Another way is to use \begin_inset Quotes eld \end_inset generators \begin_inset Quotes erd \end_inset . First, create a file containing, one per line, commands to generate sequence. Then pass this file to jellyfish and the number of generators to run simultaneo usly. Jellyfish will spawn subprocesses running the commands passed and read their standard output for sequence. By default, the commands are run using the shell in the SHELL environment variable, and this can be changed by the \family sans \begin_inset Formula $\opt S$ \end_inset \family default switch. Multiple generators will be run simultaneously as specified by the \family sans \begin_inset Formula $\opt G$ \end_inset \family default switch. For example: \end_layout \begin_layout LyX-Code ls *.fasta.gz | xargs -n 1 echo gunzip -c > generators \end_layout \begin_layout LyX-Code jellyfish count -g generators -G 4 ... \end_layout \begin_layout Standard The first command created the command list into the ' \family sans generators \family default ' file, each command unzipping one FASTA file in the current directory. The second command runs jellyfish with \begin_inset Formula $4$ \end_inset concurrent generators. \end_layout \begin_layout Section How to reduce the output size? \end_layout \begin_layout Standard The output file was design to be easy to read, but the file generated can be rather large. By default, a \begin_inset Formula $\SI{4}{bytes}$ \end_inset counter value is saved for every \begin_inset Formula $k$ \end_inset -mer (i.e. \begin_inset ERT status open \begin_layout Plain Layout \backslash @ \end_layout \end_inset a maximum count of over 4 billion). Instead, a counter size of \begin_inset Formula $\SI{2}{bytes}$ \end_inset or \begin_inset Formula $\SI{1}{byte}$ \end_inset can be used with the switch \begin_inset Formula $\switch{out-counter-len}$ \end_inset , which reduces significantly the output size. \end_layout \begin_layout Standard The count of \begin_inset Formula $k$ \end_inset -mers which cannot be represented with the given number of bytes will have a value equal to the maximum value that can be represented. Meaning, if the counter field uses \begin_inset Formula $\SI{1}{byte}$ \end_inset , any \begin_inset Formula $k$ \end_inset -mers with count greater or equal to \begin_inset Formula $255$ \end_inset will be reported of having a count \begin_inset Formula $255$ \end_inset . \end_layout \begin_layout Standard Also, low frequency and high frequency \begin_inset Formula $k$ \end_inset -mers can be skipped using the \family sans \begin_inset Formula $\opt L$ \end_inset \family default and \family sans \begin_inset Formula $\opt U$ \end_inset \family default switches respectively. Although it might be more appropriate to filter out the low frequency \begin_inset Formula $k$ \end_inset -mers using Bloom filters, as shown in section \begin_inset space ~ \end_inset \begin_inset CommandInset ref LatexCommand ref reference "sec:Counting-high-frequency--mers" \end_inset . \end_layout \begin_layout Section How much memory is needed? \end_layout \begin_layout Standard The memory needed to count \begin_inset Formula $k$ \end_inset -mers, given the various parameters of the \family sans count \family default subcommand is obtained by using the \family sans mem \family default subcommand. It understand all the same switches, but only the \begin_inset Formula $\switch{mer-len}$ \end_inset ( \begin_inset Formula $\opt m$ \end_inset ), \begin_inset Formula $\switch{size}$ \end_inset ( \begin_inset Formula $\opt s$ \end_inset ), \begin_inset Formula $\switch{counter-len}$ \end_inset ( \begin_inset Formula $\opt c$ \end_inset ) and \begin_inset Formula $\switch{reprobes}$ \end_inset ( \begin_inset Formula $\opt p$ \end_inset ) switches are taken into account. \end_layout \begin_layout Standard For example, for \begin_inset Formula $24$ \end_inset -mers, with an initial hash size of 1 billion, and default parameters otherwise, the memory usage is: \end_layout \begin_layout LyX-Code $ jellyfish mem -m 24 -s 1G \end_layout \begin_layout LyX-Code 4521043056 (4G) \end_layout \begin_layout Standard Conversely, if the \begin_inset Formula $\switch{size}$ \end_inset switch is not given by the \begin_inset Formula $\switch{mem}$ \end_inset switch is, then the maximum initial hash size that would fit in the given memory is returned. For example, this is the maximum hash size for \begin_inset Formula $31$ \end_inset -mers in \begin_inset Formula $\unit[8]{Gb}$ \end_inset of RAM: \end_layout \begin_layout LyX-Code $ jellyfish mem -m 31 --mem 8g \end_layout \begin_layout LyX-Code 1073741824 (1G) \end_layout \begin_layout Chapter Subcommands \end_layout \begin_layout Section \family sans histo \begin_inset CommandInset label LatexCommand label name "sec:histo" \end_inset \end_layout \begin_layout Standard The \family sans histo \family default subcommand outputs the histogram of \begin_inset Formula $k$ \end_inset -mers frequencies. The last bin, with value one above the high setting set by the \family sans \begin_inset Formula $\opt h$ \end_inset \family default switch ( \begin_inset Formula $10\,000$ \end_inset by default), is a catch all: all \begin_inset Formula $k$ \end_inset -mers with a count greater than the high setting are tallied in that one bin. If the low setting is set ( \family sans \begin_inset Formula $\opt l$ \end_inset \family default switch), then the first bin, with value one below the low setting, is also similarly a catch all. \end_layout \begin_layout Standard By default, the bins with a zero count are skipped. This can be changed with the \family sans \begin_inset Formula $\opt f$ \end_inset \family default switch. \end_layout \begin_layout Section \family sans dump \family default \begin_inset CommandInset label LatexCommand label name "sec:dump" \end_inset \end_layout \begin_layout Standard The \family sans dump \family default subcommand outputs a list of all the \begin_inset Formula $k$ \end_inset -mers in the file associated with their count. By default, the output is in FASTA format, where the header line contains the count of the \begin_inset Formula $k$ \end_inset -mer and the sequence part is the sequence of the \begin_inset Formula $k$ \end_inset -mer. This format has the advantage that the output contains the sequence of \begin_inset Formula $k$ \end_inset -mers and can be directly fed into another program expecting the very common FASTA format. A more convenient column format (for human beings) is selected with the \family sans -c \family default switch. \end_layout \begin_layout Standard Low frequency and high frequency \begin_inset Formula $k$ \end_inset -mers can be skipped with the \family sans \begin_inset Formula $\opt L$ \end_inset \family default and \family sans \begin_inset Formula $\opt U$ \end_inset \family default switches respectively. \end_layout \begin_layout Standard In the output of the \family sans dump \family default subcommand, the \begin_inset Formula $k$ \end_inset -mers are sorted according to the hash function used by Jellyfish. The output can be considered to be \begin_inset Quotes eld \end_inset fairly pseudo-random \begin_inset Quotes erd \end_inset . By \begin_inset Quotes eld \end_inset fairly \begin_inset Quotes erd \end_inset we mean that NO guarantee is made about the actual randomness of this order, it is just good enough for the hash table to work properly. And by \begin_inset Quotes eld \end_inset pseudo-random \begin_inset Quotes erd \end_inset we mean that the order is actually deterministic: given the same hash function, the output will be always the same and two different files generated with the same hash function can be merged easily. \end_layout \begin_layout Section \family sans query \begin_inset CommandInset label LatexCommand label name "sec:query" \end_inset \end_layout \begin_layout Standard The \family sans query \family default subcommand outputs the \begin_inset Formula $k$ \end_inset -mers and their counts for some subset of \begin_inset Formula $k$ \end_inset -mers. It will outputs the counts of all the \begin_inset Formula $k$ \end_inset -mers passed on the command line or of all the \begin_inset Formula $k$ \end_inset -mers in the sequence read from the FASTA or FASTQ formatted file passed to the switch \family sans \begin_inset Formula $\opt s$ \end_inset \family default (this switch can be given multiple times). \end_layout \begin_layout Section \family sans info \family default \begin_inset CommandInset label LatexCommand label name "sec:info" \end_inset \end_layout \begin_layout Standard The \family sans info \family default subcommand outputs some information about the jellyfish file and the command used to generated it, in which directory and at what time the command was run. Hopefully, the information given should be enough to rerun jellyfish under the same conditions and reproduce the output file. In particular, the \family sans \begin_inset Formula $\opt c$ \end_inset \family default switch outputs the command, properly escaped and ready to run in a shell. \end_layout \begin_layout Standard The header is saved in JSON format and contains more information than is written by the default. The full header in JSON format can be written out using the \family sans -j \family default switch. \end_layout \begin_layout Section \family sans merge \family default \begin_inset CommandInset label LatexCommand label name "sec:merge" \end_inset \end_layout \begin_layout Standard The \family sans merge \family default subcommand is a little direct use with version version 2 of jellyfish. When intermediary files were written to disk, because not all \begin_inset Formula $k$ \end_inset -mers would fit in memory, they can be merged into one file containing the final result with the \family sans merge \family default subcommand. The \family sans count \family default will merge intermediary files automatically as needed. \end_layout \begin_layout Section stats \begin_inset CommandInset label LatexCommand label name "sec:stats" \end_inset \end_layout \begin_layout Standard The \family sans stats \family default subcommand computes some statistics about the mers. Although these statistics could be computed from the histogram, it provides quick summary information. The fields are: \end_layout \begin_layout Description Unique The number of \begin_inset Formula $k$ \end_inset -mer occuring exactly once \end_layout \begin_layout Description Distinct The number of \begin_inset Formula $k$ \end_inset -mers, ignoring their multiplicity (i.e. \begin_inset ERT status open \begin_layout Plain Layout \backslash @ \end_layout \end_inset the cardinality of the set of \begin_inset Formula $k$ \end_inset -mers) \end_layout \begin_layout Description Total The number of \begin_inset Formula $k$ \end_inset -mers with multiplicity (i.e. \begin_inset ERT status open \begin_layout Plain Layout \backslash @ \end_layout \end_inset the sum of the number of occurence of all the mers) \end_layout \begin_layout Description Max_count The maximum of the number of occurences \end_layout \begin_layout Section mem \begin_inset CommandInset label LatexCommand label name "sec:mem" \end_inset \end_layout \begin_layout Standard The \family sans mem \family default subcommand shows how much memory a count subcommand will need or conversely how large of a hash size will fit in a given amount of memory. \end_layout \begin_layout Section cite \begin_inset CommandInset label LatexCommand label name "sec:cite" \end_inset \end_layout \begin_layout Standard The \family sans cite \family default subcommand prints the citation for the jellyfish paper. With the \begin_inset Formula $\opt b$ \end_inset , it is formatted in Bibtex format. How convenient! \end_layout \end_body \end_document Jellyfish-2.2.8/doc/generate_options_tex.sh000077500000000000000000000002661323712541700210160ustar00rootroot00000000000000#! /bin/sh for i in count stats histo dump merge query qhisto qdump qmerge cite; do echo "\\subsection{$i}" jellyfish $i --help | ruby option_to_tex /dev/fd/0 echo done Jellyfish-2.2.8/doc/help_parse.rb000066400000000000000000000215361323712541700167040ustar00rootroot00000000000000# Autogenerated from a Treetop grammar. Edits may be lost. module HelpGrammar include Treetop::Runtime def root @root ||= :line end module Line0 def spaces elements[0] end def sws elements[1] end def text elements[2] end end module Line1 def to_tex(opened) res = "" unless sws.empty? if !opened.is_open res << "\\begin{description}\n" opened.is_open = true end res << "\\item[" res << sws.elements.map { |s| s.to_tex }.join(",") res << "] " end res << "\\noindent " unless text.text_value.empty? res << quote(text.text_value) end end def _nt_line start_index = index if node_cache[:line].has_key?(index) cached = node_cache[:line][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] r1 = _nt_spaces s0 << r1 if r1 s2, i2 = [], index loop do r3 = _nt_switches if r3 s2 << r3 else break end end r2 = instantiate_node(SyntaxNode,input, i2...index, s2) s0 << r2 if r2 r4 = _nt_text s0 << r4 if r4 s5, i5 = [], index loop do if has_terminal?('\G[\\n]', true, index) r6 = true @index += 1 else r6 = nil end if r6 s5 << r6 else break end end r5 = instantiate_node(SyntaxNode,input, i5...index, s5) s0 << r5 end end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(Line0) r0.extend(Line1) else @index = i0 r0 = nil end node_cache[:line][start_index] = r0 r0 end def _nt_spaces start_index = index if node_cache[:spaces].has_key?(index) cached = node_cache[:spaces][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end s0, i0 = [], index loop do if has_terminal?('\G[\\s]', true, index) r1 = true @index += 1 else r1 = nil end if r1 s0 << r1 else break end end r0 = instantiate_node(SyntaxNode,input, i0...index, s0) node_cache[:spaces][start_index] = r0 r0 end module Switches0 def sw elements[1] end end module Switches1 def to_tex sw.to_tex end end def _nt_switches start_index = index if node_cache[:switches].has_key?(index) cached = node_cache[:switches][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?("-", false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("-") r1 = nil end s0 << r1 if r1 i2 = index r3 = _nt_short_switch if r3 r2 = r3 else r4 = _nt_long_switch if r4 r2 = r4 else @index = i2 r2 = nil end end s0 << r2 end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(Switches0) r0.extend(Switches1) else @index = i0 r0 = nil end node_cache[:switches][start_index] = r0 r0 end module ShortSwitch0 def name elements[0] end def spaces elements[2] end end module ShortSwitch1 def to_tex "\\Opt{-#{name.text_value}}" end end def _nt_short_switch start_index = index if node_cache[:short_switch].has_key?(index) cached = node_cache[:short_switch][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?('\G[a-zA-Z]', true, index) r1 = true @index += 1 else r1 = nil end s0 << r1 if r1 if has_terminal?(",", false, index) r3 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure(",") r3 = nil end if r3 r2 = r3 else r2 = instantiate_node(SyntaxNode,input, index...index) end s0 << r2 if r2 r4 = _nt_spaces s0 << r4 end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(ShortSwitch0) r0.extend(ShortSwitch1) else @index = i0 r0 = nil end node_cache[:short_switch][start_index] = r0 r0 end module LongSwitch0 end module LongSwitch1 def name elements[1] end def val elements[2] end def spaces elements[4] end end module LongSwitch2 def to_tex val.empty? ? "\\LOpt{#{quote(name.text_value)}}" : "\\LOptArg{#{quote(name.text_value)}}{#{quote(val.text_value)}}" end end def _nt_long_switch start_index = index if node_cache[:long_switch].has_key?(index) cached = node_cache[:long_switch][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end i0, s0 = index, [] if has_terminal?("-", false, index) r1 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("-") r1 = nil end s0 << r1 if r1 s2, i2 = [], index loop do if has_terminal?('\G[^,\\s=]', true, index) r3 = true @index += 1 else r3 = nil end if r3 s2 << r3 else break end end if s2.empty? @index = i2 r2 = nil else r2 = instantiate_node(SyntaxNode,input, i2...index, s2) end s0 << r2 if r2 i5, s5 = index, [] if has_terminal?("=", false, index) r6 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure("=") r6 = nil end s5 << r6 if r6 s7, i7 = [], index loop do if has_terminal?('\G[^,\\s]', true, index) r8 = true @index += 1 else r8 = nil end if r8 s7 << r8 else break end end if s7.empty? @index = i7 r7 = nil else r7 = instantiate_node(SyntaxNode,input, i7...index, s7) end s5 << r7 end if s5.last r5 = instantiate_node(SyntaxNode,input, i5...index, s5) r5.extend(LongSwitch0) else @index = i5 r5 = nil end if r5 r4 = r5 else r4 = instantiate_node(SyntaxNode,input, index...index) end s0 << r4 if r4 if has_terminal?(",", false, index) r10 = instantiate_node(SyntaxNode,input, index...(index + 1)) @index += 1 else terminal_parse_failure(",") r10 = nil end if r10 r9 = r10 else r9 = instantiate_node(SyntaxNode,input, index...index) end s0 << r9 if r9 r11 = _nt_spaces s0 << r11 end end end end if s0.last r0 = instantiate_node(SyntaxNode,input, i0...index, s0) r0.extend(LongSwitch1) r0.extend(LongSwitch2) else @index = i0 r0 = nil end node_cache[:long_switch][start_index] = r0 r0 end def _nt_text start_index = index if node_cache[:text].has_key?(index) cached = node_cache[:text][index] if cached cached = SyntaxNode.new(input, index...(index + 1)) if cached == true @index = cached.interval.end end return cached end s0, i0 = [], index loop do if has_terminal?('\G[^\\n]', true, index) r1 = true @index += 1 else r1 = nil end if r1 s0 << r1 else break end end r0 = instantiate_node(SyntaxNode,input, i0...index, s0) node_cache[:text][start_index] = r0 r0 end end class HelpGrammarParser < Treetop::Runtime::CompiledParser include HelpGrammar end Jellyfish-2.2.8/doc/help_parse.treetop000066400000000000000000000020321323712541700177510ustar00rootroot00000000000000grammar HelpGrammar rule line spaces sws:switches* text [\n]* { def to_tex(opened) res = "" unless sws.empty? if !opened.is_open res << "\\begin{description}\n" opened.is_open = true end res << "\\item[" res << sws.elements.map { |s| s.to_tex }.join(",") res << "] " end res << "\\noindent " unless text.text_value.empty? res << quote(text.text_value) end } end rule spaces [\s]* end rule switches "-" sw:( short_switch / long_switch ) { def to_tex sw.to_tex end } end rule short_switch name:[a-zA-Z] ","? spaces { def to_tex "\\Opt{-#{name.text_value}}" end } end rule long_switch "-" name:[^,\s=]+ val:("=" [^,\s]+)? ","? spaces { def to_tex val.empty? ? "\\LOpt{#{quote(name.text_value)}}" : "\\LOptArg{#{quote(name.text_value)}}{#{quote(val.text_value)}}" end } end rule text [^\n]* end end Jellyfish-2.2.8/doc/jellyfish.html000066400000000000000000000446671323712541700171260ustar00rootroot00000000000000 JELLYFISH

Jellyfish: A fast k-mer counter

G. Marcais and C. Kingsford

2010/10/1

Version 1.1.4

Jellyfish is a software to count k-mers in DNA sequences.

Table of Contents

Synopsis

jellyfish count [-oprefix] [-mmerlength] [-tthreads] [-shashsize] [--both-strands] fasta [fasta ...]
jellyfish merge hash1 hash2 ...
jellyfish dump hash
jellyfish stats hash
jellyfish histo [-hhigh] [-llow] [-iincrement] hash
jellyfish query hash
jellyfish cite

Plus equivalent version for Quake mode: qhisto, qdump and qmerge.

Description

Jellyfish is a k-mer counter based on a multi-threaded hash table implementation.

Counting and merging

To count k-mers, use a command like:

jellyfish count -m 22 -o output -c 3 -s 10000000 -t 32 input.fasta

This will count the the 22-mers in input.fasta with 32 threads. The counter field in the hash uses only 3 bits and the hash has at least 10 million entries.

The output files will be named output_0, output_1, etc. (the prefix is specified with the -o switch). If the hash is large enough (has specified by the -s switch) to fit all the k-mers, there will be only one output file named output_0. If the hash filled up before all the mers were read, the hash is dumped to disk, zeroed out and reading in mers resumes. Multiple intermediary files will be present on the disks, named output_0, output_1, etc.

To obtain correct results from the other sub-commands (such as histo, stats, etc.), the multiple output files, if any, need to be merged into one with the merge command. For example with the following command:

jellyfish merge -o output.jf output\_*

Should you get many intermediary output files (say hundreds), the size of the hash table is too small. Rerunning Jellyfish with a larger size (option -s) is probably faster than merging all the intermediary files.

Orientation

When the orientation of the sequences in the input fasta file is not known, e.g. in sequencing reads, using --both-strands (-C) makes the most sense.

For any k-mer m, its canonical representation is m itself or its reverse-complement, whichever comes first lexicographically. With the option -C, only the canonical representation of the mers are stored in the hash and the count value is the number of occurrences of both the mer and its reverse-complement.

Choosing the hash size

To achieve the best performance, a minimum number of intermediary files should be written to disk. So the parameter -s should be chosen to fit as many k-mers as possible (ideally all of them) while still fitting in memory.

We consider to examples: counting mers in sequencing reads and in a finished genome.

First, suppose we count k-mers in short sequencing reads: there are n reads and there is an average of 1 error per reads where each error generates k unique mers. If the genome size is G, the size of the hash (option -s) to fit all k-mers at once is estimated to: $(G + k*n)/0.8$. The division by 0.8 compensates for the maximum usage of approximately $80%$ of the hash table.

On the other hand, when counting k-mers in an assembled sequence of length G, setting -s to G is appropriate.

As a matter of convenience, Jellyfish understands ISO suffixes for the size of the hash. Hence '-s 10M' stands 10 million entries while '-s 50G' stands for 50 billion entries.

The actual memory usage of the hash table can be computed as follow. The actual size of the hash will be rounded up to the next power of 2: s=2^l. The parameter r is such that the maximum reprobe value (-p) plus one is less than 2^r. Then the memory usage per entry in the hash is (in bits, not bytes) 2k-l+r+1. The total memory usage of the hash table in bytes is: 2^l*(2k-l+r+1)/8.

Choosing the counting field size

To save space, the hash table supports variable length counter, i.e. a k-mer occurring only a few times will use a small counter, a k-mer occurring many times will used multiple entries in the hash.

Important: the size of the couting field does NOT change the result, it only impacts the amount of memory used. In particular, there is no maximum value in the hash. Even if the counting field uses 5 bits, a k-mer occuring 2 million times will have a value reported of 2 million (i.e., it is not capped at 2^5).

The -c specify the length (in bits) of the counting field. The trade off is as follows: a low value will save space per entry in the hash but can potentially increase the number of entries used, hence maybe requiring a larger hash.

In practice, use a value for -c so that most of you k-mers require only 1 entry. For example, to count k-mers in a genome, where most of the sequence is unique, use -c1 or -c2. For sequencing reads, use a value for -c large enough to counts up to twice the coverage. For example, if the coverage is 10X, choose a counter length of 5 (-c5) as $2^5 > 20$.

Subcommands and options

count

Usage: jellyfish count [options] file:path+

Count k-mers or qmers in fasta or fastq files

Options (default value in (), *required):

-m, --mer-len=uint32
*Length of mer
-s, --size=uint64
*Hash size
-t, --threads=uint32
Number of threads (1)
-o, --output=string
Output prefix (mer_counts)
-c, --counter-len=Length
in bits Length of counting field (7)
--out-counter-len=Length
in bytes Length of counter field in output (4)
-C,--both-strands
Count both strand, canonical representation (false)
-p, --reprobes=uint32
Maximum number of reprobes (62)
-r,--raw
Write raw database (false)
-q,--quake
Quake compatibility mode (false)
--quality-start=uint32
Starting ASCII for quality values (64)
--min-quality=uint32
Minimum quality. A base with lesser quality becomes an N (0)
-L, --lower-count=uint64
Don't output k-mer with count < lower-count
-U, --upper-count=uint64
Don't output k-mer with count > upper-count
--matrix=Matrix
file Hash function binary matrix
--timing=Timing
file Print timing information
--stats=Stats
file Print stats
--usage
Usage
-h,--help
This message
--full-help
Detailed help
-V,--version
Version

stats

Usage: jellyfish stats [options] db:path

Statistics

Display some statistics about the k-mers in the hash:

Unique: Number of k-mers which occur only once. Distinct: Number of k-mers, not counting multiplicity. Total: Number of k-mers, including multiplicity. Max_count: Maximum number of occurrence of a k-mer.

Options (default value in (), *required):

-L, --lower-count=uint64
Don't consider k-mer with count < lower-count
-U, --upper-count=uint64
Don't consider k-mer with count > upper-count
-v,--verbose
Verbose (false)
-o, --output=string
Output file
--usage
Usage
-h,--help
This message
--full-help
Detailed help
-V,--version
Version

histo

Usage: jellyfish histo [options] db:path

Create an histogram of k-mer occurrences

Create an histogram with the number of k-mers having a given count. In bucket 'i' are tallied the k-mers which have a count 'c' satisfying 'low+i*inc <= c < low+(i+1)*inc'. Buckets in the output are labeled by the low end point (low+i*inc).

The last bucket in the output behaves as a catchall: it tallies all k-mers with a count greater or equal to the low end point of this bucket.

Options (default value in (), *required):

-l, --low=uint64
Low count value of histogram (1)
-h, --high=uint64
High count value of histogram (10000)
-i, --increment=uint64
Increment value for buckets (1)
-t, --threads=uint32
Number of threads (1)
-f,--full
Full histo. Don't skip count 0. (false)
-o, --output=string
Output file
-v,--verbose
Output information (false)
--usage
Usage
--help
This message
--full-help
Detailed help
-V,--version
Version

dump

Usage: jellyfish dump [options] db:path

Dump k-mer counts

By default, dump in a fasta format where the header is the count and the sequence is the sequence of the k-mer. The column format is a 2 column output: k-mer count.

Options (default value in (), *required):

-c,--column
Column format (false)
-t,--tab
Tab separator (false)
-L, --lower-count=uint64
Don't output k-mer with count < lower-count
-U, --upper-count=uint64
Don't output k-mer with count > upper-count
-o, --output=string
Output file
--usage
Usage
-h,--help
This message
-V,--version
Version

merge

Usage: jellyfish merge [options] input:string+

Merge jellyfish databases

Options (default value in (), *required):

-s, --buffer-size=Buffer
length Length in bytes of input buffer (10000000)
-o, --output=string
Output file (mer_counts_merged.jf)
--out-counter-len=uint32
Length (in bytes) of counting field in output (4)
--out-buffer-size=uint64
Size of output buffer per thread (10000000)
-v,--verbose
Be verbose (false)
--usage
Usage
-h,--help
This message
-V,--version
Version

query

Usage: jellyfish query [options] db:path

Query from a compacted database

Query a hash. It reads k-mers from the standard input and write the counts on the standard output.

Options (default value in (), *required):

-C,--both-strands
Both strands (false)
-c,--cary-bit
Value field as the cary bit information (false)
-i, --input=file
Input file
-o, --output=file
Output file
--usage
Usage
-h,--help
This message
-V,--version
Version

qhisto

Usage: jellyfish qhisto [options] db:string

Create an histogram of k-mer occurences

Options (default value in (), *required):

-l, --low=double
Low count value of histogram (0.0)
-h, --high=double
High count value of histogram (10000.0)
-i, --increment=double
Increment value for buckets (1.0)
-f,--full
Full histo. Don't skip count 0. (false)
--usage
Usage
--help
This message
-V,--version
Version

qdump

Usage: jellyfish qdump [options] db:path

Dump k-mer from a qmer database

By default, dump in a fasta format where the header is the count and the sequence is the sequence of the k-mer. The column format is a 2 column output: k-mer count.

Options (default value in (), *required):

-c,--column
Column format (false)
-t,--tab
Tab separator (false)
-L, --lower-count=double
Don't output k-mer with count < lower-count
-U, --upper-count=double
Don't output k-mer with count > upper-count
-v,--verbose
Be verbose (false)
-o, --output=string
Output file
--usage
Usage
-h,--help
This message
-V,--version
Version

qmerge

Usage: jellyfish merge [options] db:string+

Merge quake databases

Options (default value in (), *required):

-s, --size=uint64
*Merged hash table size
-m, --mer-len=uint32
*Mer length
-o, --output=string
Output file (merged.jf)
-p, --reprobes=uint32
Maximum number of reprobes (62)
--usage
Usage
-h,--help
This message
--full-help
Detailed help
-V,--version
Version

cite

Usage: jellyfish cite [options]

How to cite Jellyfish's paper

Citation of paper

Options (default value in (), *required):

-b,--bibtex
Bibtex format (false)
-o, --output=string
Output file
--usage
Usage
-h,--help
This message
-V,--version
Version

Version

Version: 1.1.4 of 2010/10/1

Bugs

  • jellyfish merge has not been parallelized and is relatively slow.
  • The hash table does not grow in memory automatically and jellyfish merge is not called automatically on the intermediary files (if any).

Copyright & License

Copyright
© 2010, Guillaume Marcais guillaume@marcais.net and Carl Kingsford carlk@umiacs.umd.edu.

License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Authors

Guillaume Marcais
University of Maryland
gmarcais@umd.edu

Carl Kingsford
University of Maryland
carlk@umiacs.umd.edu

Jellyfish-2.2.8/doc/jellyfish.man000066400000000000000000000347171323712541700167300ustar00rootroot00000000000000'\" t .\" Manual page created with latex2man on Wed Feb 29 10:58:48 EST 2012 .\" NOTE: This file is generated, DO NOT EDIT. .de Vb .ft CW .nf .. .de Ve .ft R .fi .. .TH "JELLYFISH" "1" "2010/10/1" "k\-mer counter " "k\-mer counter " .SH NAME .PP Jellyfish is a software to count k\-mers in DNA sequences. .PP .SH SYNOPSIS jellyfish count [\fB\-o\fP\fIprefix\fP] [\fB\-m\fP\fImerlength\fP] [\fB\-t\fP\fIthreads\fP] [\fB\-s\fP\fIhashsize\fP] [\fB--both\-strands\fP] \fIfasta\fP [\fIfasta \&... \fP] .br jellyfish merge \fIhash1\fP \fIhash2\fP \&... .br jellyfish dump \fIhash\fP .br jellyfish stats \fIhash\fP .br jellyfish histo [\fB\-h\fP\fIhigh\fP] [\fB\-l\fP\fIlow\fP] [\fB\-i\fP\fIincrement\fP] \fIhash\fP .br jellyfish query \fIhash\fP .br jellyfish cite .br .PP Plus equivalent version for Quake mode: qhisto, qdump and qmerge\&. .PP .SH DESCRIPTION .PP Jellyfish is a k\-mer counter based on a multi\-threaded hash table implementation. .PP .SS COUNTING AND MERGING .PP To count k\-mers, use a command like: .PP .Vb jellyfish count \-m 22 \-o output \-c 3 \-s 10000000 \-t 32 input.fasta .Ve .PP This will count the the 22\-mers in input.fasta with 32 threads. The counter field in the hash uses only 3 bits and the hash has at least 10 million entries. .PP The output files will be named output_0, output_1, etc. (the prefix is specified with the \fB\-o\fP switch). If the hash is large enough (has specified by the \fB\-s\fP switch) to fit all the k\-mers, there will be only one output file named output_0. If the hash filled up before all the mers were read, the hash is dumped to disk, zeroed out and reading in mers resumes. Multiple intermediary files will be present on the disks, named output_0, output_1, etc. .PP To obtain correct results from the other sub\-commands (such as histo, stats, etc.), the multiple output files, if any, need to be merged into one with the merge command. For example with the following command: .PP .Vb jellyfish merge \-o output.jf output\\_* .Ve .PP Should you get many intermediary output files (say hundreds), the size of the hash table is too small. Rerunning Jellyfish with a larger size (option \fB\-s\fP) is probably faster than merging all the intermediary files. .PP .SS ORIENTATION When the orientation of the sequences in the input fasta file is not known, e.g. in sequencing reads, using \fB--both\-strands\fP (\fB\-C\fP) makes the most sense. .PP For any k\-mer m, its canonical representation is m itself or its reverse\-complement, whichever comes first lexicographically. With the option \fB\-C\fP, only the canonical representation of the mers are stored in the hash and the count value is the number of occurrences of both the mer and its reverse\-complement. .PP .SS CHOOSING THE HASH SIZE .PP To achieve the best performance, a minimum number of intermediary files should be written to disk. So the parameter \fB\-s\fP should be chosen to fit as many k\-mers as possible (ideally all of them) while still fitting in memory. .PP We consider to examples: counting mers in sequencing reads and in a finished genome. .PP First, suppose we count k\-mers in short sequencing reads: there are n reads and there is an average of 1 error per reads where each error generates k unique mers. If the genome size is G, the size of the hash (option \fB\-s\fP) to fit all k\-mers at once is estimated to: $(G + k*n)/0.8$. The division by 0.8 compensates for the maximum usage of approximately $80%$ of the hash table. .PP On the other hand, when counting k\-mers in an assembled sequence of length G, setting \fB\-s\fP to G is appropriate. .PP As a matter of convenience, Jellyfish understands ISO suffixes for the size of the hash. Hence \&'\-s 10M\&' stands 10 million entries while \&'\-s 50G\&' stands for 50 billion entries. .PP The actual memory usage of the hash table can be computed as follow. The actual size of the hash will be rounded up to the next power of 2: s=2^l\&. The parameter r is such that the maximum reprobe value (\fB\-p\fP) plus one is less than 2^r\&. Then the memory usage per entry in the hash is (in bits, not bytes) 2k\-l+r+1\&. The total memory usage of the hash table in bytes is: 2^l*(2k\-l+r+1)/8\&. .PP .SS CHOOSING THE COUNTING FIELD SIZE To save space, the hash table supports variable length counter, i.e. a k\-mer occurring only a few times will use a small counter, a k\-mer occurring many times will used multiple entries in the hash. .PP Important: the size of the couting field does NOT change the result, it only impacts the amount of memory used. In particular, there is no maximum value in the hash. Even if the counting field uses 5 bits, a k\-mer occuring 2 million times will have a value reported of 2 million (i.e., it is not capped at 2^5). .PP The \fB\-c\fP specify the length (in bits) of the counting field. The trade off is as follows: a low value will save space per entry in the hash but can potentially increase the number of entries used, hence maybe requiring a larger hash. .PP In practice, use a value for \fB\-c\fP so that most of you k\-mers require only 1 entry. For example, to count k\-mers in a genome, where most of the sequence is unique, use \fB\-c\fP\fI1\fP or \fB\-c\fP\fI2\fP\&. For sequencing reads, use a value for \fB\-c\fP large enough to counts up to twice the coverage. For example, if the coverage is 10X, choose a counter length of 5 (\fB\-c\fP\fI5\fP) as $2^5 > 20$. .PP .SH SUBCOMMANDS AND OPTIONS .SS COUNT Usage: jellyfish count [options] file:path+ .PP Count k\-mers or qmers in fasta or fastq files .PP Options (default value in (), *required): .TP \fB\-m\fP, \fB--mer\-len\fP\fI=uint32\fP *Length of mer .TP \fB\-s\fP, \fB--size\fP\fI=uint64\fP *Hash size .TP \fB\-t\fP, \fB--threads\fP\fI=uint32\fP Number of threads (1) .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output prefix (mer_counts) .TP \fB\-c\fP, \fB--counter\-len\fP\fI=Length\fP in bits Length of counting field (7) .TP \fB--out\-counter\-len\fP\fI=Length\fP in bytes Length of counter field in output (4) .TP \fB\-C\fP,\fB--both\-strands\fP Count both strand, canonical representation (false) .TP \fB\-p\fP, \fB--reprobes\fP\fI=uint32\fP Maximum number of reprobes (62) .TP \fB\-r\fP,\fB--raw\fP Write raw database (false) .TP \fB\-q\fP,\fB--quake\fP Quake compatibility mode (false) .TP \fB--quality\-start\fP\fI=uint32\fP Starting ASCII for quality values (64) .TP \fB--min\-quality\fP\fI=uint32\fP Minimum quality. A base with lesser quality becomes an N (0) .TP \fB\-L\fP, \fB--lower\-count\fP\fI=uint64\fP Don\&'t output k\-mer with count < lower\-count .TP \fB\-U\fP, \fB--upper\-count\fP\fI=uint64\fP Don\&'t output k\-mer with count > upper\-count .TP \fB--matrix\fP\fI=Matrix\fP file Hash function binary matrix .TP \fB--timing\fP\fI=Timing\fP file Print timing information .TP \fB--stats\fP\fI=Stats\fP file Print stats .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB--full\-help\fP Detailed help .TP \fB\-V\fP,\fB--version\fP Version .PP .SS STATS Usage: jellyfish stats [options] db:path .PP Statistics .PP Display some statistics about the k\-mers in the hash: .PP Unique: Number of k\-mers which occur only once. Distinct: Number of k\-mers, not counting multiplicity. Total: Number of k\-mers, including multiplicity. Max_count: Maximum number of occurrence of a k\-mer. .PP Options (default value in (), *required): .TP \fB\-L\fP, \fB--lower\-count\fP\fI=uint64\fP Don\&'t consider k\-mer with count < lower\-count .TP \fB\-U\fP, \fB--upper\-count\fP\fI=uint64\fP Don\&'t consider k\-mer with count > upper\-count .TP \fB\-v\fP,\fB--verbose\fP Verbose (false) .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB--full\-help\fP Detailed help .TP \fB\-V\fP,\fB--version\fP Version .PP .SS HISTO Usage: jellyfish histo [options] db:path .PP Create an histogram of k\-mer occurrences .PP Create an histogram with the number of k\-mers having a given count. In bucket \&'i\&' are tallied the k\-mers which have a count \&'c\&' satisfying \&'low+i*inc <= c < low+(i+1)*inc\&'\&. Buckets in the output are labeled by the low end point (low+i*inc). .PP The last bucket in the output behaves as a catchall: it tallies all k\-mers with a count greater or equal to the low end point of this bucket. .PP Options (default value in (), *required): .TP \fB\-l\fP, \fB--low\fP\fI=uint64\fP Low count value of histogram (1) .TP \fB\-h\fP, \fB--high\fP\fI=uint64\fP High count value of histogram (10000) .TP \fB\-i\fP, \fB--increment\fP\fI=uint64\fP Increment value for buckets (1) .TP \fB\-t\fP, \fB--threads\fP\fI=uint32\fP Number of threads (1) .TP \fB\-f\fP,\fB--full\fP Full histo. Don\&'t skip count 0. (false) .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file .TP \fB\-v\fP,\fB--verbose\fP Output information (false) .TP \fB--usage\fP Usage .TP \fB--help\fP This message .TP \fB--full\-help\fP Detailed help .TP \fB\-V\fP,\fB--version\fP Version .PP .SS DUMP Usage: jellyfish dump [options] db:path .PP Dump k\-mer counts .PP By default, dump in a fasta format where the header is the count and the sequence is the sequence of the k\-mer. The column format is a 2 column output: k\-mer count. .PP Options (default value in (), *required): .TP \fB\-c\fP,\fB--column\fP Column format (false) .TP \fB\-t\fP,\fB--tab\fP Tab separator (false) .TP \fB\-L\fP, \fB--lower\-count\fP\fI=uint64\fP Don\&'t output k\-mer with count < lower\-count .TP \fB\-U\fP, \fB--upper\-count\fP\fI=uint64\fP Don\&'t output k\-mer with count > upper\-count .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB\-V\fP,\fB--version\fP Version .PP .SS MERGE Usage: jellyfish merge [options] input:string+ .PP Merge jellyfish databases .PP Options (default value in (), *required): .TP \fB\-s\fP, \fB--buffer\-size\fP\fI=Buffer\fP length Length in bytes of input buffer (10000000) .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file (mer_counts_merged.jf) .TP \fB--out\-counter\-len\fP\fI=uint32\fP Length (in bytes) of counting field in output (4) .TP \fB--out\-buffer\-size\fP\fI=uint64\fP Size of output buffer per thread (10000000) .TP \fB\-v\fP,\fB--verbose\fP Be verbose (false) .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB\-V\fP,\fB--version\fP Version .PP .SS QUERY Usage: jellyfish query [options] db:path .PP Query from a compacted database .PP Query a hash. It reads k\-mers from the standard input and write the counts on the standard output. .PP Options (default value in (), *required): .TP \fB\-C\fP,\fB--both\-strands\fP Both strands (false) .TP \fB\-c\fP,\fB--cary\-bit\fP Value field as the cary bit information (false) .TP \fB\-i\fP, \fB--input\fP\fI=file\fP Input file .TP \fB\-o\fP, \fB--output\fP\fI=file\fP Output file .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB\-V\fP,\fB--version\fP Version .PP .SS QHISTO Usage: jellyfish qhisto [options] db:string .PP Create an histogram of k\-mer occurences .PP Options (default value in (), *required): .TP \fB\-l\fP, \fB--low\fP\fI=double\fP Low count value of histogram (0.0) .TP \fB\-h\fP, \fB--high\fP\fI=double\fP High count value of histogram (10000.0) .TP \fB\-i\fP, \fB--increment\fP\fI=double\fP Increment value for buckets (1.0) .TP \fB\-f\fP,\fB--full\fP Full histo. Don\&'t skip count 0. (false) .TP \fB--usage\fP Usage .TP \fB--help\fP This message .TP \fB\-V\fP,\fB--version\fP Version .PP .SS QDUMP Usage: jellyfish qdump [options] db:path .PP Dump k\-mer from a qmer database .PP By default, dump in a fasta format where the header is the count and the sequence is the sequence of the k\-mer. The column format is a 2 column output: k\-mer count. .PP Options (default value in (), *required): .TP \fB\-c\fP,\fB--column\fP Column format (false) .TP \fB\-t\fP,\fB--tab\fP Tab separator (false) .TP \fB\-L\fP, \fB--lower\-count\fP\fI=double\fP Don\&'t output k\-mer with count < lower\-count .TP \fB\-U\fP, \fB--upper\-count\fP\fI=double\fP Don\&'t output k\-mer with count > upper\-count .TP \fB\-v\fP,\fB--verbose\fP Be verbose (false) .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB\-V\fP,\fB--version\fP Version .PP .SS QMERGE Usage: jellyfish merge [options] db:string+ .PP Merge quake databases .PP Options (default value in (), *required): .TP \fB\-s\fP, \fB--size\fP\fI=uint64\fP *Merged hash table size .TP \fB\-m\fP, \fB--mer\-len\fP\fI=uint32\fP *Mer length .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file (merged.jf) .TP \fB\-p\fP, \fB--reprobes\fP\fI=uint32\fP Maximum number of reprobes (62) .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB--full\-help\fP Detailed help .TP \fB\-V\fP,\fB--version\fP Version .PP .SS CITE Usage: jellyfish cite [options] .PP How to cite Jellyfish\&'s paper .PP Citation of paper .PP Options (default value in (), *required): .TP \fB\-b\fP,\fB--bibtex\fP Bibtex format (false) .TP \fB\-o\fP, \fB--output\fP\fI=string\fP Output file .TP \fB--usage\fP Usage .TP \fB\-h\fP,\fB--help\fP This message .TP \fB\-V\fP,\fB--version\fP Version .PP .SH VERSION .PP Version: 1.1.4 of 2010/10/1 .PP .SH BUGS .PP .TP .B * jellyfish merge has not been parallelized and is relatively slow. .TP .B * The hash table does not grow in memory automatically and jellyfish merge is not called automatically on the intermediary files (if any). .PP .SH COPYRIGHT & LICENSE .TP Copyright (C)2010, Guillaume Marcais \fBguillaume@marcais.net\fP and Carl Kingsford \fBcarlk@umiacs.umd.edu\fP\&. .PP .TP License 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. .br 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. .br You should have received a copy of the GNU General Public License along with this program. If not, see \fBhttp://www.gnu.org/licenses/\fP\&. .PP .SH AUTHORS Guillaume Marcais .br University of Maryland .br \fBgmarcais@umd.edu\fP .PP Carl Kingsford .br University of Maryland .br \fBcarlk@umiacs.umd.edu\fP .PP .\" NOTE: This file is generated, DO NOT EDIT. Jellyfish-2.2.8/doc/jellyfish.pdf000066400000000000000000007307261323712541700167310ustar00rootroot00000000000000%PDF-1.4 %ÐÔÅØ 1 0 obj << /S /GoTo /D (section.1) >> endobj 4 0 obj (1 Synopsis) endobj 5 0 obj << /S /GoTo /D (section.2) >> endobj 8 0 obj (2 Description) endobj 9 0 obj << /S /GoTo /D (subsection.2.1) >> endobj 12 0 obj (2.1 Counting and merging) endobj 13 0 obj << /S /GoTo /D (subsection.2.2) >> endobj 16 0 obj (2.2 Orientation) endobj 17 0 obj << /S /GoTo /D (subsection.2.3) >> endobj 20 0 obj (2.3 Choosing the hash size) endobj 21 0 obj << /S /GoTo /D (subsection.2.4) >> endobj 24 0 obj (2.4 Choosing the counting field size) endobj 25 0 obj << /S /GoTo /D (section.3) >> endobj 28 0 obj (3 Subcommands and options) endobj 29 0 obj << /S /GoTo /D (subsection.3.1) >> endobj 32 0 obj (3.1 count) endobj 33 0 obj << /S /GoTo /D (subsection.3.2) >> endobj 36 0 obj (3.2 stats) endobj 37 0 obj << /S /GoTo /D (subsection.3.3) >> endobj 40 0 obj (3.3 histo) endobj 41 0 obj << /S /GoTo /D (subsection.3.4) >> endobj 44 0 obj (3.4 dump) endobj 45 0 obj << /S /GoTo /D (subsection.3.5) >> endobj 48 0 obj (3.5 merge) endobj 49 0 obj << /S /GoTo /D (subsection.3.6) >> endobj 52 0 obj (3.6 query) endobj 53 0 obj << /S /GoTo /D (subsection.3.7) >> endobj 56 0 obj (3.7 qhisto) endobj 57 0 obj << /S /GoTo /D (subsection.3.8) >> endobj 60 0 obj (3.8 qdump) endobj 61 0 obj << /S /GoTo /D (subsection.3.9) >> endobj 64 0 obj (3.9 qmerge) endobj 65 0 obj << /S /GoTo /D (subsection.3.10) >> endobj 68 0 obj (3.10 cite) endobj 69 0 obj << /S /GoTo /D (section.4) >> endobj 72 0 obj (4 Version) endobj 73 0 obj << /S /GoTo /D (section.5) >> endobj 76 0 obj (5 Bugs) endobj 77 0 obj << /S /GoTo /D (section.6) >> endobj 80 0 obj (6 Copyright \046 License) endobj 81 0 obj << /S /GoTo /D (section.7) >> endobj 84 0 obj (7 Authors) endobj 85 0 obj << /S /GoTo /D [86 0 R /Fit ] >> endobj 88 0 obj << /Length 2072 /Filter /FlateDecode >> stream xÚ­XIsã¶¾ûWðHUYö%·É2¯Þ¤’z©¸r™Ì’(‹1%Ê"•‰óë_7¤(‰öØ5ñÁ„°t7zùðßÝÝ|ó^˜L8&…ÑÙÝ:“œ3§Bfµa¨ìn•}Ì?”uýôºÝ|;›knów³¹â2_mG­‡ù¶Ý} 6‚c$jP‚q)³¹ôÌA þÃ`),ù¹8,‹ªÅ./v+êý>þTíîÛusX¡Ø Ö íAŽbA$9ïg^æåâp,O$D†[Z,¹dŽ4™gÁÚ´_¶y$ã÷™·yyh«f+µÊL§¥v´Ô0\™äií»EÛŠe—f»Ñì¹0àQg’2;xv67*'÷ÎDÞn&ŒT– e2Nk¢À®?2o›u7“>ÿ<“!/% v R0|Þ›äGb}`NöR&ôÆ­è'`€“æjGÂøåu´åã±Ü-Ë–‘%2¡™ÒVÒÖm`VÛè+%ÒÖÅ >“ÎÒDÞ’fÝ~)± ¯Íö3@&2¶‰ý¦N<ãñ„-× <†ÌŸ¦Šƒ³l8§2Q‰Êvy¨ö:ü‹lâÃeø¯Í Lp}F»Ò® ôƒ#ì’I%UÓ(DÔÌEž;E[®¨ÙgLA?·˜IǺ«æp.—ŪŸS;NìŠE]RgµÝ×Xx1 tÆÈ•'>·’‰9 ìßøäIÖÓ²ïÑ:%òH7Èu&ñqhÀî±÷j›X`à Hš(ìnæa'ãÍ<ôÌ{ZÏ4¯w_{K2myæ¥e³Ý’‘ÐWWÀ¦пC˜³ÓÐ1cM4xØýŸxÏYWèS.XFV›@ÒâWÊô»¡osìöÇ~Î’¾*ýlé+8ý¥Þ4Y%AÕÖ³g¨D:ÑF—œº‰‰èMþ¹ªklÙ‘sã@·)©?5Ðìž½{CìFǪ“ÀnC-´Ž`¶«Ÿ[ÎAuy¡/f.ÌÇ *ëÕ¹üAû¿û `¢ØöI_?QðT*ˆªë‹®+ ¥~l¥4H¸[—t-…¦à4´_%¼&ãUº¯dSfÅÍj­‡c÷Y£¹Z÷þÇîEã4Wl±†ŒfÓ)‘«èIV Š?†dáÏe 6@F;bÖ:ï‘|8 pK”ŠÇå…D1NgÂy†ÿºD1VEIZº¿¤^qÉÇ׫W*Ì\¨I}à˜1øªë¹¿8ázz& ì‹®ˆ±xºå²£Þ:žÂðc}h¶Ô"Ç ‡*‘@_{\ÌKóÛ#áõDŒ„edg-bb× µ"Ðu=>Öòh9Y´ <SìYF1 ˆ }²¡ ÀójM½ÅŽ FveÌ‹UâÂ(],Ïû~BÊê4pË…ž=¹ÞÜ~5“c°L¼Àwjpý†Ê¿‹-•ÌHŠÊýâÉbÝÔuß{©(‰÷¢'#÷ôÚ/;yïFÌv¸æÂ  ³BXäNL=T¹0~5ü}g9Ýg¿¥Ër|¿¥öû8:¼½C½½7¼½cüIÌ" endstream endobj 86 0 obj << /Type /Page /Contents 88 0 R /Resources 87 0 R /MediaBox [0 0 612 792] /Parent 103 0 R >> endobj 89 0 obj << /D [86 0 R /XYZ 90.801 734.821 null] >> endobj 90 0 obj << /D [86 0 R /XYZ 91.801 696.959 null] >> endobj 2 0 obj << /D [86 0 R /XYZ 91.801 520.108 null] >> endobj 6 0 obj << /D [86 0 R /XYZ 91.801 370.137 null] >> endobj 10 0 obj << /D [86 0 R /XYZ 91.801 317.073 null] >> endobj 87 0 obj << /Font << /F15 91 0 R /F16 92 0 R /F25 93 0 R /F26 94 0 R /F27 95 0 R /F28 96 0 R /F31 97 0 R /F32 98 0 R /F8 99 0 R /F33 100 0 R /F11 101 0 R /F35 102 0 R >> /ProcSet [ /PDF /Text ] >> endobj 106 0 obj << /Length 3579 /Filter /FlateDecode >> stream xÚÍZݓ۶÷_¡—Nx͉@ =Ó‡&]g¦qß4I¦Ã“¨k‰”I*çË_ßý?t8Û÷Ö¹™#€‹Åb?~»Ð·7/¾y•d«".2“­nv«BǹÒ+gÒØ¦fu³]ý™Ø\­µR*zÛÕUseòh(‡ºm®ÖÆ©\G~øoß¿ûî§7ÿ¼yóöÇ«ßn~xñýÍ‹/ôJÁŸž(ë8Ë²Õæøâ—ßÔj c?¬TœùêžfWÖäô®V‡Õ»ÿzñ-q™>æ2˳¸(2æò¿Õáð°«ûýÕ:5it¬º»Š›ë–Ÿíy8‡ø¿»ùë¯:±ÿù3²ûÍ«|¶„¶qaíj ìÚñïöíù°½Z'ðõŠ¡=ãKÝU÷KƒAz«YVUw¬¶uÙ=ðdZ÷JG¿þª´=T=ñ«JU_ÎH쑹ÙvÕ¶‡A}Ý.öÝ×T<³Ýq Á§%Ê[Cy{ùµ,4€Lp¸ñÕÚoVÃfS‘g,‡øjåIôSÕ›¦nîXN‰™ *‡oò ‹¾ú¡:€tutxÀ}›q^Œóï똴:‰J~J8·ŽÛ¼9l¡\ÚÓPƒØ@혉d~Z4!O<Õuÿx]Щ$÷P”L‚ÏS×Þ‚˜øm •0¢ñô°Ë€\áliU eÁlÜ@¹“0u±Q‰H3åª$ÓÙë(–]éfgÔ\œçùÜ5b¢½!>Ú-|©ÑŠøÃŸ÷kÁ\R£}dÊØ¹»˜ÕWÎU³AMaqËñºâæ®ì‡’›¼-™Ñó³ieÞû¦ÅeïTe¥£*¾-³°O]%ã{W•Ûþš„«–R=÷“NÎÕÁdpnÔZa¢õ-ª~Ôûu?te³ (‰Ëbàd¦%*@=‰s—ŽÄ¿ ø«"Yê÷±|¦MÆžˆ©¿íÑ$¶ÞôU,F©ð”f¹ãWW9žÌN‹¨¤|`´ž³ˆ*8òøþ1‹i<íô9@Â$qj ?é2(gGãafàñ†žYÛ”MÛÔ›òÀ¯]uêª~©pØ_÷•µUsîA'f0,ZvLЋfd¤«~ÇE«®¯Ö›öx:TGaƒX΢û}½Á÷½Ÿè­Ø@¼°b €‡g•%ïðØðåP}¬7í]Wžö¸gð"¹Ðw¦Yô3{8%çÓÑ“ݘQ`³©þrݺ‚ 9®ù³À×ÐЗ»‹ï@z‘€Q±£‚H ìPgó4ê‡b·ÑpñÉ ¡Z`fØ€°•‡3ã™á9¿_˜ÊÃY>¦•g5š{>âÿ[ŠZè’q€B>©w³9w8«ù(Óû &žŒðÈÚð2!B—Í{ø¤ã.¼ãNÄq·fÁ×µä¹Ö‰ó ¹QjТÀ÷”O÷DoÈÀ©•t,ûZ8åN>S“x©‘¶Âë qlg×v€W6*‘M)Ãè±nê£Hœ:‚âÇÒXçqlÃÑ1¶áK/È § ¸ïêaÀàD ·!ñoëþ=FˆÜEï0þƒˆl.R³.:•]y¬ïÖ°@ÙX;û)X+¹btsžO$<ò‰/,ß-ˆÞ‡–Ÿ¸Ë9B¼€]ǧݲ§b&˜òy¿Ü/IŸX•û¾f@G ¤ªÞVät¨ƒ ~Dúo +)±UgIìã-°øÀƒÄ¢~¨‰@Â.nXO“„­£UuláAù8P-À£œÙÏ8,7mÓ‡½–‰WK´¤þ%*Ÿ\‚,'Žh±ðà Â<Ä&<ε¨Ì`5T2|W5àÂãš½ªÁ£)$`çIKØŒ@¨î½métæÂ§¬U¬’âY§Œ4ë†×%ìîšo‡hË ²Lѹv zåE+7ò@‰À¨Vã‘'Dy₳E)[D¤I Ï8sú"> PÄ]–˜€%:cM„§æGÕu¦¡yšü9¼ùÕ•i]š^r|~ô1&,2T! a¬†­} åqfÇ|àÜÔβ!Ò"zCŒ{ÍK¶GiKꥳ'PLªceF^Àfœ'v t1e @¦/П,i·ñnЀx|Æ‚‚²zL™Âù’JãÂégæK´`ËÏÑñiò8÷oƒ;÷i#Pú‘³ƒX6È!4q‹,Ä™eGlÁÙoydhÑdfÙ—‡‘䱚Žûõ¦0zæ¯C4Àªõ¥Uk»8PçfɃJT˜O¯ I¥XJ=îçùÇ_“œK„¤±˜ðò1»ld"G[p*ºñš¶­¯{Q+ð™ŽóìÂýßr$—<Ž<ÎuþÅø8rwÑôdõäèwmw™M•'ƒSÎ={¢„! Å‹äûÒa*Ð:¯¹úÓ|žˆ 6Ãu°˜")Z>Ä,Cé[Êl|…-ºPnîÁ­RÖaпÉÄEä ¹‘ybªµP/ý³ï+†p²èò¹½°¹ãç¡jî†}ðÌll²gù³ cö0„sô¤ˆíDî h–#A‡LA@*âÔ^¸É×AZ:iÕýL N] *À' بXÒú+Nõ/ùÚB¡$+XdÐgŠzœè¨[‚(—c}l,ÑÇç Q?P9‚:Þ¼{Ëäû3ÌË>VÒÏŠ É”Ð"N²bBu»MSýÎøq™Oö÷ÕZd¡Õ?¾’"„ç†zŨr֎ض«}%cÄv¢—ª×_yHééÍÌ5·á„;&ü4¶dG”Âém†3Œ¥Ôïí=•0™zçbÇi2E¡sÃV‰’‹„<ú›3G˜CzwíáÀ,”¯2avähRñ$©™{hKÌ•ôžÐ·‘´•xÁ—®E=ÙòËùÄO®áŠ“ÂŽ¦ú8pKâSªÔO>xš—!ÌCOˆ%T‹mâ¦È æ‘Jj•¤È@N+¶ÆjÙá!PŽUšC™&a¤foü~.R»eo4×§Ùl©‰5‹³G’$¾}9øVÅ’dTñÍ÷ˆšx>Jƒ Æ-==–TÚ1I4Îb!#•B¾>Q>Ì,$`ð9…±Hn—ØË8ÇáÜ3é¶©¸‹¶OȤdˆëÔØ:™¢ š" ={Rx6¶ˆA%àÄâòÂÈ~AÝ‘(Þ%CP*ªƒ}®yQ‹L„ûrކ°ÞþTR•1É}$v#¢vS$Æo¹ð*ÛQºØ©F' D¥öˆž«N¨ã #s†5 @X[÷Œ›ZfVa!%RtÇVÉ]uïÃ……³pK5ÔG¾Fs>Èh¤w•üN—®Üs±3•÷£­Ž“Ü>'Ífò—;Â>R½¤ž9Ó8ˆ©÷Œ÷­ÿ³­ÃPŸøÖ/_"DœÂw{ÞN*{ôÄd/ IoŽ£"0G¹¡ÂkÀXž¡?¤F‡ p’iˆ‘õ{G½Æ‘m+eq~ýñí ObŒP6ä=示ª‡M^Ë½æ ’à¼új>5ùtã8¯†áŸ¯ÔŽ Ú(]ªzgÑ›f¬tõæ|(I!Rå‹s8VK…¸‘º´ .•0’¡þù]‹•4Ѻ©š.‰.û=›°Ì¨w3Y?QE0ɹ㚳pð®–²…LE)?8¦CÓ5;Ó±rÏTl$;)6[*t~L9 ¼ˆfc“Í[{ïº8 È8íƒÇ\lð ÐÏ+'å™OÁÂk’·$»EÕÁîZÖGðÂå„,N]zqåXŠGô%l*ÁSb£›Ec@5ºpsØÁ]V,`7†¥ØWcg.*7û*xU κbßo*õ”LÈ&6õN~Ù2þNetçfÂ|ØFýºãøó–Ùg7fŒZ¨¾ÖçeøEWnýod`J"¿Íéù1¥ü fÊëøJ‚Ù£:Ñ=¿LzÀâ‚„¨¸p\¢MÊNµII 俬ò­ìã+‰@ùò“òè[·ø{‹„/xç”ÚAhÔrDd6]UöÕ±FÂò>U.ƒçÜp~¯,9#*Pƒ‰Œå„ û>Òn¦[³¹ñá\wã…\ÊøŸøøºÚÓ©>y¾DE§Ï¨_9ÌѱžÿAEù¥Ží5·_Ñèmwæ_¬A)®¹N ¦dü<ÿ´Ç endstream endobj 105 0 obj << /Type /Page /Contents 106 0 R /Resources 104 0 R /MediaBox [0 0 612 792] /Parent 103 0 R >> endobj 107 0 obj << /D [105 0 R /XYZ 90.801 734.821 null] >> endobj 14 0 obj << /D [105 0 R /XYZ 91.801 625.29 null] >> endobj 18 0 obj << /D [105 0 R /XYZ 91.801 519.237 null] >> endobj 22 0 obj << /D [105 0 R /XYZ 91.801 293.078 null] >> endobj 104 0 obj << /Font << /F36 108 0 R /F35 102 0 R /F8 99 0 R /F32 98 0 R /F33 100 0 R /F31 97 0 R /F11 101 0 R /F14 109 0 R /F10 110 0 R /F7 111 0 R >> /ProcSet [ /PDF /Text ] >> endobj 114 0 obj << /Length 1770 /Filter /FlateDecode >> stream xÚ­XYsÛ6~÷¯à[©ÔDàái2“8Í4ÉHN;“ä– ‹ )ʃÄ!¨2ŠbtID(wçÍ- %ÎÔóÕ“;rQÞ†H÷v (¹ÕK뤪“¾SK÷zI"ÈD50imâgä8^‰uÒdÔnj‚üi­I9I%“ÏJqߤ¥Xɵ³13c %j {ù©t/¦ð$J’Ãl ûäeÀ²–ÝÏ›t[ûôðÔ—ÆVìÙÅA¢1Å` ¨gÁ²ªEV¥ÿŠX~Œ€HX‡Õ¦Þ³?“Ê`êi€J5` %¼ºSoTùÁÃ#DYô“aºjrɵ[U¼l²á[–îɪÇ¢*ÈX 1G$Ü?ã¢_4õ®©Ç°ƒÓ½XVu™nïF°C&sfÅ®µ6kW ÉïÇdnJ÷Awõ¡{Aa1Åè{ÍêPO·V3„­ˆFĶÛÊ&c…Èß'Û² ‘.KT6Œ‰tC(ö¼ÕŌǮæúa¼¤hK>›¸·im ÇÅH3j='Ж.‘­ºÐ†“¾ÁAÛ:×þÞýI|¼sôÀ9‰ý©V‡o(;ê¥|_4@ïa{øªuÂ,DIÍ5ݧÙd|†ÞÏßóö|e£nQo< ¹jeŽÅ0;¡ulИÊÔPî×?•À¶²³H²-¶é2É´¥€Ä¨„VÈ"ß¹°N²JL¹a0 r×z!õÚ1V‹8Å#kQKÏËä1UÅJ’¯Nfº>iï óªWž:y80–âpŸŸeçV"Éù0”¡€·-è¯YÆÓÚ4DØtdWIÜÊy±’ ªï†Ûè’æ¾Åuß$_%2qˆ *'÷[²|‚zlÕ#IcFz›féŒè1úI#Êõ¸º: 13šØ€.Kk‰ï H”c>„« a?ÙœæR™)CpošŸ¿U ßšiÇÎ8Êþží=¦êL'-Œ{äQ÷òtÛwqŒí!êäã|»L·}¶K/$k¤å\a9_šÂ–Ø«ÅCj³ƹÊ&…(«_¿Rà@¿&¦N^uqÁÓaÆ{a¹hi™:]$3Ë®¶Uu‚XÀš•º½.¶¿˜ö^ôZýW϶öA4üáÎÜßÍ…«Ð٩ꀔ[»º?ÞÅ䥚íeãMëv³ÛéÊ÷Ÿa,àôÿòÙ\~àó ½ªZ‡­Àh³‚ûPD&xŸÀö8âLa¸ëOÏ/{rÇbÄcÖ]:åíCóC0\OšíÒv%9˜l“Ò¨¾õak¢(&0×iÞŽCÌ&ü®!-zrƒj £awf}Ìïa"íÚ2c”¢\w×ñVJ÷ç{³€ž<Ö>}áöÆü|Þ‰Eà  "G€í›@ )âE½‘—Þ‘C%òÑÚ¼é„öú™jÞ´´Ùn”0˜·™°ØØZr¨rSvô–QÖM–MXâ…¬õ⵨“4fèëvìu@½gxŽ[—¾é*Xµ$üýÂQµåï£:Q`†L¡j ˆàö¤„þYÖû{¡ñòHw×ùˆ†1Ü‚ÎRKg …G.\t;ÕÏoÔÛÛ²ÑI+4V¯B—ÂmÌÞœþïµ#A endstream endobj 113 0 obj << /Type /Page /Contents 114 0 R /Resources 112 0 R /MediaBox [0 0 612 792] /Parent 103 0 R >> endobj 115 0 obj << /D [113 0 R /XYZ 90.801 734.821 null] >> endobj 26 0 obj << /D [113 0 R /XYZ 91.801 657.537 null] >> endobj 30 0 obj << /D [113 0 R /XYZ 91.801 629.44 null] >> endobj 112 0 obj << /Font << /F36 108 0 R /F8 99 0 R /F33 100 0 R /F32 98 0 R /F7 111 0 R /F11 101 0 R /F31 97 0 R /F37 116 0 R >> /ProcSet [ /PDF /Text ] >> endobj 119 0 obj << /Length 1604 /Filter /FlateDecode >> stream xÚÍXmsÓ8þÞ_áou –%ËvnæJ9 wÓ”/À7qQǶÜ^ÿý­´ò[âRÚáfn°^V»û¬vWO8™¼xÄ“D™¯œ„’اN„„‡3_:Ÿ]F‚™G}ßwk•ªzæ”3î2»x~qòúìÇß?žžÏ<Ƙ #œý5{öñ|öuþîàùÁ÷êøð‡öV(B8‹ÍÁ篾³„½wŽOX;·Frãð 6sßÉóƒ¿NŒÇÔ¡”$¡v°sYÄ‚$‰ºLƒÐº ¼xpúŽGAsœ üE^eÇ3óÐý6£n§Ý<‡ÑÝŸòz­ñ¿Æö¹Ü*YõWœ./·©ZkCF·quŸÃ!Y+¹¨§vOe½ÍÓY»w¨©Ö¦ËMfgýa3O/!ü±[6 çj¡k×Þ&«¬,v6×i½>ž²~QÈïÁE~l6Ú´U ž¬ð úµcƆžß®åBK¯­˜9´X4í±"¿kG‹ŒÌ¼¶«Ö¡ ¬²X(c–>hLÁ$anQ*\]˜5 §˜‘«dq5Bg³Àèmr%·¹\H…AŽ™ îˆ0pçz\ª4GBî;â3tÄŽ¾ö>o–Úª‘yÀ·ôŸý`¶!ø$‰X$ã ¦2K8 ¡ˆµ¦(¶ÐeSh?”Å>Htsƒ>váÓ€£!`Jù‰X8Ηþš« îÓL‡Èäæ ÉT¶aÉ ô?ô—Ù*…¸áÂÍ, Ý4o²qk9øKPû³*ûÞÈ*[êµc,lÆá8Iü ÃR` {ïíã[«Êv¬ø2‡¼;Cm¶(ϳ)—’„Äð„Ž]jo_¿jf¨¶f.z¡±f+6N­uvåÛ Ý ñÃ.Eæki«}“Õ÷ÚÁ#“VMžßc) IÄ;§™Jež-ÑZblÊž›ú´›E54©Éq¸“@½è˜“x‰OÂ,‰[’Á³¤¢Ê_EJPÙ#IÉë*K•í´i1PtU¥›q[ïÊ™ï¶ÿú‡š9EÍðjæ~Û` §ýs4|õ†ñ‚Óžßhu†/ݘ÷טAµWòÆô̧]Ç!š4÷­uæ²1ÄåÚÈ*”=”‡VUeZK“OÖÍ ~Ñù$¢!ÒSíbOšF‚+)~†-¦‡‹CÔšç­î“Þ°¯Àsù Ø®½|euØ)~ZAݽäsª{—>r°C.Ü“.¸¢¬·æq…/Æ}ëÚ½OŒˆ~–,÷̺2»ÔïF\³½LÂd…Å6_Êþ¹Ã—]KGåÌ;`’?ÌD»RkP³æ2£îp°§Zñ²í¤ kÉÎð~jÜIk<–ât‘*¼PHM¢(¶:07ÚcP‘fp þëNâÚ¤U6ÑÖ)Ü>L¯L­T(\VS˜í¤¹ q‰A}B¨ÛZV¶!óAèÀý*º†oè ïðIŒ­}hò=ƶÿ¬2A¢þMÿ!ma­ÔûaÌFüË@$Þm§/j„ô>†3x%vÂàÑ”Wë |øXªù§Ö5E#~¿û÷A(<æ;PdZL•m²{9¥Hˆàô‘˜Þ¶JïAÃÜUYM%pýwC© {ìMu€ÔªqYOÑ·˜<AaÁCPö~Möu¨Kmý„Ó~Hh´[«£!Cš¤xè‚ÿF“•&Ïy ßDÎ{ÏÝúZn'Ò‰¹>A ò ;¶Fÿ÷ìøé?†Fe©¸Iu‹ì¯ññ¿žDÕA—`@šèdV×·,ÏÌp˜X̧®­? »o1FÓÛ(²Ä^=Æ.%ÐŽpüÆì^VMZÝáJ˜­È |mÆ ÚÿêøN¦Œ endstream endobj 118 0 obj << /Type /Page /Contents 119 0 R /Resources 117 0 R /MediaBox [0 0 612 792] /Parent 103 0 R >> endobj 120 0 obj << /D [118 0 R /XYZ 90.801 734.821 null] >> endobj 34 0 obj << /D [118 0 R /XYZ 91.801 696.959 null] >> endobj 38 0 obj << /D [118 0 R /XYZ 91.801 421.596 null] >> endobj 117 0 obj << /Font << /F36 108 0 R /F31 97 0 R /F8 99 0 R /F33 100 0 R /F37 116 0 R /F32 98 0 R >> /ProcSet [ /PDF /Text ] >> endobj 123 0 obj << /Length 1258 /Filter /FlateDecode >> stream xÚÕW[OãF~ϯð[–ÌÎÕö n¥²[¤®`iEØ–‡LH¨g}Ñ_ß3íÄ"¡­J$2Ÿ3ß¹““éèÝ)‹‰dD£`º$A &ALâ‚Óyp2ÄÇ‚1çõz;žP³fnïòêäÃÅùù¯Ÿ?^Ž'ŒñVzÁ‹?¦¿_|¾ßL?~›Ž¾H€áCZ‚¢( n×£ëÌáݧ#&“àÑH®NóŒƒ,¸ý9:1³ŽÁ„D(ÆI%’2²OÀ6IÃÉRe[ ÿî4é¨0"IáL#;]®JkïZ•°"az§¬RhâÔàd$©è-ê,;€&йGû¨ªt•©¹El5úPN§õå¨A{3ª¢\å›}¼ÌLDƒ÷eœ°ž(#2$…N. IŒ„vŠÆ(Id7ß„ ›ï= †AZñ«v<žp.Âû1 •Ža–Áêé+&¼\Ú²°µ£½¾Î·ØSÞØÇùìx›VKcŽ6Ö¹hy¿&kU؃nóz3¦IX•C*'O Eh8W‹´Îª#ý5à°¿ÚèoH²}\¤eÕ,óbVvý¸T…²Ëj©¬ÆR¥scƒ>¥ì½¤­Qö1ÝÌw´Me©oµÚܺ½3Êæõ€[ùÂÆÁ CL@Ž:‡Vöí­ɳb¿ÖËÝöžÁº)öÔC"(­t^WÛºr õqg­‹¨g k¹ ›S+ú ì`7ÆB„iV;;M]Ë­ðEŽìÎaU¨¹Þ;è Ê‘ÄñNkÜúÖpŽìw5ß…:î¶Á±ö,Ò¬T}¨1Ý1}ôÊ£WélšSÄbßSÝ f°KµM‹´Ê‹6lÏ»£,|3ëÎ<|–ëÁðh§ÃÄä –•;)Ä#oÓûzµ©">`:ÌT*ýìÊ7?TÝi[S›sâqU-w Æ÷g» FÂÞ£þ§4« DcokÏkbH€ïDýÊ»]ouo¿ìs„¨ oå³¶Û·ÆAŸ±»ÆBç°ò”1D²ãiî=u&ìû&"„Ië[Y«ÍÝ€o %‚7b‡ô¤ÎiOJ”IÒ^]z®ìÁ½l`®Ê„êÄúÕ¼„cU¾7›& › ǦP.CÑrtú:6µg Ñéj£§·­€Ÿ†¨ä¼U½WYÖ'éFXZªAjýOG|éó5«Áb­T®þV½Ã$¾Èߟ8ñRŠ¡.âF0S›»¦‹Ïüš;GX8Ó]ûT)ç¿%dnÃí$$ }AÖ‡æ9YLvZà;ö»OÑÚ¨O§‰DJ›&p~ö¢¼˜Èþ5½k•NÌIvŽö/r}hF1\Å@3ÊPÌxÚ´ÏÝCã$<”Š¡BèÙ¹iéªêg˜tˆìq£/qÎY§unšVòhìíTaC;ÀŸº |‚U6ï6c—ÂlÖùÁÂÔDDäaÏ_jB¸`èµd{©ÏêuW—sûíÕjs-.àvþŠÆƒ+–»Dû°Ë 3s¯ÈK5H ¼'ª‚£ßZï_^+íaý1ðö+þ‡Û’ª ð›“X¡ârI·}A"†I(œ•´;…b¸ËÀÇ —‰$„¢EüÈ®OÍÛYQ§Å“ݡҼŠC ³·Yÿ5¶BÝ endstream endobj 122 0 obj << /Type /Page /Contents 123 0 R /Resources 121 0 R /MediaBox [0 0 612 792] /Parent 103 0 R >> endobj 124 0 obj << /D [122 0 R /XYZ 90.801 734.821 null] >> endobj 42 0 obj << /D [122 0 R /XYZ 91.801 631.268 null] >> endobj 46 0 obj << /D [122 0 R /XYZ 91.801 377.767 null] >> endobj 121 0 obj << /Font << /F36 108 0 R /F33 100 0 R /F8 99 0 R /F31 97 0 R /F37 116 0 R /F32 98 0 R >> /ProcSet [ /PDF /Text ] >> endobj 127 0 obj << /Length 1313 /Filter /FlateDecode >> stream xÚµXKsœ8¾Ï¯à¶°e$@€«rXÛëZ§6ñ¦<ÎÅñ‡˜1¸üï·¥X3޳IÊeêî¯_Ÿz|²\¼9÷¹•„3n-×VBIìQ+b! Bf-sëÆö w\êyžýЋæÉqõBßöõæÕõÉéåû÷|8»r\ß÷mXÉE`_þ³¼¸üpåÜ.ß-þ\.Ôòà‡î­PÂ9·²íâæÖ³rx÷ÎòˆŸÄÖ£:¹µ«gÏ*­«ÅÇʼnBL-JIJ€29I>†LY¨!‚7çñÈOÏr)hŽ<ݦwâØqƒ ´¿8Ô m—%¬ž>{4h7èö_:ySﺢ®Ú[|ÌWÇ»´ÛHCJ·‚‡º?î…ÖM½EM)ndõv—fȵ–´KWi+^P„¡BnoÒvC7¦ž}ÑáV#Ò¼ÅC÷îV4-n£]¹Ûmnµ]Zåi“ãvQíúN+¯r<ñؘH…v&ãR÷—Êa‘Ýi[u…"»‰_ê¾{dòJgîÊñøì…^.Öi_v¸ñÕ‘Ë^àcQíÏÁ/=ÂàþÞˆ‡¾hD.÷Ž1ù¾?Ê> HâE`8!¯1¹§G.x—0Û]f×ÝÆm»¼hŸ×OâŸG^ÉžÀYD2(Ö:-[!qÌÀpµ‰ƒÇFf`dió䮊î¹u’ØÿäÄþ(&²^E© *ÕHTUÁ¥C-JÅê]Q­ëò¶•¹M»–uõJÈaðcQ¡T4’ 8 x0À+—⹓ ”²x8v:x8LáDœx Óx¨T@Xv3ˆB£ìuˆLÜ/QÛ7 Å!á~2 ‘†ÓKÒyn% r9X¹Þš*ÖÇ&Š7ÆÕ(w3ªâ…É z¹)tŸmE{Ð ŠLCúÉØùê@§Ï@ÏΖ)ÃIŽNiÜM<Ê䱈D±¹z¢ÇlW$òïäqTv€È¡‡‹ênŽ·N_;ÝI©î¥ê®I·¸]¯ñSÑ/žC,¶³¬oD•‰vNñÿ`=ìNð쇉¯4Ù,k™ÎÇ™ñ9‰BSúoóº_Íu´6èpìïÚÇ[V÷•|œ÷iÛ$šÆEO¦‘ÈÅ!"ŠI€,¦e:j‡ân3ÇD Ãðu^ §þ’ªôåÝã-h<âÆ£`Þ#L®›“§îåÑJ–öˆR¸'èÈjm\Z÷Тs<ȸAx.ÙCžÛ•È>쳺úMcnï‹Ý87¦Ú<‚œðÍ MÖÑ/ãëÉÚöLØ8¯™¢QÍ”t:cÊr†uñ#Ó«Kõ`¥¿ƒˆ]Ú¤]ÝìÃ61#ÂbÙº ‰cM_DYŽšNsº’q)÷=js è8ÃQ¤9R퇱M %Á®ÏÕÛUÓã—Øa‰zÙ æïáÿÿõš)_ endstream endobj 126 0 obj << /Type /Page /Contents 127 0 R /Resources 125 0 R /MediaBox [0 0 612 792] /Parent 103 0 R >> endobj 128 0 obj << /D [126 0 R /XYZ 90.801 734.821 null] >> endobj 50 0 obj << /D [126 0 R /XYZ 91.801 696.959 null] >> endobj 54 0 obj << /D [126 0 R /XYZ 91.801 467.497 null] >> endobj 58 0 obj << /D [126 0 R /XYZ 91.801 259.898 null] >> endobj 125 0 obj << /Font << /F36 108 0 R /F31 97 0 R /F8 99 0 R /F33 100 0 R /F37 116 0 R /F32 98 0 R >> /ProcSet [ /PDF /Text ] >> endobj 131 0 obj << /Length 1050 /Filter /FlateDecode >> stream xÚíW[oÛ6~÷¯Ð[¥.âx)1ØÌÍŠ-Xêqú’æAŽéX‰l9º$Í~}y%¹ò’¶ƒ›¢Îå;ç|ü$Oç“ïßæqÀfÞ|åqˆ¼SQìÍ—Þ¥OB!ôï7¢¼Aˆ!¡Ü'v÷übúfvvöó»“ó $„øre³÷óßfï΃«ùéä—ùä~‚<(?¨KƒcÌ»ÞL.¯ ·”÷N=O¼Gm¹ñ"œèkèåÞùäÉTC&=È1ÃÄc œ3ƒ9üý(”ð8öüöÕ—(Ãë¢Ùªe­@ÉHq/R‚@ĨL¥Cü¸,šE.Œ]Ò3‹@qkuRl_Õ¦Ú¢©w^Gþ]€|À—3w³zmVN|kúƒÙ•0åÞ£úʱl#tæq¿öá0BåBnbj‹¿pÅ7» ÿ|å `9îUŽþ²tâß…ûÙº2»¡*Ú",ìsge~[êVù *KrÀ8ÙÃ_,m’U“ç2Q âÈUq"ê4ËÝÑrÃTÖgH‚¿_—“V—´Â|Õß,ËOZß:YÖ±öT¹/§¶Î_í{™QœÂ¾Ê8ßS!#›°¯*c´KwúeB’tDžßduª²õ üœÏ7KºÓsò•zÞòiᆼȵø4Â'(sB95V:ãª(7iýÂ÷)fH±Ñûýÿ}ªgÚTÙØÙ?Š·ÝY訊ôÄCÄD~lQâ>ïbÙgyÚ\¦8¶™ä&4ñåóDGfýVß]”MZ>™Ìõ­ØÇJ$|„Û›Ÿ“¨/ endstream endobj 130 0 obj << /Type /Page /Contents 131 0 R /Resources 129 0 R /MediaBox [0 0 612 792] /Parent 133 0 R >> endobj 132 0 obj << /D [130 0 R /XYZ 90.801 734.821 null] >> endobj 62 0 obj << /D [130 0 R /XYZ 91.801 551.567 null] >> endobj 66 0 obj << /D [130 0 R /XYZ 91.801 321.976 null] >> endobj 129 0 obj << /Font << /F36 108 0 R /F33 100 0 R /F37 116 0 R /F8 99 0 R /F31 97 0 R /F32 98 0 R >> /ProcSet [ /PDF /Text ] >> endobj 136 0 obj << /Length 1425 /Filter /FlateDecode >> stream xÚ­ËrÛ6ð®¯à©CÍD‚¯ôÙc'NÇ•ätÏãïË£«åèÏ·øq+â,t80ræû¾µÎF_¿;Öö>Zs£ÐzÒ”™%E¨aÇJ­Åè×Ñ…Ö‚[\2WúÕ0ÂüÐgQ䓴೿Œ#i«²Jе˜^‡=ýk „‚Ï—qèÚ·ã‰”ÒæŒ3亮]lñ+íëqWe—GÂˆè ‘‡ :äT?8Æ,’ãÕ.š]Eä\ö”ÆHÊS;9<0’EW.ˆ×4¿«t<ñ¸ZV{ÐÉ íL•c@îÔKë}Ÿ9¾lÙ÷qEVäEMv­ÆØJåâ2NS•&© QƹY$‘”*ëä^¥GÚ«Òá'6`ê$D`M8à„nkøš©Ë½‚ø•ÞÓªŽW©An P4¨ÔöàbW’&%9}3•I\ÇM]d`Á mQ`ãKÇ‹ b" ^w½ ƒt}ÈÏkÙ“sMñ|¥Ï…Ì‘!s ¶ gXä™:STç§ S¾ÑAÉÑÚZ•™Ú$&Y]ô®L•‰×7Çs’mL$<Ά’x" /À¤²‰•oRù²8Œ]nËd·ÇfPàÙ?Ñç6Y«¼2npÝ× P‹­b^xÎ XØ#ôJ,Á?´&=20Ü{)Ž Æƒ.ŽPÀÔ²€Êß$i78S×þ—ë81åêz} Nȼ jEìZ¾w±°\ ˜^ƒ¨ò–KW’¾ŒË”V¿$ù®ÚåfàÌÐíWÃxþx×dI¼®X“m˜Ú4':’ùNg*ˆäžÏ¼Ð7õhrí$z}‰’3ÏíÕ$¦±€¼?”Å®Œ3B»EnK¥SÛšêþâRa«{ Q¯!5q ¹[Õe²jjE[IM_pÙ´(‰*£ŠßŒ¹læ`C×äeÈê=-°.ŒjÐÙu¥qŸ¡e'…¦«IÜ~÷`*WÐ ¸o@â*MÖ¶®ÒöSü ¨öØ4\é2£u']ò@ í¡ óP¦s î‹Ó§ ˜j ã6Z8ödžzXg}«ÜÓ‘Öµ £¿gèݶKÄ5áL”JCq@U°e¥é!´ £@ 4´:lHÊ:_—;´Èçؘœ )Žs‡V-^ë‹”æûUI« šJm›íß„ýín-K’5»{4Ø1çÜžÍ''˜F8ŸÝ-BÁYõ¾Ð²Pd{N) ˆ$;¤‰6(Î%º/°ëÖ‡°£#à§«9n]~€c0 f7·7ËGCTÒ÷úfywµX¥|ž0rú=Þvfs·¼¹|¸Í)X÷óûÏ‹+FQ\(“&I$UbºJ@ྡ20i„¹H¥€ˆmaF­‘²Quœ¤Õ`:<¢fÔ ¤]/Ó ­÷1ZEEŒ5³VæÂahbÚXCF˜BòÙÒ— ¶©œó\δFàúÄ-8-ò-1­@jp^›¹ƒÝl»«Õ2¿Rj ¯Kh¿²kÑûº>¼NŸžžØ.oXQî¦)h5èïÀ,½óö~6Â9LOGžÎðÀÌðYi[VÿzKîMF´©7ÏÍ~È“®ò»¬v¥é;šõ˜>_°¼Ó3û’vf˜¾{u¼1ÐÅCNæèyÙþþ·!ŒLøÞ•Ýűw]××3ÏáÔP¹ïÂ+*|åö‚ Nûl ‚çg ^úõ³å ­¯õn÷^ ½W¼ {¯àÓìo2wŠ+ endstream endobj 135 0 obj << /Type /Page /Contents 136 0 R /Resources 134 0 R /MediaBox [0 0 612 792] /Parent 133 0 R >> endobj 137 0 obj << /D [135 0 R /XYZ 90.801 734.821 null] >> endobj 70 0 obj << /D [135 0 R /XYZ 91.801 696.959 null] >> endobj 74 0 obj << /D [135 0 R /XYZ 91.801 648.225 null] >> endobj 78 0 obj << /D [135 0 R /XYZ 91.801 561.024 null] >> endobj 82 0 obj << /D [135 0 R /XYZ 91.801 402.923 null] >> endobj 134 0 obj << /Font << /F36 108 0 R /F31 97 0 R /F8 99 0 R /F14 109 0 R /F32 98 0 R /F33 100 0 R /F35 102 0 R >> /ProcSet [ /PDF /Text ] >> endobj 138 0 obj [755.6 674.4 703.9 1044.7 1059.4 355.6 385 591.1 591.1 591.1 591.1 591.1 948.9 532.2 665 826.7 826.7 591.1 1022.8 1140.5 885.5 296.7 386.1 620.6 944.4 868.5 944.4 885.5 355.6 473.3 473.3 591.1 885.5 355.6 414.4 355.6 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 591.1 355.6 355.6 386.1 885.5 591.1 591.1 885.5 865.5 816.7 826.7 875.5 756.7 727.2 895.3 896.1 471.7 610.6 895 697.8 1072.8 896.1 855 787.2 855 859.4 650 796.1 880.8 865.5 1160 865.5 865.5 708.9 356.1 620.6 356.1 591.1 355.6 355.6 591.1 532.2 532.2 591.1 532.2 400 532.2 591.1 355.6 355.6 532.2 296.7 944.4 650 591.1 591.1 532.2 501.7 486.9 385 620.6 532.2 767.8 560.6] endobj 139 0 obj [569.5] endobj 140 0 obj [361.3 1013.7 706.2 563.9 588.9 523.6 530.4] endobj 141 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500] endobj 142 0 obj [277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8] endobj 143 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 144 0 obj [277.8 277.8 777.8 500 777.8 500 530.9 750 758.5 714.7 827.9 738.2 643.1 786.3 831.3 439.6 554.5 849.3 680.6 970.1 803.5 762.8 642 790.6 759.3 613.2 584.4 682.8 583.3 944.4 828.5 580.6 682.6 388.9 388.9 388.9 1000 1000 416.7 528.6 429.2 432.8 520.5 465.6 489.6 477 576.2 344.5 411.8 520.6 298.4 878 600.2 484.7 503.1 446.4 451.2 468.8] endobj 145 0 obj [670.8 638.9 638.9 958.3 958.3 319.4 351.4 575 575 575 575 575 869.4 511.1 597.2 830.6 894.4 575 1041.7 1169.4 894.4 319.4 350 602.8 958.3 575 958.3 894.4 319.4 447.2 447.2 575 894.4 319.4 383.3 319.4 575 575 575 575 575 575 575 575 575 575 575 319.4 319.4 350 894.4 543.1 543.1 894.4 869.4 818.1 830.6 881.9 755.6 723.6 904.2 900 436.1 594.4 901.4 691.7 1091.7 900 863.9 786.1 863.9 862.5 638.9 800 884.7 869.4 1188.9 869.4 869.4 702.8 319.4 602.8 319.4 575 319.4 319.4 559 638.9 511.1 638.9 527.1 351.4 575 638.9 319.4 351.4 606.9 319.4 958.3 638.9 575 638.9 606.9 473.6 453.6 447.2 638.9 606.9 830.6 606.9 606.9 511.1] endobj 146 0 obj [583.3 555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8 444.4] endobj 147 0 obj [562.2 587.8 881.7 894.4 306.7 332.2 511.1 511.1 511.1 511.1 511.1 831.3 460 536.7 715.6 715.6 511.1 882.8 985 766.7 255.6 306.7 514.4 817.8 769.1 817.8 766.7 306.7 408.9 408.9 511.1 766.7 306.7 357.8 306.7 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 306.7 306.7 306.7 766.7 511.1 511.1 766.7 743.3 703.9 715.6 755 678.3 652.8 773.6 743.3 385.6 525 768.9 627.2 896.7 743.3 766.7 678.3 766.7 729.4 562.2 715.6 743.3 743.3 998.9 743.3 743.3 613.3 306.7 514.4 306.7 511.1 306.7 306.7 511.1 460 460 511.1 460 306.7 460 511.1 306.7 306.7 460 255.6 817.8 562.2 511.1 511.1 460 421.7 408.9 332.2 536.7 460 664.4 463.9 485.6 408.9] endobj 148 0 obj [625 625 937.5 937.5 312.5 343.7 562.5 562.5 562.5 562.5 562.5 849.5 500 574.1 812.5 875 562.5 1018.5 1143.5 875 312.5 342.6 581 937.5 562.5 937.5 875 312.5 437.5 437.5 562.5 875 312.5 375 312.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 312.5 312.5 342.6 875 531.2 531.2 875 849.5 799.8 812.5 862.3 738.4 707.2 884.3 879.6 419 581 880.8 675.9 1067.1 879.6 844.9 768.5 844.9 839.1 625 782.4 864.6 849.5 1162 849.5 849.5 687.5 312.5 581 312.5 562.5 312.5 312.5 546.9 625 500 625 513.3 343.7 562.5 625 312.5 343.7 593.7 312.5 937.5 625 562.5 625 593.7 459.5 443.8 437.5 625 593.7 812.5 593.7 593.7 500] endobj 149 0 obj [535.1] endobj 150 0 obj [577.2 603.4 905.1 918.2 314.8 341.1 524.7 524.7 524.7 524.7 524.7 850.9 472.2 550.9 734.6 734.6 524.7 906.2 1011.1 787 262.3 314.8 527.8 839.5 786.1 839.5 787 314.8 419.8 419.8 524.7 787 314.8 367.3 314.8 524.7 524.7 524.7 524.7 524.7 524.7 524.7 524.7 524.7 524.7 524.7 314.8 314.8 314.8 787 524.7 524.7 787 763 722.5 734.6 775 696.3 670.1 794.1 763 395.7 538.9 789.2 643.8 920.4 763 787 696.3 787 748.8 577.2 734.6 763 763 1025.3 763 763 629.6 314.8 527.8 314.8 524.7 314.8 314.8 524.7 472.2 472.2 524.7 472.2 314.8 472.2 524.7 314.8 314.8 472.2 262.3 839.5 577.2 524.7 524.7 472.2 432.9 419.8 341.1 550.9 472.2 682.1 473.8 498.5] endobj 151 0 obj [892.9 840.9 854.6 906.6 776.5 743.7 929.9 924.4 446.3 610.8 925.8 710.8 1121.6 924.4 888.9 808 888.9 886.7 657.4 823.1 908.6 892.9 1221.6 892.9 892.9 723.1 328.7 617.6 328.7 591.7 328.7 328.7 575.2 657.4 525.9 657.4 543 361.6 591.7 657.4 328.7 361.6 624.5 328.7 986.1 657.4 591.7 657.4 624.5 488.1 466.8 460.2] endobj 152 0 obj [342.6 285.5 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 285.5 285.5 285.5 799.4 485.3 485.3 799.4 770.7 727.9 742.3 785 699.4 670.8 806.5 770.7 371 528.1 799.2 642.3 942 770.7 799.4 699.4 799.4 756.5 571 742.3 770.7 770.7 1056.2 770.7 770.7 628.1 285.5 513.9 285.5 513.9 285.5 285.5 513.9 571 456.8 571 457.2 314 513.9 571 285.5 314 542.4 285.5 856.5 571 513.9 571 542.4 402 405.4 399.7 571 542.4 742.3] endobj 153 0 obj [272 326.4 272 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 272 761.6 462.4 462.4 761.6 734 693.4 707.2 747.8 666.2 639 768.3 734 353.2 503 761.2 611.8 897.2 734 761.6 666.2 761.6 720.6 544 707.2 734 734 1006 734 734 598.4 272 489.6 272 489.6 272 272 489.6 544 435.2 544 435.2 299.2 489.6 544 272 299.2 516.8 272 816 544 489.6 544 516.8 380.8 386.2 380.8 544 516.8 707.2 516.8 516.8] endobj 154 0 obj [499.3 499.3 748.9 748.9 249.6 275.8 458.6 458.6 458.6 458.6 458.6 693.3 406.4 458.6 667.6 719.8 458.6 837.2 941.7 719.8 249.6 249.6 458.6 772.1 458.6 772.1 719.8 249.6 354.1 354.1 458.6 719.8 249.6 301.9 249.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 249.6 249.6 249.6 719.8 432.5 432.5 719.8 693.3 654.3 667.6 706.6 628.2 602.1 726.3 693.3 327.6 471.5 719.4 576 850 693.3 719.8 628.2 719.8 680.5 510.9 667.6 693.3 693.3 954.5 693.3 693.3 563.1 249.6 458.6 249.6 458.6 249.6 249.6 458.6 510.9 406.4 510.9 406.4 275.8 458.6 510.9 249.6 275.8 484.7 249.6 772.1 510.9 458.6 510.9 484.7 354.1 359.4 354.1 510.9 484.7 667.6 484.7 484.7] endobj 155 0 obj << /Length1 1857 /Length2 13545 /Length3 0 /Length 14692 /Filter /FlateDecode >> stream xÚõPžËÒ† Á]ƒÃ‹»»»Kpwxqwwww—àî`ÁÝÝÝ-@‚ÖÚ²²¿ÿ¯:§¨‚çêîé¹{¦{ #RP¦2±3ŠÛÙ:Ó1Ñ3rDä„5˜ŒŒ,ôŒŒÌ°dd*ÎÖÀÿØaÉÔ€ŽNv¶ÜDˆ8 ?l¢†Îrv¶ik €‰›‰ƒ›‘ÀÌÈÈõŸ@;Gn€¨¡«… @Ž mg t‚%±³÷p´03wþØç?ŸJc*íßËB6@G cC[€œ¡³9ÐæcGcCk€²±ÐÙãRPòš;;Ûs30¸¹¹ÑÚ8ÑÛ9šñSÑÜ,œÍJ@' £+ÐðWÉyCà¿K£‡%¨˜[8ýË¡lgêìfè|¬-Œ¶NK\lM€Ž€ÝÊR²€/ö@ÛËþ+€ðïÃ0Ñ3ý7Ý¿Wÿ•ÈÂöïÅ†ÆÆv6ö†¶¶fS k à‹¸,½³»3-ÀÐÖä¯@Ck'»õ†®†Ö†FK7ˆ ) ?*üw}NÆŽöÎNôNÖÕÈðWšc³5±³±Ú:;Áþ¥OÔÂhüqî ÿ¾\+[;7[¯ÿ©…­‰é_e˜¸Ø3¨ÚZ8¸¥Dÿóa‚ýÇft°122r°s€ »±9Ã_¨xØÿv2ýeþ¨ÁÇËÞÎ`úQÐÇÂøñÖËÉÐpvtúxýéø_‚eb˜X;Œ€f¶°ÿdÿ0MÿÅ÷ïháÐfüh?&ã_?ÿýÒýè0;[kÂÿ¾bY)5u1 š—ü_§°°;À‹Ž@ÇÌÆ`bbgp||øüožÿžÀªÿÛª`hñoud”²5µpý«ˆÓûO!®ÿî Ê àw·ûèg €òŸö×adc4þøÅôÿyþ^òÿ¯÷ÿÊòÿÚþÿW‘¸‹µõß~Êüÿø m,¬=þñÑÏ.γ!g÷1!¶ÿ7Tø¯¶³6ù¿>)gà ²5³þï1Z8‰[¸M,œÍÿÕDÿ¹…äÖ¶@;'‹¿#ãÿñ}Ìœ±ÕÇ£âôqW»€#õ¿[ŠÙÛ™ü5{Ì÷nèèhèûqõÄðbúR ûß½ ` ·µsþXø(Î`jçûײsDþ2ýMìÍõ_âd0¨þC>µÿ×Ç:ÈÀ`ôqŒÿK¬¬ô1ÁÿDÿU'ƒÉÈ`þÌÓðÃiú2²ÌþÀìæÿìõ¡ØÜÃÞüã-û'âÃfñ~·ú?”[ÿÒmþØûCè©þÒb÷~µÿ?”9üÊÿÀNàÇi:ÿª\þÀU®à‡*·ùC•ûø¡ÊãüPåù7þO£»8:~<¢òGý‡ÿ~±@w 1ìÊ¢1O°eCð·ßuB¸nt“|sdêéTt^+Žß]ž¡R¨j³·„RFú×÷Ä(ïW _½ÎÚ› Â:’;Ÿ½_ô”f:a—§?NŸ 5àÃàÑ©z¿:x«X}jí–&ËwpáDT(DûíÖ/áÞ8P±6ºx xXË.÷R1K£­P:OV`”³€E éL‡MzíŽ4ÿ0‡š7õN(@ësÃR⥵Íû¸à¹Q¥ÂìÔƒMŠ­……ÿéu|†ÜKø8UsÉ«ìkôßR.GDÜðjp₌6±¯–cp9_–¿l7iOž›q–£µšñ”<€œ‚°Ú+„¬LÂ4©†d¤L?ÏÂïñ•_9QÔ„æ{/AÏù¥j7µwb7SÌѤ ÁÚnWŽ/ûË#$C¥áŒ„,DŠ)È&ɪü—ϳÊ>bJ#N1MÅ^Úïô_ÑY~² óþêl£³ÉÝçΉ©0ùl¤ÐtœtuñZÒo>¢Ý\‡~4¬ßž7íÌüÆ’ÔÂqL+ÅŒ)ŒxQ™Ã9,¾Å¸€nã„§ ¦>­ød¢qN„73 €8÷šÓuQ!°¦x‰zÎzTŠ’ŒÓ‹¤Ï°÷ÓŸžÀÈØç¼Ìå¶;ánUÅq)MÒÒ¶ÉÐc6lž[?ô[dMƒn¶¾cN\ø|à,ËëKN¨žRå&kÈe†ªÝë`¾£èŸ9™ÿ¹ÇÒµf†*äJשÞA‰øuºv(„ä%xكߚòø ¡%ã§ yà(žÅûKLº°á9“w{†^Þ÷¬Ü_m®ÎZVšFÚr®iÖùMÓUf¥ð;PÇ:CöZÑ!–W-QJh1çô‘Ëð”þ&ù©¸h+—‰ZgÉ£ «Uäˆs½ž·ge·V¡EO®|=üBÎ'lâkèärI¡UŽ®E~âÊÜ¢LçóÔ7ꙃpk6¸n8qqaõý'¦e¢·°bfêæs\Èù ÜhNnøŽ€[kÕJ¨¶`©Â;m·J0œÝqcr­#ƒRì™ò¼®Í:x'I ø×4ŠÏmÔN‡Ç³Ó*&\ó†ÛÅQÈ!«Ú±ã† ¤©f L/¦HP:Ç)PŒ'0†JSz(”™/²˜–($cD6n›Ì$¶cŽ;¤ÞQï3*¨²PÉIºÓ^•¥ïO¬ô)nh-UûkÞ ¿™…OÍÖ›Ü~Yõˆ×åÂÁÈW•šZòÄšÄ[Ó°ŸWâ÷™Æy=Þ£P?n^^¤aÏÀ¡Ñ*+î#2í,|®"§(³­ÆÖ1hÐUŒ â>FÜÝhïc·Æ¶e4â µÑýv}C{ưZV¢£IÊŽ£M *I2Ø-Wðåœaª^ôeG¶v·KçžzGð·' EéWòéö¯Á×Ìië‘Ýd4”)w™Vþ X¢[o Ã`)V”¨#‰±qVéÈöµˆÎz'Â?žÂ°vêu$|O5ÑôÊÇ›Þ0 ŸÑŒÉz|)щVa¥]—œ‘|Ò‡¸Ý§·½öòÙCQk&&“Pä‚3`~“+Òý°<¢ˆ Ì#oàhBiGIuÖÚz×qÄ÷ófK‘+mc#n ¤îªEêÆ?_=å­‹žLn¤í”ýijI“œp>Úõ½{ ôá,o$‡Ø±ï—9ɧÊ-mÁUŸãâÅ Ø©1jZ€e÷¡îá€+}¯³{;4F9ÌU¢•X¯¦uaíW“0z: 4ÜQãнH| ”ßW>Âr™½ÏÍ¢–¶µRÄèa¸ðë¢-Þ¿É¿„ÿ¸·â?¶ÈùÖ·rŽ ‚Žæ^}fÔîÒ'€û5t¦>q@›q¥Öî”ãÙ“òr dŒà׉ A0_8Èkl]>x5ÕBà©,"Ùjò©^6¦Œ<'uÜy ‡Pl]wZ#ØÚlþÓèw«D]MªEpÇ•{NŠ«þ­mɼüNÐþX¨o~ý-T(ް»-³±y#‹µ`%…Ÿ´|³DŽÒ`£TéÁÄ¢D:wXò |?þƒ¦ö—%T=ˆ¼h»O¸×Øö‰84“¨XtÐ#ßYüV_b¸±8 1XÉ-èG^yÅ}÷91ã™ìNh@ªJ,þÍ¿(Yë_Õ{öüxU¾fcË5ΔñDöë ÿ£\9 ´êbáü‘³%4ˀ܆Ǯç×àCÚ­ëVÁÃ'%ta þŸûÓg%Wçk®ájâ :BæVõvé-5ÛÈÙœà„`àWWÔ݃øòR8Š®¥\¬`žï¬K¿l¶œTø¢9§[FºC+¹Pï¼Wª”f÷Ë›”Å_˜Ó¢Ú_‹±Ö¾©ßŽ÷µ}=¿ê÷{Jà¯*¼[>ÁÑ:¢Ç·üÂ-¹FœþÓí3‹råuß›¢«Q—KwQ-`íc·Ó£¨†¯Êáó}÷7˜~fÂõ-ÅeBñòø™ÐÖêͱ—˜æÐ*ôØO–y_×X}Sâìàh¾#à·€ ‡ o©ôºƒ³säg ñ;ëÌQs jµ…Åú6ieÉæmTñ²¿£5 ý¿Q“ÖÚÚ¹ï°Èïû~ª‘vij÷F¿†¤›ªò`³¾EÅ4äb+BZ¶ÿL| nLˆ„4ë #4KÛ²Û\G "ÃWÅAïùfQRÞ¹N9Ÿ`¾?n_Êkì®*,¥ì4mg|ÿ‚¥=ž8©¯#«î<Æ;ÂÀÓßL|¨„Wm³ÑW“—EUóPŽž%«ã8¬Îß;7“h—\2â±·±B%<y­Ó%¸jp=%-`spXI¾ãdÕ[œÝEêžÍkÁ3|áâ€ß+në™öª)ÍB­Ô"jÒ7 s\µ^‰£¾êt ÌÂÊÝÇ[éXŽ,p†—5›…å¶5’† ’íèwˆÃIr<²dÓëçúT!¯¤Ö(tTÍÄØ¾·m ;ß™ªCÓLqv^ôK%XÇdl‹Úãu VwÖá)*û ¡ûRTAÐpkŠ5âæáá-‰^àuªêû™×º{ÜðMî"¤ËåÒim©}yIæ[ÿóä¿ødTZ¤k¢b؈%RÞ XâSM;Y®±ÿ'’â!ßæx¸´È±/‡Ÿ€`³ a†+ÊL™·SÀ0ÀaŸ8œ ‚“ž1ÖÉiˆG“[íÉ \:[ûÀˆõ 5ûë„K*! N‹gœ^h ×…y¯{L]¹ø(¢˜WZu»²ªAÍçƒbœ Ê¨wLæpÞ”%ûõ± Å‚>£,h¾è-'Ð]ȯPú¤ãûÀ-$ÑÿLP·¨Ä0,ž Æåu *À«ÄñÏÖúÄZ¸¼l¾’GžàwçÙD-õ Ï6fÈ—<žª¤!ˆ'¶9i¡ã˜†ÿœ«œÉ|õJ}3 –7Ïä Šœ„‘pÆîw²³‹vÓœâÄø³˜êÖÀ˜áf¼š›ØûÏßUµ+çì•êK1p¡hŠœ0¼ðdîÖ严°‹wÕÈ—¾Âæ»|ÛâM…[ÄÌ:íº´û~sõ‚Ž@Ê2Dkñ#êHMŽ—•˜Õeƒb¸z{e²6 ﱨGgomè_Ÿxq9äø³g90F¦m›q§‘[f*ܘY7‘—BzLŒ.E}µ©j¡ÌXK XŽ_7$ÈAìåƒúÈRðWxª¿9'"€¦qƒFcٟŸ¢?öù¸Éeb 0€xÁ”LUù1Ò•§íYiíÅ òF">¼yz,ZÏS½¿7Ö®ïe Цö‚z6Tmìf3.¡W˜‹AŒÁÒ|¨üsöŽ<“¶¹±yQê]ݯ‹?ÂäÛõ]!—çîKÈ"yŒª¬rÜòŠ­]í¾õ8D¨ûŠ4>Úhbÿä;îÑ›=Á2ò¿åÙBëŽkm%ݿћËç§Õ̦Ç^O.ÍÌ#M–øÙnÙEKrùY•|R¹ª‚é47º2]¹z¬Kg¯­ï92ãlcœÆœ“> h¤´I áÕ‚f`|ä® ýÊDd|±€çáŒ@¢¿«®È¿xp@‹D¨)« ¼ñjè ÖÎÖ­$[øæ/³,Hê½"ª^5wÇ  ß©7ÂBÍ(s¿pÒÿº>ØJå3÷©FúDÎŒx–”í‰óF¿Ë¬RĉY¤™ƒV&'i!Wz²srŠ*ÿ0%œuþ q‰´Ï®£2µ½CŠPÃ8GáײoD+ èÚð6p_¯d€õc„.™ÊÿË×UC @¿!‚žÇkŒ^~å,9ÚVZÄ=ôÑP%Ya7/¯ÛnŸ•@òä§µ7KÁ*o<«‡Ï~¬Eâoç¡N>Ô¯?–e¾Z–fü4¶×õóÍàäíÜ‹ïMgi)²l?`Î $Kå⟼&õô×ëëã·‘ý!+¿ÇõË#⬱;ô`¸D9E¨úB%J/0±²Èõ-§Ö”Ué¹â*vF£½}Ú„I_ÉZkÜ…ÊagÛ ð„ö€xÍb¾§|¾•u¤€±"::èIÅ =wÞD¶˜Öw¯¨Ë;o×?n:å»hšÅçý½]º¿²J”Hk­kAFwdÖ¸÷×)åo¡ÖP<}Î1á´äI;‹äçð!ré¸û¾O ¿SHÆâ”hÚŒUw*ñUTv@)s©[^ÄdôLÖÈšzˆoß”£èe*òȽ9ÂÜ$^±—³žrI·Õ"fä º–߬mfÙ˜u¤Bý¶Ó¢;ÖA&ºÏ‹‰Ã Y¨úaóá@å9Ž¥9 Áçw˜8Êeš<©Åx°¶G'°P ìÈœÐF”ÈÉ>czôb†Wh¨§É©­Ôùˆ”O<NŒå˜u—›’Óë,/^ýÜæÕaè?÷_kÒ(Ĩ`O´›ºü±#¡ÿ¶éŸÿ²hs„ÿPßy.oMD9·’“z¥ôêÐA— å ¥÷R€°È! yo4ìm‹Ëíïê0Ðô8e˜ÒŸ=¨Í’¯úËV9ªN•ð¼èÚ–ÃÉÆý¯ê®2%0ØÃkÕîƒ$`Rv!Qp±=ë( ;peÒÆ»Ü#4ÊÝA”€´c{ÃÒ-pâóa']ò´Úµ]Ýl«Ÿ}ÊM²Wç›úo–¿ÇÒ•–Zx¯ö·ãí ÐŽ ­•½˜YfP½ëø{›2E´ñ}vèlÊ’$2yH˜ÚäðKUX‡wÆðùØ·<¼Y&í„Èà?¶v…V(Nhð8=<•Ï\FQ®’§4<ßrmNVXÜ—î",dˆbª\¢¦M¢Wø±Dê5~Z JWóS7ñØXc“FŠoœ9¶Z?c<›ù §ÜÑi®¼!Ó¾CÕ†áOà¿ôT‘ÒlÝf´ãt[÷æzÆ-åÕd@P¶[˜‡o-LO¨ÑÜ4+ýÄÏUþkz€¼î8aJÄ]´„á¶m‹H¸ÊƒÔž8z’É0‹í—Op=MgiàD¦êS)™€0éAÝ(KWRnŸ’à>³b-ú‰¾® ê³ÂÛºv:ÚÌ{šPVÕ›ŒŠ³³¿Cnz7%fŠ‚)<¼1r@?ÕÅ{èR_¤VûG Wí¼ºH«|m¦­¯ÛœÏYsJ'1ª±ðÛ³ñ˜FÂ;ºÀT?ÑQWL"amËÐa-;Ö,¾ÔfA·Yζè= Ú•²N´¡énUÖ¨Åï$jÉd÷jE©šgM"K@ÀPú‡š ÒΛ‡ÞñZõ{«Y‘ïv¦AƒsôñÎt¸wÄ´×¾´qš¢Òïbx[ÊM¤µlŒÛÖ;Ñ • i‘8ðõŸ’ažJ†ëwCsø / ¯EKÉÈK§£îƒÙ"‚oÑIrö“¼Úq1ŒSe¯À!0-•Ó»8šr%íB«ßfS¥1ïèA3˜É†!ÝĈzõF‹×u][+Ã0Ô{/~Øo玿ÎWn¼k¸¹[‘Õ äã…¿ôªz"ެK]JÔŠJ"Ö^²“²:Ë~kF®•6m†ý&u)/…%²˜íÐlH/“B;X Ïï/’èkÍA‘kcšGÞd7Ê4°SÎrhñ6RŽrà‚߀`Ó»”ŸòÍËdâ ?Ÿc\úhQÌcâ* ±ô€ò›FìCTÜÙ¸={|Z®jØîÖMò‘e„v°Û‘^ºdÜ­\mc³îo¨‰ ”Ë=»O09é—WaSê0îiíwiÑÏ­ÃJüÚØÅ 8âäD7¹´´pž ±lÛ§¾p¢ˆ:Ð& v‘ÿÞ@Òf‘ƒ¿Ûq‚ìw^d@›ªèmSç9ºL|nAáÁHÖ­wa܃*‚_(V|Ñæóô-Q( –QuH´ÊIÚ#™B8²j¯ƒC ’ƒ¹¹x–ÀS"¨R—B $VÒä¸.Uë\Ÿ™;]¬;‹¸ÊØc¤œl\PÙW¸ÃŒ.^» 0ì”®t÷ðmçÄv±o.ôFè`»ªÃ~'Õ¦rz•7áÍ!‰­Þ>Q­”›§äœF È0ëV<“D=€Dv¦ï3e?Â9_,ø¡Š>¾ÉRÍgX¤×á狌%²§ûús¿ÌŸy“ØT¤lO?|O\šsæõÇëø³×]÷Wmcd¦ hŒ!SP‘ˆvÔ¯îêc©ÕTñÂa˜Ñ2F‰œìžðã/EõòpÜmF ÁAÍâØ,ë¹_sõ)9s¹¹ Ü=Ô´Hqóž!Á7"ÍÄç[ŽÖ³oŒ$µ«Ñ§Ë nˆìü7²àˆA(Ymn‘0xÖ~ð+‚¯‰†¨ó€ŸÜÐ0äšVçzóò¦>¼âS[„ØìA“f¢ÿðR]Ì©¦Ö! BfB ›°ñ­â4dc©Ø?ë´RàG˜í¡.T?„~7æ êÈÆõÿLQÎ3i¶>!ïôHšähU¿=—óãRñ'(ES‚ãž?+^ÅPºÌh•^åÓ÷£ ñÒd]AO1\üP»‚´|Õc“šgh.MaG6eU0Îõv†N‚¦P]ß]ÄÒ”b)ùícûôíÌYƒèƒKrÒˆ¹™›3†'C—7\î%fÝØ]ÏÑ„+gêãÔûÈvè¤Ô )u<È:“98ä˜6±ˆÔMIU °þêD^9tBŸK r‡D–•¦EϬY)Ý삲HxTôo3”r¬Ê[«\t.ŠÛNÅmz5V‚.‹ §¬MÅÓÊMN¥!ˆ‚ŒÌ”æ¶bºƒN´à° ÷›AªE LìoçÎP…’aHÛ ¿o,è·A£Ô™¡Ýc~æ³ro–/}Õ±µœ†4…@>H0» ËM]]ÊX½“?ì¦AÚtÐ5ô'܉¨ôtaÌ!º½TµŠ£Ä=f7_qÐpà¾!ÂͲK@®¦HY4›ÛOñ¡ß =̤œç@v'h]P4²¼AQWÂæpôýÖåÃKý(…}×~jjajI­ØrÒÂU3>y8½6ma.Î."f‚ ùƒ 7û¯”×ÉG ülr,c…¹&Ì“¡1ÄÇhµT—¦8ü2¡¹‘Ã×,VÝggñÈÀ‹\ ŸA£cœÜ®)¨º†:§m2áêûc;žYGkeS,„¨·‹¯w¾ZÁ¶ò-ÿR ~*eÞk”5e µ`Dâ!ó€å‰œ]”fñQ)°ñG8F P±áûÍÐ, ‚íår*kŠt9¬†7ÕòÜ¿;Íù8ZÝ™Ü2 Á2 úü8ãÛq)GÚÀ!(úÌ¡þöàmƒÇ_—ºü„ˆWè}α¼Ð§£.c¹(ÐÒ– «/Ì™sAØý˜Y¦MÞ93B†x#wà×÷‚¢df¶;¤ä!Ë~Ut3¦´I–öýG L`n*¶­)®µ‹7çx—Lp» êäkÃ2êò¦Ù¾½ìñw(a÷…Ñž¥]dn6’ÑŠ 8yZƒtt ïÀºÅ#ýZBDRD‡‚$2#P=ŽæãbM|b‡¡§EñsÌ¥Š±))í°×<ö§#?ÔêÎÚe~gÛåÎÀ\ „zŸ[;é‚h¾}/eJðÉMÊùX¦™k‘¢YE®D4ñFP¦Æ NâÚê–@ú Z|<Éêo0ªêU6¢©öZììA*OjË09v Júvª/_¹~ K.^,l«òÄK§iùÌ1@½–ðyÔðs€²«¼²ÌõÏS-u¶&¹vÇÙŽà]wëÖÂó™p8g¥n5ßOHpA¯ê›°¶}WÁ€ 6/ Ä¥”Áõ ü1²Ž8jNTòK¾ ’–†)’8ͦ_÷gž-êÕbÎF?U+Ê^6wÖLÊü:_ñ–W¢A:&´•C‡ù͉×ÔJš°i„à–éÉQ¬ä¡)¼å)D´fF½Ñº"1BmÄØ3Êž •Gˆ·ö$á/M%±àßXÞ_ÌA_<ºëüx^ðºU›¹ÏBž®keµb)å%ºÉ‘ä¼2æš0üf¦WAMó}W€Õ#Úþ¤Gz8a— ÕhS§Í‚Çñ•pÙ¥‚¹Kׄ=îËø,l[!ñ1ªIy”-1|¾ÜC„å’„´¯î÷èe{ÏÅ(Ùù@N™5Ó¨ t6WPiÁz²‹Û)ãÈwö9SA:cä¦ú’]³aÈK̖˱,AMè¯X[»<ì+õÔŸH±Ú™q Lí/óiçc&÷‹À}'dRî$0£Söù`Øâ¼7ȪRÛ€®ïc¼më Ace³^PÛHØJë’áÒøš©o{Õ÷;ñ9ûQäG…O³x[6º®*ÊwÚ‹ØÛ×B!|¬†J4›Ö@JÕBݶ)&ݵ4×2ÑÄî¬P0Õd 5ÆŠ‰k/*­Çvî[‚˜à$pVl‚©ÏæBa¸ñÏ2¢™\õU=ÚŦ*Hœ;P•´ì9¤ª®ÚïË$9ˆžAàz_C‰Ä‘Í\° îûÛ ©–_„kä… ½;ÌNd Bì4qà-ªOa‚'4D «Úf:£‡“‚Ç ²3«žÄëÈšÉÞš‰¶­¤ég‚“ø¾îõRSb ªX»Y=óõ{HÞ}u‡µoõoÁßVRTi1š œ=n t" »ØQÏ\DûŒ6~Í€L>îÝÖ4«ïI ÿÞùF9%Q´(ÞJ ­A¯·>ùÍU¯§#Æ3R½3õ;ìô×Lí†%¯×±Ì'òçÚ!Q^Ù®óH »¼Vl RU„èÙü66Y’³wh½ÜŽ àÒ¥qª#|§nH°üÖTUø·3/ù_ÈKàï`œ…²"8Uדz-Z–qÈÏÛý |2/׃ÖÞ¥ÂÓ„"eœÉBîdYØò›Þ¯@Bx`Øw‡ŒÕO'œ*(¿En’xì_;ØvÖ¤œ¾é\ÒÎÓàµrdž\O„¬X³š ‘¿?°‹5^ïô¯'³tMÌÿTØñ×ÜÐCc Ó‰ôãVŸµ?’€=ã^-){¯‰B~#Û¼÷+é#ã›Y²Æ²¹q‘ÙÀÓá»Îja«bîZm²2U«Ø·^i¶ÔwWâ 6LÈ`™tŠUõêåÆ|9!>¥Ä<Іº¥qø²!Áîý>aµàÇJë·üÝ-ê}’ð 5ŽÄÓâ´Ö9H¥ >@ÝÒ;‡¼›×Ý„¾¾Móªôb{‚³ôvõ›=¦hwÜQÅ[~ås™~—╼Ë"2;ì…ÛbI³vÛ(IXÝîѫÛ*ù$aš ¨)úW #MC'ý cû–fŽL°•à˜ˆÂ19kßhù5­3(•7Áb†jÿõd§ùÎ,REÜɺã!_dX '¢jyªSâÒk‹¦âkú º³*=¾a»SÑå!¥ÖèãöÍ'jÙ›u:ZÚõ%ÕúÞ,Ѱ¶ìÎù½KеÝj'NäÕ¥Iè3è}бyÍé¬À/dŸÎ-ð3CÎÔœjž¦* -Žß6",a’SøŸNžh* Göyʳ¢DÍSVNì“Vªmrg§h3ˆ}Ì2 Tä1$[#ùå ‹JèçΞ4ùVû'rb TgùšiêðVéo2'DC^Vþ¶*jçæ}ÄË“÷¹;°tÅÄ‚3©WeÊ÷زOŒ´´,SÝ÷—™F°zw°zÅí 2þ¦|òìµòLú³ãã%C¥ß©Òo$/£(ƒÒL¼´ÄçDElÁB‚öóÖYДÍÖŒh,û3‡¦ÁvŸd»¢~Sµiie|Q沞íÓC–,ú]Ù!Š(±Y[WJ¦œ°šx¾bd‰pqÞ§g¥ <…F÷Ž6Í‘Òç]”vÅÉüÖwZQ›'ÂÊî`(‘ ÝÓáššëÚ4i+7#7"Ü{ZQªÊGv)_”îÔlSQ&¥¹k›yß”¿qN“—¤»«>àÇ0¹½y°¡_dA™#ðcOæñǹ*¤o­¼-Ä«Ø:X¥ì9È4Gõ1x›†ë‚>¦šnÃÌ áÕꜙNµŠo ÎøXÒÐHïƒø0÷+¡Ã1ó%ˆÙ4­£óí s )úl#[æöA+®|Ã΂0V-æò·>‚Žgd«¸´˜ƒH†WBZLm @Þ;XË5LŸÑõˆX– C]ýœD6ç9M—ÉÁ³“k$»B(}Í)ª­á)ÇžÁl¹Ó–¡öÚaÜõš•5 ئó”øåӨɛX«ÒcÚ¬Òº‘Š®¿–íó‰}ñâ÷˜Íaa¾q¡Á/¼~怰–¿ã‘ü—˜Qc v‡ðP˜óÌ9,Ow5ÅDŒo"p2€øÖp®<Ø {ÆÞÖŠùî¬oµ ?¶7(Ë5ã@ÈØ?FÛeZ´E/*<YOx@Y’Þ9Œ.2wpžb¦òúc×@ºGU_ÓÅõ}Ô}fº©iÿiõ ”SWtƒëÍZÿŠ›0ÒñóÊg&O#eX¿6"™3yÕÉZìßÜLtõCçô bPEø˜8ð˜`§ìç|8©LnÚÖ>ŠÍg{v)&Ñòû˜â@”Ä:?áÙç -æ^ç!âÅ}¥%<ßø¶~ÞÉ“s>s•ZS×Þ±Pꇥ_Z®Zh¸›óe9ÏSâW†ièci™Kɑڤ¸E5¡¤ÆNR©-Cgr/¦í{k¾’R÷*«š§VÀ |¬¶'÷.&wñ²]3¦ˆþê¦)Æ-tÚñ*ËŠ£ F`£È\”¥ãp½Éø÷>8 [‰ª¦Æ´ôAwvp”bií#ÒÒm=G³±´+UãQ>_HÂÈÔø=€H´8B2i·SçÍØj.ðÔÐ ¸ò 4Ú .ˆ%ñ¾ïÔGm£gTïàÐ!t/)‚kf[ÕÉ3Ø ÃnÞ?¾€ß3É*¦”?šífXâÃ^ËÅ端­Ê§ŒñÒãH}QtÀ_¼&m˜×´›šYF¾iR¸™´ü2ñªø,éÈnJXÒÚÃDP2j‘VØbÑ̈›)ü½ANáz´MP GÆôþÄÆé#ÎxèÌÙ «`¯I§”©³pg࢙SE¤ž…ò³wCa‚âkº‹`nÂ3TŽkW¨D?äz¨Nƒt{Ç£²€V Ê*ÚkqÀú ÓˆþÃ\øÚ“O´›8õ,ç:"·ÆÃ¢ÇMpÁ)Jˆ*´àJ\ps —y'?F—ù+Ì7c¤±à« ÒCrW»æ)ÿ¼TþÕ¥G} >÷vA™õº0†{Sõ Ý!“"‡—kÏ„Œ$Á{³Òí‹*Àq³Ø›%ö(>GåZŒ†sÿ®/ò0’ñˆ5&Öqõ¹`þ9ñ’Xr]ªŸŒø`6Ð%9–°})îÝlN¼4§Êýf^ÔÜW-*íqJ g]€š{¬?·*>‹"|¹I «ÊÓ¡&WÃ×-?Ô9ØQóÍ(âWâY¯©<Ë© ¥ÓN^y¸³ÍKw¾’S·½J„@l AZêËk‹\ýþf]Á±™Eû *#T·RØmÓÎÊᥚ>•¥QP¯‚P³I¯pkÝ”jERŒõ)ò[qBǪݳšç•Y}‘¨2Z^|$X1g¬,…"¢z(w!K°¿ŽP´—&ààÅ«¾íïàWH¾Ý®bxp¹qªÙi ¤¸!?^I“Ö¬¾‡³Íõ=]ü^dð÷P¨[ÛO3hRO]ro_ß+‘¤Íw ;-_t´©3Ôún$®kàãK’ú-ØÂ½šÜý¨Ñ(§ôEš6èÎÍÓRÛò<Ö—$Ísµ«’ž¡Ñ¬Mz`óz„»•hÏ#‰5ÄZ¹Ó•oâÖ¯4\q˜l„c?1¢—EF!¾,Ã@Óõ{e‡#B¯TyšLSä».Õ"®þÕ=DŽ|özZÜS šaÞfÂ&šþÊn`ᥡܶtcq Œ#-Æ{+*T/t«Aò2»4àrbVBÁ½tÀˆÐUy€ÿĶÀö²׃¨D`°ð>Zh'–2[¸„õ>UA3££¢ùàbÊâè^EšÙ› Î¹KŽqYƒ;ã·Îõ§2ý®û©ÊÔŒÝýÖ%n¨ùÄÖÚj™tÖ¿Ö‰ ¹r國 ÝÁîm½˜]„ø 8y«¾ŒNf2û—TLÐQçÀË&»Ï©–nçb£@ ‡‰÷ÿZðŒ7soM½S×óõ¬-JÞµ@ÔÞ†6ƒÍ”„ŽA¬üÄ mï<ã@Y>—Ú= íýåòš~7ì'E_yØd‡½ÄÊIŽ2œÍ–ƒ~£+Œ _W¼ù¦þ¥õUóÛKÕ–wN‚É3|†§Jº !ËëÃJ{ý{®c[àˆ!tZé;lj Á{—2!¤Ä¢0©l[Àd°^ª¹Îw·1å>T”‹oü^åׂà Ë»Àðô-ª E¬8í=«»Î1ÊêZvÞæÂù¦ÿý§sýªO ~ÖF~Ñ´úüfsŸ}úJ¥ï–k$],'ï¿æ ÒÁ‡íoôÖ'c›ÁBè½à¥M„Âf¸Ò¶õ5ÅÈýMøÃ¢Ä¸iÊÙ‚7wô%ó¡’p)ùÖoE&þã¦vÛ]A8©ê›vmSÿéÐϽGWŠÐ_v»Ï<.b: }"BU‚Þw{ïA‚5n(—v ø3±bÜK誾&‘ŸkÂ~6ŽkŠ>´¨”6ˆŒV¶¢™@Ü9Ó»öä…‘x¹þÞT&ä]^Õèc½ñH\6›DË+™Q'? Õ4O¯â—ÄŸÁ8Nh‹-‚ЏvÔåäÇÂM¦ñ-èuâI²å·LûЫËì2Êfgá7œ¥¤¯Ò¸ªô!wm7K ©h˰"(“??UOÉ>9¹ð‰ý¦S,# ×f†*À '·øìÉk:ÀðÝ¢2‰ a1É„Tf…Æxz–þ <[Sjà Þp2£0׿Q"?Úô©ãÐÍý×*ò:é¬Wƒk †ÜÉa¢ä°½é3‡Øæ/KfDÍ!ͼ^Eè¥7®!Ø#ðµ'³îSQü°]u¾#Lã¡awRÈÍo:8 âDÃZß LðJª‘Ôî›hââÀËyGŒ˜{‚`ìS[¢Jmaç‘´÷{D¬?•FÅc¡ñý²S’'V9Pdû¤ ý-ˆq7ðù<tÏfà@b¨iߨ;r4¡3ÝoÅzâãý^Ò•FEôJtï*Gt;ð«ø9é0›‹å:í„rÀð ºÙ“Å·SÙþ8Ê•¿û@´CS¹— ò£Ô¨k~Ë_¿]k Ê™I 7´lkÊb›“++r–Âz³û¬Ê¨AEµ+EÜ&¯Öµdœ¤ L;X2`ÏE«Î#£²b;Yíâ`1 ‰^Ü> endobj 157 0 obj << /Length1 2012 /Length2 12811 /Length3 0 /Length 14046 /Filter /FlateDecode >> stream xÚ·TØ-Š î.;»{p‡à 4NCpw  .A‚»»‚{€A‚[p÷GfæÎ̽ÿ¯õÞb-`WíªS»NÕi ¡PÕ`7w0Ë8@\XØYÙ’Jºì66NV66$Mk;ðìH4Ú`'gkˆÀ¿’N`Ë‹M äòBTr€ä]íìœvv^66ÿˆN)›µ9@‰ ï;#ÑH:8z:Y[Z¹¼œóŸ_ôf v~~^æ?Ââö`'k3 r±Û¿œh²h8˜Yƒ]<ÿ+½•‹‹£èîîÎ ²wfup²a`¸[»XÔÁÎ`'7°9à·d€2Èü—4V$€¦•µóŸ  wðb°³6Cœ_B\!æ`'ÀËé7ŠG0äO²âŸfÀ_Ͱ³²ÿî¯è߉¬!ƒÌÌìAOkˆ%ÀÂÚ P‘Qduñpa€ 濉 ;g‡—xÈÚdúBø£t@F\ zQø—>g3'kGgVgk»ß¿Ó¼´Yb.é`o†¸8#ý®OÊÚ löÒwOà_—k qp‡xÿYXCÌ-~Ë0wujA¬ß¹‚ßHýÅy1!ýc³»¸ÙØØxyøàw°‡™ð÷šžŽà?œì¿Í/|½/2À¾Öà—HÞÎ 70ÀÅÉìëýoÇ#$vv€¹µ™ Àli Aú'û‹lñ'~¹'k€>ÛËø±Ø~ýý›áË„™;@ì<ÿ¡ÿqÅ@EI99I9¦¿$ÿí”pðx³psX8¸Ùììœü^n6€ïçù»ÿQÿ‡UdýWulÿd|±pðÿ)â¥{ÿâö×dÐÿµ6 €ÿ>AÙáežÁúÆß€›Íìåûÿóüòÿ7û¿³ü_Çÿ+’qµ³ûÃOÿ'áÿãÙ[ÛyþÅx™gW——ÝPrxÙÈÿRuÀ.´„ƒùÿúÞ¸€^6Dbi÷w­e¬=ÀæªÖ.fVÑná%¹5¬êàlýûÁ°°³±ýïeçÌl_ç—»úÃ~Y©ÿ>Rbæ`þ{÷8¸y '''ÛË€qps¼Ù_–ÔìñÇl€¬——À‹8_€…ƒÒïåáÅ›þD< Ä?ˆ”üñ€R#Þ¦â?ˆTùñq€ÿ ¦ö߈ÿ%'èoÄù’dïø2N¿ßŠ¿9/VÓÐKn³¿ÑïÍÿÙ@ðßð¥À?¯çohaýó7tûWÄo¿ƒ«Ó¿2¾P,ÿ¹@«Á—~Yÿ ¾”j÷/øR«ý?ý¥VÈ?G½H‡¼\ê¿ü/Å;ü ¹^‚þËýR›ã?îm/²vø—ú—%à»Á—Zÿ¥„ý¥VçŽÿÀnàôBw~y|þ x9âŸÖ½,+ÐÅÊ ü¯f½èqqwøWÀ‹$×õú%Âó_ð¥~¯êi•ØéÏèÿša3W'§—÷ýWæeÀÿƒÿø0ƒ=ÀfH sf‚!6µ!í7ÕâÄî,[ãÂßh¶tRX¼œ:\ïÐ’ª2ƒV®Ä“†¾`,mHÓ_Š-’?z´Ô#„·~Tk»÷y0ŽWŸÚjCšŸÄëŸÈ?¯ûJúš„ESlÛçñv -l t—4Õ<ì÷>Yº¯¥?FÃæ¶Ô¶«xJ§Y>hEÍÐäšfÍP»°"2bx Ï\^}ÃÊžx&—gBòýõ³À[ï'GÌí¬×r¹&‡s7!5¡)ì%Öè­·Än²<þwïâÂXù°¨B R£¹&‘tÐ;®Š®¡Ò‘‰µ‚=ã@ÉRô©°X3µu‰¡=;ìN¬œ:Þ¢éGvãÏHÎj;x^Q3™NÁ¢ý¶.‡ªái½ vd!—ô¢ð»á»Éßyæ óú¿òûMÓÕ'<û‹ÅÏs˜æºè÷xƒÝ@z¨§ŽÛì\7XÓQf•, ×ž68VÞÞ&ÉéøÒ̉‰7#.zfgŒáÜS¢¦Út]ŠÜãi¡áY¼6×eús¬×„ß•Ô1¦ÿJu}0®ZÙÕiŽAQØÕª$f6hzPj|!·µGu&ʨȗ ©™®»{i“¥xÜK‹qìgùŽßÕ†\;~°×–šÌìB9ÚÜÚkâ®™Gk)Þg7‚”R"úô ,!=¡÷<óéÜ ?fÒë ¿1y=`Êvä²A3tû;½-ÿø^à{ÎY4žjI.ïíÙÀG¸¹­ç– uCÔ†Lþ>8=½ R{3|‡ðš¸À¡ 7öaÊPa~´Äý­C”«B6ÂG E” §Wós¯’ÚUúžý—Çc2*ºÑ¡a¡Cè‡é·ÉSz,j‚Q€f:)ÁR©„Å|ÐÁÃwêýôèÅ!­ãØy¯ú¦»Ò¨O°?RLR’.ó×E«„yõÎ|K2—â ™¼À¡Úúiï‰àíX:W7ºrâP/$jKé±T%÷T¦Íè,*$;6T¡å57æúiº^œÌ©Ô±ãÆ—SÜ’ø2hy¹òƒwà¢÷–¦»¾"0 ·2”jËà›ms~å¬!à³ýŠlõËîÞ® wG‚· JßjjºRî@é8É-ÒO£Ë6˜´6ÃK³y”¼WâØ4åvªTŒ=øL°Y—?x÷³¢sÌïç“YÖw%“×Å?#±),øET÷«|eòK®*Dàæ·S±“S¶¹>¶“òya´™ä án m1 Q„D˜åü*Ê¡µDªü0±Vü^ñã'Ëf³à‡0M̄çpÜ´ÇÙ§[oߎg±C9Õ$•üºø*¢Wv4º":3Æ·®ªm¿Oe–R½˜J/Žài%ŽO¼å/t¶’î6Ö¥ï÷Œ S¾IE ç'*ÚÁ7çžÊ[Ñå*…kãÆ¦ˆ=Aѕ̀¯–&“¿Š)ëlÂ0˜Ÿ1ÔÍÅ!hM&«¯ÌxX°clž%xKÒÀ"Bâ8Ä{•Ô¬Øz_?0¯÷i@Ò¯nÀîòö²ü=V›y{þ˜0ð`IÁŒ3€Ô±äû!MmœéŸSÛЙ¤öÁnî@¶²¡q•ŠBÚóÓÚvÙ)ê´|}’¿øüëm·k Óäìbf°©*WµÅ“Š£®q„‹€;Y?V]ZÈ*GrÅ=µƒüôžKU;ÑÝÊ´Ë_î–ÓZÚ7$¨A½Àþ—×u’:î 5é·X}é.oìÐ>G/u ÎíËë¶Àbñ¸í†öVKÁgtíÍ;úï2šŠY³æ$Ù\I´ò®IuЖný`ŸzíÎBÉÄUG½R 2Ý’Ÿ*LU S`Ôi—ެrye<Ä"ß‘8€lJ:þ9üó¹žyìI‰Uxr\mTlŸˆ‡òaIÞŠãF¬3laV‹¬bÀ‚J•Èyö7‡ßrгˆº¡åOä™ ì‘ÆÉIä ïy†¿ØbÇÌÙòSÂ+£L¤¦{ô;N»V<îÞâèfBÂ+•n¾£èªP’«ˆÓŒï}œÅ¿§ü²Pègº¨`§¬øPôQr›ÿuÃꃿ1&c˜!é§ë Ü[ù1ëÌáw#©öò…:€EGN„'£Æ-4šïU¤µ¬6;¨ Ú¾6ÌMÃKOØHqv‡My_ý]úÅFÞ!WE•öqaSÿ1¿£ãeù×’AoD…¸O à5Q¼œ‹ê}]M’•æJ;)y?)t~C†=ºÞi;Û [æóTDyŸÅåû丙0}a• #!áÌ]ØNR N"Äù¼û:­ÀÌé_›ž<½ìÜ›%…ßöó›úsäÇ‚/š¨£f5e¿âƒi<¥ ”ê15øåæOÔ>´Ïf9Y\È=ps‡'Qm,¸áꇾ¨gÀÝÁSØÔ(0"©÷ƒ´¤U(éÞ3óÑ~æ¡ö›S?¥,'!¹u°ç='ºü»úŠÏ˹šÕ¼„Ç Bu¤ÚÍEÚˆÀû‹zŽ IDÖ!,`t1ÕÅgÓXŸò+*G8Jž.…hŠäªº#«^¦h…ÙzafÓ׾χ 4øŠó *èË•ë?ôÊ3õZqU,õàç'ÿìè3Wõ²ÏhM[;<‘VºŸµr‡ßPVø§‚Xn»î]kº]™pìêÍ/7¹öš½JÌÃ?âÝhÊÃë À•»=„nG‹êD*ßD)á2¶¢V+ÃY)Zœ[ÈÌ‹D‘?C&:`ŒƒÆ(r–P×%ö] /½‚ :ð3àÊWÕiN\ù»xJwÅÉx³PßeÜýÁÜt1†gþõzݪcdŽƒÐ1ß¿7:U‰ªÆB†ÐÇ?Ò±ÀEš0ÃÅ,Zºæ”õ-Є&Ü¡K_Ì…tS ‰ÀÄNçÌÑå°d4¿ X X’¹étWRÑŒ«’r–OQ#n­¿ë öFx}Ø¡¹ÒÙtÁQ©M_©ì¼:s†îßI#¼h}öƒšä;óÚ¹Höv8ѹÞBÊ"¥\ÖDÚ z ¹Œc\£XkŒ—N¾†¾ñ¸t cê¬ÂŒ]õÍrÜÚ5«]ŽÚ ´Í Mv±j=ûQ›—)ÇPeNÀŠ“½BSHKÿ€3åÓïs_•àýU2o·§BxÄeG&àýöOH2‰¼D#‰dú™Gœmï‹U7Žº u¶æŠw}mê õjhœ¿ÀÈ…UÑõóe¬Ò³M÷Bq6Ê<ñ/š8|íçÅÙõA·¦ xQ Ÿò`GõþÑÆ!ôÿuþŒ2¨èœ‘e¡·×úÁ”ÆŠ‹˜˜Dœo?;׿‚ùö©ïº¨(Áˆ“ÂX³¶¤È¤§+!¹É±ÑÙ#È•X%Aõ(ªîÄÒ üE—ÔÊm!‹ByÅÏ”6ºpmºÎ°JNDóûÒUõ¿²f(w)~1Z0eP@k‰GÆO à0‹rbuoxð&ŸòPw=ƒ(Îß GlP bß?"% ¹àG™æ5?®ÊvÕ-QäT¯ J LL×6f©¯œ„;ÆD々D×ü1BØZû ¼•¬9Ü%êoiuü Jm ì ZRLvËí¢ƒòw©¶IÂÉa¿¢YzìíaªÚ—åô+Ó7e@°­nbÓŸ­÷Ýw¦=©ÍÓŸa¾Œ‡aÐ8¯úeÀ‚o#o¾ÒÇ/" l8ZóE§°—–¼Cs¶6d³ç>!ŠÕ ôçÚ•ß}umóí.tʶNk¿·h»ÇlÏ]ê<(}-dÒrÃ"zti(Èr~€/ë«AMòA¹^s@ùÞhëJwìžñX•â%³Ÿ²âØ[ÏA†Óò±Ï÷ ãJ=¾„䄈§hºŠñ4\;W ÖƒÀzR©ôN޶a{ã´öÉ­)s0e¸‚ƒ ›¹iˆ¨õáóhöŠ—¬Ñh¹m½÷Nï˜ÀbZÃÓŠ! X¾iÞ”(iÄ,pV·&ûaÔjèÚ™ k<Ïÿý]¿qƒsƧ~Zü¬]RfK±§5tÍéÔ¨ÓS Mý™ 'áƒ%FAvÁJmž’ïüâAÎl)ÛA+“ÙN®æ"«§‚×Ö-âÄÆG‘¸H2ÆSif¶—Ê3Q7䓼;·ï¸³ éI?Ò6©©Qyn§¼ŸŽÊvÖ+ dÜ.µ~é"wØ!ÑxÀé[ÖÏ`†Úðø`I"Ïà.Q&$ÙÚIÖ{¢·.Ñ<‘3LÒ@ufe2U€P8JižþC83;~çzï:KÉ­ßä…RfKŽhf0z—~5¼/ÝIf¸ ·Î††váÒËHÖ†š1´ßŠ Ôþ¿¨rÿ10 ò²ÁÊú©錆F^«?GߢZS—wÈJjŽˆ¨õ*‚ùÚŠ÷˜O)kbŸäµ×.¿ÀÆhݚ͓½“Ûe†êE ªHB¢i€ÇYÛ†ñu[áˆbos_6²gYXéÇàê‹ nô)u1 ·Åšä©o™ùp7âà÷+¿ù §º=Š*X®¶Ç쩸˶h ÕÏM‡]JߘŒè˜SÑŽxŒ?t¼­æÇ†Ž‡€‘Séû£6;u¾ÓO‡òá^ÈSÎaïg7߯ÍÙà¿.^©óóÊPô~'n¥>mEÍ%६!¯¸ìIbcô©/q ´:®Ÿ„ŒaZsÒoRAV÷N• .6^^Ï^Ķ·`Å­gÝè™1®“¡#\—{‡XØ Vy:¤Œ1_[Bón}Î ž}ÉÒMt'€‹§Ž7Pî*ï€âé¼Aùâ±Ç&o]…‹´¸g¡Ótùy+¿å´K®Ì™çÙvÝÖå)í±÷¹»š>“Þ{ù„¼wÍHL-kbÈÇöæU%ˆ´Å{äbuYÒ*­WõoѪø¾¤ß(‡â~ÎRÀx/@lØ—/AQú_Y4@÷ýñÝwqÖ+Ûno!ÕÁ/)¢[Ô@Ó¼ 3õúÀ°5H;Å+Æà³ô\~¾÷äKÊè®ÆšYûéì(ä´GŒpà|e#Ú"×7>—·!LÏsl% ”ÈÈÐqæø'e_x*µÜ/U(¥¿ßû“NžœËÄö õ“ç OéS†z°á@an<"§]êy{}è½X!g !@9ä kÔ{]ß3f ¢±4Gõkó3ÝØUЙ);ÐÊñ ;ƒ¾Ê‹VÎ Ë»b~˜Y¿Þ±i|Ø©X3ÛøÖ Ç´“È™òÃõ ½fÙÎAîT†ËÔÁÅÖ1ksŠÄÞ Äõÿ¢Ílm@-XXîB¢©ÞMƒ£Ä×#õË¿yR1Ûù­w¤T=òM°”7¨ÄÀF°‰R€a>œM76¦ ’Lçøq ôìjÉXš}Î íaø$-¶ÄEÙU(¤¿?Tî ÇÀK3ßš¶` äxÓhIWQäk*4*‘„uå3 øv=¹²Ë®[Æ{¾”÷*s»€ ›ŽY$Øî€ä³Þ»wbÕ&x‘8’QÕGÌh<„‹>gZ„»µú%Þ7Í£[ÛÞÆu$ï_†Û.«]¿›þ2uIº|#4.“¶^‚•Íe¡¼ Ãâärvæœ7 >Æn ’®ä¾¥+”‰ì3„Úu“Û|²âNÀAÕ6,à32Ùγ’ûK`ÆÖéÔïM”tLýÅÌiº[Ed•)óýtÒ ÀµAŒ·¡bM©?Hñ›ºéîÈ9GL Äy%cýt™Œ·S;Õ©d7ŵû\ ßK­˜£vÖS¼žc Xg t]…ûáuaº‰_”ZM|Pæôvê°°Vù}uv#Íù¡%"ÔÙ ‘–.­ÕXOܼJçÎùÝÏqŽ£E‚›8h4/٪ÀµrÎôxÙ㣧E‡±Æ3å‚È=«¥É‘ìÒãàDÙà¹îQ\ÎeL‹®´/TMæahè6X«Íx7ÛÎN­›çÞÚ¡8$0AF¨.Žˆs&íAöiy]™oE ÞÈ}œ`98ª×;ƒVº"Z ÏV€¹G|šN"Q\ÓôƧ )Ûov1£ÊB¡ÄÚÖ£{äÕcßÐ @þÆy·Pçgh‹¤þ™¥À¿iéM®æÀ9y1rñA¯h«¼”õ•áS!~žE#®Ã( ×'ÃB_·Ôn)ŒóGà°þj¸W?ÚW ¾è8øícQ[2ó®ùT¸ÁyÇÔê™ùîÝ"é/|P²³úÓØhõEžb¼ºú9(QÐ{æX:t[×Aó•,×ó]'ž¼ím/ÿìŠʘ®.Ô³z¶ÞHy,À {à7žvƒH[q¶Ð ù:J‘X™¿NÖO˜ 4ÞÊÞ}k£¯GzFê‚þöìÄ_jÕ<1¸MºþÒ1Mƒ¬à'´4⑺îê R¦:U3Ã盄ÜR'ë}©h}r‹ÔÒïQ2ß9Ò59Š;õ4:ƒ¢©]`º’‘¾nsÀXBh/h¯ó9üç>_àö]|„!÷[» ¥Dd¥/2}b£†›ËvÒÙW#mqûÒ]ÐMå±aU ‹¡rè ÎÜqcª¿£e¯¡½bícyý!TÁTÀ¾Ég£l^-º,ÉHÇpÙ@¿ë[+Nöý‘µo'´ê>h”°‚=ÏÛ>Sä§E®ä}ïpBô*¨Å•‹¦½¤pãh.žõ´a —¢ ‚rÉ©ush’•¢, €é Œuê1þ¡$®­xo¬Þû‡òË´wKMž7|`ødïpæÞ[tÉ-×6Àkò1"5Ì"™Ÿš€"—·½ú¨¶ß¸Ÿ&r]iÃTæ4S IÖšÊk mÉ9…ÈÖ³O|„5iAÎûF7G°¬ð|WK›„1Þw_Ó—Vyk+Sh˜Ô1ˆ8¯„®Ì Úö;ŠÝqÕÊi°/³Â<¹$bý›¤X­µ6ê@ÐÐ{¶&.ÍytAf1$ÇÔðî:$`sXXÖ»Á>KgðE£8ÒG¥“¤óL¸õïÎ\ŸãF¯<óë[“ëS™ß†xgÍ’CWå¸D¢cËGØ™QÈæ/ï–O¼WÌËx­¶î¤.Ö„«Pj‡sé²6ÉŸ…ãŠB÷¾€çp(*{Úÿ[»®Ùw{!{•ùW1k•Áþª¯\úñSâMê ÍÆ‘ÇÑù‚m("˜ØÒõ•WÎT²B/‚†Î÷ˆ ¦¥ÖaÅ×c`qáGsÍè{hŒ»X­"•âôŠá3z…Å­W¦Cu,Ê (ξ[è‡þÄ×£Çl¬rµt%ò'mˆvŸ9B©§Ñr_~8 ƒqžvUôô!‘ôiêNo-&Ö7)kô«¨#§eÄHK¸ä¹›M3Sp&>a·D}÷±ÃFLz¼êÍ6eYó‘‹ÂÍÙ‚l»pºzwO%h/ŠTvëMâo~ë¯Å½,ñF¨ñì"¸€|æýêvT‡¼Ê×IØ'„tÞ>5P5sgã%¡bÝü†ØnD¸áÏYŸÛ‡í€=Q„kÓè°…3y5™úB‚¨äÓ‰˜GÎÞ dwL=2ë<Ö¡`Ð¿Ä žE}†,÷`Ñ4Kz¸Ý1\ò̓һ:m à¶_!–~S>"€Yfùîe`‰²hÄX&,”C;Æ +»ÉÕøÊlås{4|Õp§- hsîbËÌ’YuWÎæ‘¯þ̶n‘ÿºCƒ&eÁTæÞ•¦l±2 <­.Õ¯øyB³Ö#¯Ôe£AêÔXgãîôΩ¸Îpƒ¡ñËGÿUp;•·2¯G? “Îd…×#×9\'6»ô­¸‘°)Š˜–ÀiDßÀšŽF6u`æ®Þ,É¢MP"äK·Ø^PJgµxJ8yÒ6ža?] xjê|”ò§½;×Èz‰²‘„uk ”ZN‹'^'’ØÅOÂÉWsû¸‡˜*én¦¹û‹zÀ/cVÎ%«Ý••¥Õ¢à}“Š3n$»¬É…†r;ŠÅÈñX‡×'E+;å~ºq•¸ Ûmâzžå.8»ôvŽZ*RgKý¾•ÖÍ››âM^.êŽè›)#öÌûM&⸄6sÜWwÙ»IXS8 Îô¢„)¯GÐ vmã,ö²dŸêZ Uéņ1pU.~QÕ×”,´YÓï¦ÅÑJ,}{ˆ-~" †ù¾Ê‹],@.Ó›¨rI¤ìp«µzIx`,„S©uÅûëýYMت¹os|AÂÁÅŠ?¦r?RúY’¡•Ž®Ëò!-«•VXetÚ½qšA¿‡Àc(†Q^ÙJAd>Ӊά!¤3FqÁ¹æ §ûzÆ8&Ë$}$JâtJ6Y؃ëèሾòH§E›¸æp†V­‰xâ‘eÝÍ®(ß›âMFù–j 'Å5Bû¬RÔ¢×'ŽBú¶œ‚¶»_§pç*jÁÏ5‰)ڴʆŠ9-UÚûaƒx=‹&š®·a¯ ÉNkùÛ¸™å§•ƒŠJ~kĺÞ6ö,âý›Âv‚Ȫ#sC·7{“Yí‡66À›}bØM¹ŽF˜\º£€ÏáPö¢bB 0|™Š• ûúP¸K5’ßN‰Å«ÍÌ<9ÄùMæT„]8Å P9šóÒ:”™’Nš…ªb=L/i¦ûÉŽÚ|+®á~•ÌHà}»`îk ±u‹91ˆ0Îñ#㩆úÊm Qê¡Ýá0³]U|O¾L{ãD ·aöòk¯1aP ª='ºç¥@›¾Ÿõнs.«Ö]OO¼§ÁxßC’Qô9‡ç•`–è0ñØW-~á`Æ LM–˜&ðe %FÅž.û|ªÂƳ©;æíº®|ƒ£òE²YåÁ…J‹ŽD–7—cῨº,Ù”¿Û›¬Ú¨7 ×gèÆe_—Ö„ bîDÀhKî‹Ò/rÕÝë°õx•ŸªÒ{nï.z[8c¾ÔÒùseH‹ ê0Ó…Ö3ÜÕŒdÞL˼“%$‹Ø¶»BºÌº;r¼ò©ë­|E\‹Žè²?N# –&!…D䦫0´æ[çC¼“ê—Ý1‹îáŒå1¥GtÕܤ¯ÙßMž£ªp$Ô–Oõ¸‹â › ü–œBö‹ÏËò'b(ùæÞã@KG&[A€ÓäéXC<|Ûh¼7)pL9ÒÂÁy“·ï‹®djÿ4&©Ä›ã35ŽÇ÷Ì!ňﳞ7¢ÖV¾Æ6‚›¢¹Poª™É>?å¿ýB„7Ú’Ï$¸ë‘HZh¨¥Ó0…u¬ dšBÌ~ ¦‰é§=ïaœNí J7˜¬Ç¢Î}m3eo'%J’A+Æg÷…ahˆùùW:–©ÉüÐ sZKkˆ` kcYñ/5V‰‘ý`'²Û&§£sŒÚµSø„† ³§?N+£¤V–}¨P^™¨©±ºÎ?9õzsŒ!€ÜÏŒHe¾ UIw4cqfÍÓ?Pooq!·gý–\Df"£1¯¦e¼ä[B u¯î0H høQþ¾€!̨–K«·¦ÊÖ»çõZnøÈK{öDmñ@ÉÝÅP¾Ñ_tÏÍÄÞ‘¾bÀª¼R#.­…À™hvKOcYàÓ#¦«K媟æH Å|M&Q:aæ‰ ¯¼Ö÷1xñq˜Šü¹õr}1Œë8&GÁùŒ–5ZdÌ9ŒÌ)¼ýæq;§©GÐ4Ÿh:‚2ìO¡„¿„5&ãá…¨‘á•|³ˆ¡Â§n Ù@ô$‰Y2ŠÓí,$Epºêh¢ü%ÕTýs„&ª¡+fZ6 WÖìTP$¶þ¬RqwI>‡¡X½¼ô¾PP³^«ÀiÄ»²„Ð-ýúÇþ©"Š:=Ÿa6ºz% C•Q¨_Õæ[ yï\D[UØ[ž•þÍûS¢ñL¦P«ž•ž&ŠY”ˆ¥\&¾_¡²‚ö^‡¨5u3¸¯Ý™ÐÌK†ya¦UDÎ?F( DÝÎ)o¸=ud°û—¾·aÇš5hì‘‚-X1‘Dx×ÒÊ$”²÷\Q–,å]˜™­LFÑTꥬ(CÔrÌ«ªë¢õºËà-¶liÑ*pØi„…N¶è9} ¤³³åÅ/¢G³.ÒfLùfªïóíŒk\ø37þ‡hü¹¥ò ç1ùl¥§Â´ 8å°˜Ù®:»ƒçƒC0£a÷ÈÌ1R… )[[é]…*›c÷HA¹z ÄK¼ñS)8-÷ O¾úó­AÍÌ#ÓÄYch“˶ª-D? _ ‘y“OΊúéÓ rr‰m ¥'•Ú¸S4ù¸vpÕyÛlñ_ÖÄ1…ÊuÑì…·4¿Q…a}¼•üÄ*‰ÉRÝ'ï·KÕ?p¾{&VÍØ›¯¾Šƒ8>øÁå‚í¸i êÅÔTJ°GI0Ŷ‚ϹžPçÆd¨¢«}0µ p ~…ÞÙáD©«ÈGƒ—Ê>´7ÌÉü³4˽Öõj€Fփ榉3/† 1± Bdk| Ö5;ÊP””`ˆBr¬7æ*ª‰)‰é¬|V~L,‰Þl']8¦r0\…„§®­™êR©÷UÕ¼ý¥~þ‘úºR2É£ðÑæå¯ë§®òÒ@ã<•&³}ª$Í’SXC29åË’±ëw&‚wØb$ïêÅ:ÈU–7,è7÷K<š…Ë7¯A•cVé³À³5\óÛ×¥Ùò—ñ —¿s§EÙ¬˜G¡ûí˜h‚|²¬—K\œñî90ÇŸìE©ª²êbÀ͈pwÚ[Ÿøbj ºz:Ë rbûáµØý‚"&FGˆ¢± :ÓN‚Nt6P©~'B?¿T%ÿ¦(u(ÑÅR䉷3¹î6?æã7—6A ÁÖ­”ˆÓA8ž¡/l'}OS¥ˆam_)gè·Ú£‰½¾©NÝÉŨ•P¢×’¢û=ß»ˆÌDdz￞Ï,HeyÏk7þk(•&zO’ñÇÓe×&‚ÖÏÐíïØV¿ ž#7×/ª *°3 RƼ§d²r¶Ì…Õýqì'{ÁØü‰*ZÑ,_CÂÚ¸eæ«E\ÓZ§´0Žk7ë¡$ÅÐòŸVJˆ z¶o¾Ñ hF˜ÅsÚaâѨ¨ç9HøcNj¼Nÿ0sŽIaL¤2dAÝ;ÂNC$¢F¯ÉGYéd½þ”ãv>Òã|e™²¢ K,¢Å3ÕåZôƒpã±&T¯¤ÇÌo‘uÎÛ×TÏ£n*h {6dÔ¨?Ñ}Ò¨ÛküEóSå#ç×ïÓÜ Fê(žŽ´Ÿ™•¾<Ѽ¬¼…™A´ÄøÕE0{#ÌýÇ!T1<–óDž >}h.ÅüH´”ÞÉw ®ðÏ+rèÚL¦8 v'Žá&_(L¢`6ßBl”Y$ëaœˆ¶ªiˆÈ„æý˜è0ú ïWµ“Uè0 ¢“„ÊH·Ã°ŽûqÌ•°ÔÌ­ ^±{|`›BË÷y®‚ÈzÙÆ*^ +í'+Ì´dÅ·HÒïÔ3[ØwºImd¬Xˆp\0 Ñ©"&{ñxòÉT"ÏÀ(öRÞÏÞÄI—,K’­XDR’:²µˆ„†JylÝS6jˆ¸æß_Q÷»¡åã· ãHËÞÀq&è|Ø=Â?»$›78J:ÓŽñ  ®úŒñæ‡bî@¼ÏÚÓu«ÅÁXÓʯ@búÔùÈ‚Àg'ƒ15y` N‚&%ÍÁÀýÔ—îp6/%L‰ê¯f)³åäñ¥ÙWîò2ç”Zûƺè‹&@êI'€î4äëÒεƻ:sx†öñs‹Õµ|k†õE¾Îo—_ãê:Û#2OáR™güØVÞS¬·YçTãÆêy[l+îèµ ée,ÓhȨ¤ÜÌÒ¼êeBÿ2J—|ïédå¡eÚ¢/±Ü’[«còyÅÈž´¥ê:~,ÁöŽúdbËB÷]¢ã?zR1c‰cNI<å5y¬½¾?V³ÑññDÓnŸÞ}WZF±tZE‘Áò¦*`¶{3ëbëˆ5h9È#‚ÍÑçöçÕ7j;¥+ÉLKV…ÈObë(6õJ=…Ÿ*Ÿ²8ó¸âÁZà!‚ÛGG`Eò¦,D)—¸Š6ˆkBôÁ¶®püxÀi„¢`(œvþ_{˜µÄðù­ÜEþåL£ó³EÂÆr‚6J­œ¢„G܃U¶ÓZØ2ð­ÃTêñ>yö‚ m‰!ÎJ(§pÔ¸Ú žÕG¢F›,j@6T¥õÏÚöè<:¥ÙÈmb¦ gÚ}¦®Sþ­X¡kü î¯‚¡K>iÈÒ†Ý{ñøøý³öuiy\|s¿F›¨ŠÞŠ|¼¿d¹ÿ ™±‘Þ;0h8O=¡²ÛM;ÍpŸå*±Ü`ý<8%â¢ùåk‡ia¨ ‚l xÌÒÛD‹¨Ñs¦ ®äS¦ƒÞL7 fVdâ¥|šëGѶzÙ\°g<-A5YŸh 6=ì»Ó›ÃB] dmà:|Z6­qœôC)”Ì0gµ «×=¾~O¬Ýzër>$¤$“,&c’¿g(ë."Ëqyµ+ä5=gÊÄ2R“ Y8)Ÿéô ¬¤,ç.¨°Dw_I,åÊÕ¸d6 &)êѪlÈ™2OÒW2ú ûŸ"«/Þæ&ýئ¡¢S$ð;¼¥ð9T3‡!¨á©îpÿ¾™Ô[‚x>ľƒ|Ä»H¨lmÛLá†ÙZ¼…Á3Ÿ°â¶,*šDFeý%æ³"×GG0¼õ×ScRï÷²¦ÊZˆ¨³q}˜x²(2¨pÐr)4“?|¥ˆ½Ö¾w2Fìïº}ÃÖºD*ç\t÷³n#¨‘AìÜ #3“‚”=#q´oËœlV’e–V½íÓ›šukç`%µÀ誗³KÎUŽá^W”ƒ_Õpj­í¹“@À*É9Jä) NeMo+JݺöŽÂ¶]'¢š·l@,Ä×2t2'­™d† è©P30m7¶„èÚjšÓÃ\0ýs²Í®­oI¿õŽÆ+c·Å’5åÕÂÅÙvʼb¼EKZðßœcv>³³§Lbõ0ˆH¹jYCÏjÂKõð•c©ø:J&묙„Vͺà¯Èõý³Íóý:—2!9sõוl&d`v?ñ£6”k]ýð0Ñ'q¢ìM9üN–çî»Hâh‹h&ú2–iõ¯ÈæÚŽò Ðì*ÌÙa¢©­ÍÅ|ùЇ;Ô%¤Ò¡{ο¬wÆ û…\5S¡Ò>òÀ÷1¥xËpŸÅ|ž«,Y»ðȤû‘ºs:zåz’õ‰NéûTî=Å.v¯}3°´0—€÷ý…)¢x¿÷Oßð ªØæ›A‘‘Ãf«/—ª.&nåñ‡.âèšùS‡ëáUH‘N‹!”¡`»ªó¤q^ÕP góC©'§iýà®9ß…]TQ`” uY6õg½“Ôa’‘À¶2ÁeôÄã)ÊnFÙU´'ëàééà=β£hcƒYI-†{ì '´“ˆú_æeâ·ç103ÔÒõ¶1¹Ì+ÕÝ>(3¦<éZÑ›îNÊÖŠ|ÞKîêPXˆŠcá‘é×êŸ%Àª-(Žþ _Âà”þ¼>QìÙyâ%M;–¶“žöó”…\FR÷3CFÎû3˜1ï‰áò#;T~ö±.Ô÷¨ðr‡‹-Š“ÇƒžðËTÎëvÐ}§bÂûW¢Åžff¾ŒƒŸ]\Þ^ýÚ@Q%)³/[bºpšŒÊÑÌx|ùçÓLêµ`H£ pŒò@žlÚ”B4N¨'Qû Œù{ðéÊHå'vñô±·½ d'>—aé«~xJ«ª´rpJTK—~ËØ+%“׷û?LR ¼XáìUÖ mß·Ÿ¾èß{Š~zôîV)ývÏîù¦ï­œ?EO‡ÇÌîT•êº}ÔT_aÁaž­¯¾òk{5q­<‡"ކb+;=]¬ ÌÏ vÝž2Wèâz}aYô4ßmµP`¶“ˆ4;¢ÊP~þòÞðÞ»ÏòR. b÷m«ð•ìÀhwa‘5þ)sìüׂ7ñès7DL©}ᢙÚ.h½OÁÍ”G”?V¯>Í‹´ ßJ?YÏQë$¬aC,l¨`ôæ…\˜9\Ÿzâ÷8ሴ8Ôë{¸jæ{&¡9œ5Æ"6ûR8ÆÁcëê¹ßZ.×é×j|‹,["¹±]‡ƒÏÊÁö ¦Í%Õ$É”CÓ|¶Zõ±§:þºÀ2*ѶÜÓ¹ž‰jbqÇMæ£4fM¡:YÞ‡M…Ü„@\ƒ(bÌÇ'î†R?Uá`-È€8(Y9ž×}˜²®¾Ð&—s³ˆe€¼«]nzÃL¿N÷ãk/ýžZÜõHÁk Š"ˆøFkTÕ`èAhÍ©¯ï Ì]ê»`Y ¼C—ìÉEýTBÀÝ­_ÆU­*G]8Lüµ”g¾ò†ÈVTV}yÓÚ:j7¡ÊK7"‹Ž@F½©ZÔsÚ!5Zã ¢}Ì»^™Dó±~¦»ô‹\ö)Óo1K(©"!Q7:”£y’(cÝœiŸÂå*(¬jʪ¥ùŽ.â:i¯Ô)“ЃS!aAõ<زåþ¬9îJ 4˸ øÂëø-©©<,¯P¾3²%ÇŸ-ôe«H•Äçêí4GºÎå³áç¸+ŸGû¡MÑÑJâ1‚Ú¸;ŒÅxïI){ñmÞÔg«œ ÍúIꨤ+?ïVѰJÒt¢ÚË",NÀ5Œ€|ÊŸ^ÉäûÙöP-g}Rç‘\÷ݶËGFòzG_cÂÆ“ŒßгèÎ7Qé. + ãgíáXxEøOdùµã<áD›¾ÑH8£< ÂCe]… #µï“šªÊ‹Ç+¿ÿ¨Ä;)Ÿ%?1Sk2­`¤rF³(8@ùß‘úД±ÏkTLÿ=t\¯!˜Ö J¸çxÅrªq*> endobj 159 0 obj << /Length1 1470 /Length2 6897 /Length3 0 /Length 7877 /Filter /FlateDecode >> stream xÚw4\]Û6Ñ‚D¯ÑF”eFï½E] 3Æ £w¢·Ñ;ÑE'z z¢†D ¢¾Ižö>ïÿ¯õ}ë¬5g_wÛûºË^gؘµõxä H+¨2áÊÃÇ (hʉ@ ^ˆŸ€Mæ ‡þ)&`{E¹Àñÿ0P@AÁ®h™"Øm§‰DÔÜà>Ÿ°8Ÿˆ8àÄþ2D¢ÄŠ`w É PC" .l H'/ÌÖνÍ_K‡5'€OLL„û·;@Ί‚YƒM°«Ô½£5ÐCZà®^ÿ Á!içêê$zxxð‚]x‘([iNn€ÌÕ  u¢Ü¡À/Â-°#ôf¼l};˜Ër=¤« p˜5á‚öpC@ (zs€žªà±ñ‡±ÆÜ€?sàãåû;ÜŸÞ¿Á¿ÁÖÖHG'0 †°ØÀàPÀce ^WOWnùe†» Ñþ`w0 ¶Bü>9 ,§£ þIÏÅsruáuÁQþ ƒÎ²¢€tt„"\]~O†‚Z£Óîü£²¤ÂçO`C@l~‘€¸9 0g7¨ªâŸ&hÁ?2[¨+@‰‹ Î¨§µðWx}/'èo%ß/1šŸÒ `ƒ&õƒÙ@Ñ/°;àŠrƒúùü§â߈€Y»¬ ¶0Á?ÑÑb¨Í]|Ì` B÷ôëù{eŽn/÷úÇüw}J†54¸þ`ü·N^é ðáðð ||bBôÂïßaþNÀ_äKµÁ°?ú'¢* ûƒ:yñpÿ³-8þNÀ¿wÐB¢{ àø§õÍ@B kôßÿy~»üÿúþW”ÿ­õÿû@Ênpøo5Çoýÿ£;Âà^ [ÙÍ=šHôp þÛÔúÇ(Ë#áÿÖ©º‚ÑÃ!‡°…ÿD˜‹2Ì ц¹ZÛýÑAÕC@µ‘.°_W €‡ú/zܬÐ׉ ºR¿UPô4ý{K%„5òkìø…„` ìE€.< |øÐó zþnltE»Ðäü6HÁ¯z €r¿D¿‘˜þ‰€Vÿ 1ÐúoÄÇ'¢þ¢ã¸ü]ÃÖÚ …BñïnBSù ÿ¾1 PO¨5ÁÜ ÒZ"ÄþMÈÛ³j9:ž/£R“l_ S9y|æPmnDx/9«2ž-¡Nä^¾ë&YXSâ8–ýÄôÓg»¹/¼%Q§õÒ÷êé Ýñ/­³cTý ¶åjûðéyôe7|:û> rÀjÆìPcËqv%ÒÎ#?óèUñ¬í+›ù¢³Q%¬NxU:ÁkcT<Å–k•9Msו‡áöC²}Oâ©ã“I²ì7Lj/¸üvb }L–ùŸŸO{/–ëó»tÒ²ÒšÐ0`“ ³ûÈMV£þèSR§]dÃ`1Ó(ÝF v¬a,}ÿaå=Í·§A ¥ÄkãaqÖ:«lòï¾Áõ²ÛiÈrjEŠ'~ò=Í'pÑißüIå]¼'$]U(Cõj^‡tã@"NTù½_+…N¦/z·ßÊ&ž´¶"Á’°ÐÌUÒ½qK0—©™Ðø3gò`ey錙Z¼W…µŸøÈo:-$ê˜?ÑaΖ¬Ëg.²'ÖÏeÿ4cð#éâf€¢³•¥‘݀Ɇ‡AÅÂÝÍmC²9aV»'l®ÕƒödK«Â UtþuvÔ×ç’±ÙB9Â>÷—|+ÄÊáEÞÿ¨ü1…†10F2Oj¥¥H$+ƒqaI=;PB2 !—f»jæ¬õóÜSã=*¼NùiB¯ô™Ö8zMÿÄ¢_JÍ>«fÄòåa3á0'q<¯±Œ>—¼wü°…[CþÉïháTÀRWÆHv{¾7U¯1ö§:/“äNxy;·w‚aÂBca»÷ý"º„¾Òsù°Gƒ¼(æ‹"UÃÙj Rÿ™SE^:ýRí,éÜOêH­èMïzÂ$‡R…À–yEÕ/oôÇ ] z"Å'Þó…ØaeE¾Å ¸VRT^ö‘I'i»`ÕÒ}©½} -ve˜pòªî>PŸ#ElíDàXŽ ~ÔI %ä½ónã«å"S(‘ÒÎ]¹Åùu:FfƒD¤·érëÜ=P"Õ¡UÏÕÏmíË™#Ò‡ýi½:wo ÖRR‡’ÍÁ³·&r4Å"ÍÂá¦YgM»µ&DœnýIúf ‡:hÐYÀW+Õ9‰) 5>ÉªÚ ù‹LÄÙ æ—Õ ‹)‡S[qúƒU=E ¹ò‰Ûbwí"ö°e‹°H“È(¨­†Ô ‚(„½=ð“Ÿ/öÓÛ';©É2û@Yæ”=0\d[P+©¸ªÉzNÆÈ#“¾õåëBÄÙv™üçB”ªÞSÞ#’¤7lÉ?÷í[š$]ÖV(Ä8÷Leº÷˜T>O‰%HàN× j0y †õ‚éœAA>Ùþµ÷Ƙ-j»}aëK1ûð'©ž KuOB´"ËÎä~¿eÙV`€Ytã°¨q>.òIª¬ÒÿIë=£úü!K‚,wb½›g¢tÉ4•žrWXø÷8—™1­0&Õ ™öÁÙE•ü*%,·ƒIL>•q2¼ª%nL|dBú½•hHØ¡zg¬GBÀƒÀî4¶‰ÏèÒ²´à~ÊȘõ–iŠVáUV‡ÿf³œHLÃê¼Sãud®±•:}lNM(ûèù$©‹J5mCÂ8@1]Ðm‡G<ËiîìãÛ'|Ÿ¼Ø¯)%‡´¾«N)aó"[‘_Û>³Ä½hШçcÿ6ñƒï@i_¶–S¿ÊR~é̆­‘}ò¡8Ü‚¢ãÜca–äÄN^Ü_D“ÈsØAS‰‘Ï_í8uÃñI|Í Tï´mR_r¨$HTjÉ8¤Ýÿêë= ×¶C¥ƒr¾qd ¤|ö¨SF¹hTh8޲Š0dyÚeHħôHJú@i\9í-‹.d°qióz£O‹»H©ßÛFƒS`ˆÒÓ–:Žÿ‹'Sµ’1ù'¶f-£ô¬¤7r{g¹Í²†::_Éîv¶Ýܰ¢îBDnE9æy`ª suðÖÒͧz÷Š~ä¼\#]®¦ÉãF4Š=±*º •OøÌ)(z’óÁûù{iÕìGŠaÑÕl#ܹp åæƒ¡–Ø¥"¢(ìçG¶l2ùAŸoMzË8CdÊW²xØùž¨×Á éÒ‚Õ·8Æ÷ƒ¨v&¯…¢qœº"¸7pÕÞ,G-¢„-£’w§Ò¦»F!c6§ñb¯È, ŸÌI”¿–ݺ……eδ²0í(Y7ÜÎÀ02t_±òE [ÅQ}7NQ?,®,›Ç'–’òU«çC¯ W2I9I=žà/Lc›OC¬u×kTõõLTò¿°{!P‘Œ®–߯>¦[¢y-~þDô„9|êuùœ‡™"-n”jb¾¦ž&Å»58!¡ß_Úº6Çhôj—ìȱ‹£Óž*|a¾‹Aúq¼¹Lˆþ<™7¡C9Ö¿CÛÜ¢1JD©sé.ðY<˜ÿVùÖ"*õ‘^4‘%s‚^ã„P_£jVú} f‹ž» HBŠrÎ&0®hå߃|¢ÎŒ¹s€ cWx€‹O/¹ÿZ%‹`ô 0±¯Cºå°ú~åüiSúŠ©ýv!·’Ñi}/øë-÷ÚÝ„ÄÊØ5¼p¹\»¤ëþ§W«tƒ¥quºp[Ì¡ã[v±iÔàÉþøòšŽ¶·06r|ê«ÎüfGË ÝÑ3Å­ÉpòÇ‚íá¤F¯ïÆÕG‘Êö R¬ÖZ÷,Ú)|Ï.â\W¶öUJáéÀúy¶&Trç±Ü=NÝHÀS†¼d-º2deŸ%)=ØØ%ï›ÃÇ%ä²c{còÁ˜ëÅš¡ÄÇk Ú}··£ûéG_H2†±&úmU‰=Å^ß§Cy¼ë£¶#/Ó¥©Š¢Êk\òW·‹ËÔݲÚílYq‰Ñ̦˜Ixî0£1¶ûµÿ8º#5{}ŸŠ©ŸŒmÎý±óœ>W2%öV‹;IbÆuÜêÔ¹vDíh6në1Wœ6™#–Ûž×ö4Y4–µ|ÂáÄï}]USJ{ŠEáv¨& ¡Ýš(£SMn|Ö¡Áíû伆8·žˆÓ å d¬…?¶&Œ¿ÍB“ž°Hʶ¸a±ƒT~ñâÆ“\)½øãÒ±œpˆq0¸ú•ä2‘°‡—]Š)k«M÷¾Û›Â,çà“ ¶§3 ˆ(B³™¾ÁÒ+§Œe–R÷3ÍÌêéRíÄ'~âù»Ô}¶÷îн~i¯;gÂí™ÑÐ;†UÕŽ‘äP>²üÜå7`ر „l5* fR\SGµ‡Oèè;{BkÛlFî¯Ó–=@hÄ(@qÕ„ÄØ½¢æC Ôéï¯_×ÓM]¶ª¶ €Ì²›–îYh—´ —Q©/Ç]O©@~ÔÊò•¼Ê™¹Ê%ÿSo6b ¡LBqãâ²§ÌüáŒyB2¤ßÈ#¢¦Wãx aï@;lÈšœ¸J¥×R Këϰר ê·³$5ý‚"ØîH¼ Y)8fGAëë¤ã93ˆÊ·6 ùÀÛ«ú¯Æƒº¦\·E˜ Ÿ!êTâx4Nˆâ”âiÆÖ(?À»¾^·æyVÉk­2tý¸ä³`‰#MôF;í%'ëÕ·lió¥¯>o«ðÏžª©™úæW'RÛ+Ut\MŸjT‡xöyË·6âŽvKÚס†Þ—o£P%&sAõå7]Ž}2ž:½ÞÑZߊI§•$ Ó-eŽs ^½F±›É¼¨v?´îËWVësä†ß2W:ÈH‘éî›GHfuò¯­Á^dÝûô.¸ø@f[Ý=*Ž_òR.Q#¢ÃS[ò`=ذ۴\®ßÕBî$y|SÂÈ•Yde¬„4pŸz}ǸšÉáPPa‹Ub !ÕV¼¦œ¢Ž¸w"y÷“+þ§ÝÆJ• ¤ýäBø*ÞTÖ°Xз+Å›*;,ᾤvàÄNV q߬oÅJ\ ‡×§\«I2‡‰#ÿž}zýTÊîªæÚ{ªï˜Q‡èOòhŸðúû{FƒêË|Õ¶É /äút5^ñ“LŠü•Ø •æz„ñÚ$*·£{\Þ+Ü1û(ÂLÕÆkzÔÚ´qº\2¼É™3¾-½kè0šg«á²|—h“ÉôàÁØï±´½­ŽMôø¥G|˜ ²Í8ì:Þ›ZÔv({Y”Ÿ/õ(ø(‚Ääìĸô–±ú›a„eãRÁ5\{Õ÷‡|;éŒLËm:>(ß]×¥ŠÝÖ–ö™A?Í·J&vÎ$ö,;äGzç²OÉ„Ù//B{ïûÜ=§Ì&äºÉØ K"Úö_XµÇH>,Jì·ÛrÝÒV8Ñ_BrixFª&%ÈžÓ_c04ÍãD_Œ.!ÃÏi²o…6ñâe‡ƒYv—„¯Rç™ÓYÃižNœÏ§Í^ZîÞ ZA] ‘døÄ»Lù˜§àö.äÝÏÏ’;qœ| Åö7o€Ñmä¤g¬0!=é$Ú‚{ó΋Z8S{C²_µ¦Ó»§ùäM%Tie†’ÕϾϽ,= õ&˜UŒki“r[wf‚gUâüÜR‰#w,ïºCI@f2VCþU½æ,‡Ø2Up¢ÖpNã.„ÓË$?€Òoæ8<#ž³ÓÍ8äš³'h€Œ¼{^p½µ"90ùŠzúISZý «:Ø¥á‹sýjaÂ?ª4rUôˆkËÌ4.üç笺vnmt1W/›LSdزäÖ§Ýþa„¡Ïà¹Áãâ` ·z§Þå[‚ÝQ¦E°±¾ï~¤ -õ ¦oi3€}šÚvA&t*7 g-ÊÃ\K»7J¤é¢KxÅ´phN^yÃßmZ—‚R[w²±Zö(ƒöM¥߇•˜‹ïl(w&ˆÞשÑLx@ãÌ€IÕµ”\䢄&¿¨Sa±ë¡ÑšóÛ¬e¤]¤enú¦•P`šbR =ú ïËZˆÝ¼JoŒ”¢ÏÐæFŸÊ†YzëãWÔæâ)»ƒZÃ4ñdìâ(z·ê²*ÆÑÍù"xb½ò!Mù¡Ì©— † œ8ÕÚÎÖZ$Õ“W¶Èø‘­Üªo«\”JËýºS"ð}87˪`•äãvÎO^Ü£$ÓRØÃA‰v%­˜Žµ© Ý!"éyì}뜖=ž(ÿz’zÞæb×áé—ReR{‚VüŽÀ’5·Ú´[ÒÙxdþoV-Æ)X9»¾+Ð. ¦äå6ZÞh öÉÑýA½ÑwÅœÎRÇ’!ç=f’º›R‘Çb£[«r /ˆät œǺT`¡S{Þ¦š±Óßš½®ájt7úéc&ÌÙÃÙrR7:°QŠ9½Ô‹&ë`ª|?V'¾ŒcWãy^m`jÌH¶Þ§Ö÷°EP_ã‹´ýQÖ¿/V[xÜî!Í,­ ¸&ãÈÜæuf š]Šl‹T÷m"=Òåc>–îe¼¬ÇdßHØÅÃohT?/r(ÿ¼üÖÿÊ.{y(´?S¡:½¾ö™àƒälWÄrOÄùeø j”Ê>n"¡§Û£éÌtøš~ÛN:Zò–ÅÎf¯Ø\ΆB¨3:–!nxŽË˜NÃ^瘮•FNðñ“ðQ™vÔ+6ä¼<ÏwãIm{@6u8Uöp¿–²”ó=£ÀÂ×pñ•>EÐÓžmÞjAŒ7Äáe3]9Òî$q{Ë3‚¦àÙ¢&VB¼¶™ œþ¨]¸&§T§×HÅ!•v…íÄfŠ.iá‡ÙW÷×$­øX|Ft eNݬî³&ÖŸTiušd´‹%ýP x°~­Ý¸£ÜugàôÅ.y× åÝ÷n÷‘‡Ž%Ñ^i/£žY­¦‘®Äù«Ó”F˾ŒÅLNŒö˜¹ÁÄ¢æÉ+Æ|D²ÿÌÒ; —¼¹úÇ0|½ÏC'jRè»$Ù„VûNy÷Þ .rxŠ.;ý 錰é¡QÔÙÛE¹YÞ%‰j.¿ˆŠÌ÷§_®¿(Ý•ÙÐT¾ð[Þ*ùž« G+^Ã60äB&ÀQ˜Ùáî uT‚ï ’s üýî0 «ef¯T:šºlì •—ƒÜW1„ܾ<…Ypn¨QbTØ<’Þæïž_é»ÈµBÝŒg½ÌÌÆ±*s‰y ï$¬f.ôð-ßT„4=ß´{Ýóc‡?[<ûç§,›–[ßÂqŒ÷Í0[þÅs;Æo#·#õ¦|y²{è¤ß¸)4{ÓUhŽaAllT\$:0lן¥=cœ?³§_ø1 Òf ;`ãÉ.n:"åiJ©ð…ƒ ßq©‹6®¯¦Þ'ûÈéF\³ãpöÒFy;ñmûBù¸*7HÚ—±$yµ/_f žõ¦P!º\œe°/¹¨MOq¦No§§DÊÂò2îòÁs\¯Éù~ËU½_þYK'xdq<õº¹£h˜ g”2[йÂS=–·ú)‰ŽíöèÎ3^ÇSÀd½›õ¢cœ0wéòn ¹7¡Âm#Ònø´Rî•«Q$™ùÁ{Œå)áYÁ“ÏùEYb£,ª¤`Õynó76$µt¸³e »·¬*(‰—F"ƒ'’^ºØª> endobj 161 0 obj << /Length1 1821 /Length2 11700 /Length3 0 /Length 12839 /Filter /FlateDecode >> stream xÚweTX.®Á=h,8»»w Ö@c;Á]—à4¸Ü݃;‚»Vn> ïˆG>€„±+Ø ð ±9¡P‹Cì=Á–ί™þó@kJ`åååfüó8@Ôä65¶|0v¶Ù¾f45¶¨ALÁ gÿ A+`éìlϺ¹¹1Û:1C-„èn`gK€*È äè 2ü! hl úK3 5@Ýìô/—ÄÜÙÍØx5Ø€MAvN¯‡\ìÌ@Ž€×ü5Y€’=Èî_d…ÿ¾+3ë_áþ}ú@`»?›šBlíí<Àvs°  $¥ÀììîÌ0¶3ûƒhlãy=oìj ¶16y%üY¼1@JT`üªñß LÁöÎNÌN`›?TÿózÑ’vfâ[[³ÊõI€A¦¯7ïü«ÅÖv7;¯¿±9ØÎÌü)f.ö@ ;°ƒ HVâ߬WÊß6 3€“………››r€ÜM-$Q÷°ýéüÓüªÃÇËb0•ò›ƒ^¿P¼œŒ]AgG×?ÿPXYf`Sg€ Èl‡òwôW3Èü_øu Áî=–×!d°üñùë—Á뜙Aìl<þ¦ÿÙh ¦ºŽ¨¬ Ã_¢ÿr‹‰AÜ^Ll¼&6N+7€›“àóß‘þºƒÿèÿÓªl þw}ÿˆ(kgðþKÆëýýGŠë¿çƒößëCøï Š×¹hÿ^}NÓ×?¬ÿßËðç‘ÿ×üåÿc þ·&)›?´ÿ¡ü_ c[°Ç¿9¯“íâüº% ¯»b÷¿T-п–[ bcö¿>Ygã×]µ³xw&VfŽÙÁNR`w™2ØÙÔò_óôŸv¼f°Û”!Nà?^ ×S,,ÿã{]ASë×WÆéµiº@¯ößy%íL!f¬"'ÀØÑÑØåu^'À‹õugÍ@îŽ9Èlq~=xUè0‡8¢üÑZ..PìÓŸˆû)ü¸À!vPíoĪÿ…x_™Æ#Ðä/ô‡* Ù? +ú rý\^à/«ÅÜüoÈö ÁAÎ? ÄÅññ^ë²ø|-Ìòÿ¾–öT¯Ó´ýGæ×Jíþ_+ü¾FþG^Ö×ÈN×õêtzÝé¿Ý¯Wéü·û5”³¥#èoᯠ:»ý3üëºüCö«ÿ_áþ«ß¦.ŽŽ¯O㟫ù: ÿÁ¾Ã ;ÈeqbÊdUÔz[%JìÆ´3ÆÆÖwq‰¤µ-I产 .pwÁž¹ Ú9³y·Ž}ÄVüÒ`­Ïbm¸æɇ¿XÛ on²Åè=-xä¤à¶+ßÑ¡kÄngfÿ»QuÀíRdšŽ€Ñálg6ã@Zà}cÅM¹åoDšú_Ìo`Æ¢# yxØßÀµ‰f´UˆU‹NÏ´ËR9‹Œ'¼“:¸KífãÜì[*e„o¤¢ÙË_f ¥ìÿàz+o4˜¦Þþ!IøGpÙäOkâ4¢ü¥\~?má¡ßÿ|!UnDº.×çcˆ3¯’ «â¿£l=[ psI?íM‹ƒA0Úc5‰S]EíÄÁ}B6õãD¯ÒEܶ q’¦3)÷³¿I÷3—Fn W;œ Ãá:SÔÂÚàÓPõ–dÜÏý›ÑÒÍEë‚^ïÂÒ ÂªÀJË6mÏ€ðͣᤕ+ö“ïX^_Û¼pL‰©ºóƒ±á’Ê'²í•™·©ëI v›±â–jàDð¿Ž0Ôïó‹ÄYÈO¡á»AOj(~–Y|”šËù01Ù™-wvø»­—™lÁ÷ÇêÓ7œÃ+ÝP¿k&Sú„Ö7ÜØ£Å›¬O³/„ŽLndµ£"§w;bj•{8ûÞë ¨Ä(h-r£3FïÒ+±ï5üãnò¬Û­vPüEâÌEùÍ)…¢×vqÙ©tK)ê¼]x [öŒ¹¦œŠ—ßžo1©©ñ…;%R½É1;01€ ÒÿQMÊõ\»7ò›@\ê'ÚM±“Þ'(.ñ‘ÆU¯U’ŠºC6´øc–ü†O,h–|> ‚Àì—rRØü(ßu\ox>h(DzÒÖµ;ñ#©Ô ­ò•¬…n¸þ*}¹uF Æì…I?ž Ëé­_5žÑfØAØ’HœÝi.™£Du¿Eæ‘3¾ŸñGÁ$`é}¾A˜2˜ž`¡;l·±2D‹–§Õº$Ü‚`;éB)Ó»=Å&=¸Ñ+éYö €:rMotÌøåS/VÒ²AüÍhÍvÔ„ùÇøš… ù+I¿PÝDqy_ðå*Q2„V‰Ý,˜šÔ Š“¢;ç›-ˆÞ·"rE9&?dޏ :Ú¿xÉ÷†NèÙL®ÖR ˜L@HLxj=ÖCüÒ‹çqåJü™å˜*ºè_Õ¬ ƒûÓØ‰%APÕ• p§Í)£YO ¤çñ? §šOaj¶ë8¤x—1ÊC°º»ãá‹Ï†O ¿5kø¿GYþ>j9H#:¬Ö³Ç#:ÍíXëã/>Ž;kìHú®ÞPäâ6;?÷¢ÐaD%…ã±=è¾y[y_j¸ÛÒ!2½£rBæû%Ó´¹Ž‰½™…SJÎu—iÑþÙÞŒ½Éqžæ]p -_mNoÆs!´¯ÔþÝËÊ.îúH¦!³švü6•$ZɃõ+.åWÉd¥-ÇWÛT°Ã¸+ÉJ?Y h `†o¥ÀÔZîþÄŽ4ù ƒ³K]ðe˜Ö`Š®‘x”6•æB«Tr£dCìÔ$õ .Ä(ÄüÞ¾fî[zÊ}pˆ×ÃÚfI°kËÉ8•HÕÓ ¢¨ˆh&ŒBL=f[…^I…Ž §…ÏñW§Hú7ËÖNMÉŠ!(õžQîѸJõ¹bfw€Î=0Zð„Þ9#ÄÓ¾„ʽ hØpPƒþ7æ÷¯æP“Ž-¨õ Â)ÙRá‘-•|î|*1Z %8jþˆéŠÍ ý_À2Ž\ªiZGt¯Êc+üsI„ %ê^Ñ,g"õ@b!ç<(zÅ{Ýu¦ÈT)¸m[\Ù¨pQì{î!äo€*¡µzæ3Í/ŸHhªеÅàºÅ}9)lÈ(’×å -ð–_7|Ü7¯Ñäåñ´Ü±±8ضÅpÎáö´' 0"%ïuïñ4á2E¯‘5ž»,»äé5FV’Æ/¼ |ß7<™ck›í*m.Íôéayh‹Tˆ´ªà,1à<ØÇ›­þ*¥ÑkÒÿú­|˜ kÏv5a‘³?Y$Zž`à‡ÎAnìa¶tmáSí_ã=AÆ †%Lœ;l½…Sv zWBØ|ùLƒ¾l¿q—Ålã©}1Ç1JœÑø(ÊjšnŽ$œvqÛg!7ù,躚ÓÐtÒ¥AïiÏ ÚÀ/LÄv뜖ìg²L>%hÞ¿šzÞoÓ1|ŠýäÐÙzÜ£©t„ ÛKI‹Mòítš’( ‚ýÝ?%Sg%J„ݰqQ2DëéY+ƒñ†æç)§7vi‚µGÚgøVÔÍ©˜cH"–r0¡+ž“”æ ¸cc5ùNícÎe®³p¯xGuJ1Ì-#ÊOÄcy±åßÎrÄ/-E‡Ìi[š²më¸0t ðfs–Ý\Ñ‘P·'÷s¿È[û?,—äÑܾîf5‚DT¸¦(}™bŒ}ÉxgÕÛã0”•觪@C…UŽ3VïÒˆí|¶$àOlh¶äà!ܳk?ÙÚí¤@¤$iKI-?ï1Jgäé>͘²'æf³O˜o€µ*èA ú’äê[Éɾ›ØsæEߎ0))%¤LÔ¨·,NáOç*Vj|—ðìwyóùÓÄ0[¯¥&}¶ù홸»ÜûwÛOÆ"¿ÌrÉú¢$)ƒ]]×Z•ªj—nOkYMäw*¦ô`@>î¿ÊºÐŸ­WÅü½æéyc&»ôÄÀÕsgLáq™¾lÞ<¹aº¬lì%½{óº!]N˜Ý»#3ÚÁKr}¬¹¥~Ò…fO(×”¼pCg×K°õzBÑ—äÃÓWâe“zvL¢b–¥ºyŸG*g¥Ûý©Æûä‚—º2J(û߸WWåx²*Ö¨—Èt®ÙÏŠÝ å–}‚‡zgUjRj Ív$lé©FÒ{íÁÞvÙ"6Ç B¨r÷Th~Œ'S?¡Ü ê]³ ©Ø8²Z ʉ ÏlóÚe°/ì æŸ…êF¯Ð– '‡8SB7³2Rª³Oô ótê]p诳á»K àŠÐ#[Uh¨å(ƒ¾ñ"b3%îvÚ˜^ðpVÝá£ADa%hÙº^ˆ…yìèðp½`³ú™1•È ~œ8`‰í)›pвY@KµÕì—b.RSègK‘^7l¼=–’.Å;Ê´0fd&—!·BѦ`üÎ'=Q¥hwfËU4A(Òʨi—m‘%Ń8={á­ô†¬ï&n]ඦ|ª§–4úÅ!6Áiï¸ CŠ–§«ç½É%)4.¾9èBã!CâÈ+~æ+ùðReõNÃßšd‘H®Ü¨ô éñišXrWc÷½½&Õdá%Ý <ÍÖjY! ‰ï[‚"ëªòxæ>s¡Ø™ˆ¡+·Ò“üîGšJ!ŸSÁsµ‹ÎZ–ÂF·ƒؽV©ƒ6OEÿF›öi#Ã5d¢ö)½ÙÒ Î_JJQ§ñùx]ì7ü%2ÎGþ&69 þ#m)ÂÊNŠ­¸oÕ•ÎXë'¸aÎ(™œÎCî ‰Kß`Õœ«zm¤õy¨ñèƒyI_öÏ«õÃiXnnãÀïc¨ v¢_G)ƒtxB±zd⩵ÃÝ›ÞÐÃÁìz¨ð¹)N”}â)D|¶g!Šx‚ª{n}Ùy!‘½i/W††éCZÁÔñÖT WÕx~S/ÙÏ17Æ2p jhü»”ÑØ :›ÑÁa¯}qØû!*=uË•º|ÿ$Ï÷t$ªË´KñPš;®ÅúlæÄ¿‚g ˜-˜¹6’šséàÅFŠ'U5(žMvÇ‘š«ºà1Wã4ÜZwžº;Èâ"ûÍz5¦;Ú쬔m»ý:$ÑÓ¹H>!i'~V&4ÂDåÓÍMAý)Ö¢¦³´ÄJ$.{9²¼‘ÐFg·!E:p’Åm»u¢Îæ‘ë«Úv™“ðÕãöÌ(:[&KpHÏÒݬzwYë6´Z(éÙ¡j³#ÝVý«éã‡aÃÏŒçù¥Aª3‰æ‚LD|¿&p/±Ö7Zj˦Ý?^@œ™äk'·›W`ùîiDb–?©BhóbGlI±ÚÉÑëƒeéä«+»u¿»3Ì•"‚Ññºòã³¢ÚG¿UD‡?‰%‰]²ë5‚ÁR)Ë_[—Òª Mƒ;‘$?`à$ÄFƒ¶’T'ÞÛÄöácÝvzê½_ážtˆ%3=ÜŸ¨½ä²ü"€€éÔº=ÚàÆôõtaÁ8~ÕÌr=¦VÓ¦„¹¢Rß<§]Ž™¦ÂYÞílÙÎð(^GiÑÓ‘euŽ”¢EOl%¿ÞŠÿB°mþÅ'GEºT즞;Ž-æ&Æʬ惿Ótêëÿ1`røÔ]8tÜæµ„)¹•3oŸík=<ÍİíƒõQ%þ†Ä¯Âl’Í}Î X\ißñ=¯èF;b¶¦èæ †Šy»Â Øp¸sxãXNƒa3C-sÒc7¯xN%CÚ6Ï4iìÕ¬Ä<­Í¹ŠƒžÐÌÊ…²qa_”½vYEýD'¦({òcĽ,™ßMÐ6â)Wˈ¼·ì9‘¿éÄ˜àƒ±† Qžð»">&ð¾½Txù¹½ÄŽÅd°pñ…Þ#/æTçÕŽ¨ÇùŽ\‘Æé´¼èNòx+þÐØª#Ù¢Ïé®W64œÍ§<3‘F~iæËA߃8¸¦P8DÌvY–é Ëÿˆ7¤Æîò¶c Ooïøj³Éa·Òú˜™¬/÷–Φîžc’jw…¸þ /3Ã=@mòšû}?ÉÇ )?ýùG€ÍWªtµ¥ø/§tL¬KþˆÂ4¢\«Éé•@yÚ€½žVÖ=I®ááLÑ}·»©l-Ø=C ú¥d…x•š´|Ræe ÈÓZQÐdL¥6™Ÿ‚MFä¶ZÅVYñ¡[!CŸ\W¾?J︦Éà„›`‹d3*2[©CSm|–¨à¬ÉN!Øÿœ0+Ð$‡.øk¨xP‡ ªœN×wÊ:ðæ=ÃXS_é‘ä¹kRÛ7Vhå7Õ¥E¶:™q³;©dæ~èV"¨œˆÅ¼hÁWq*5ïòÄP¦ iNÚP³Ÿ'?1‡éŠzÓ4{7µSx…ïe.õºïcuÓ: Ô½“”KrsþРŸV>è2Ž6 ža+0?XOqRoÒè,_4{¦ß´¤¼Ú-çR_qºk[ŠWÒò8S2·iÔœÙ7Á7W6„u©?Þw6 ÜùÖþДs}Ìÿ ø„ÛIdŽË”0'ÐAæ­€ý³+ÀâxÝÏs>|a]±ø>ój¥†‰1˜×•ÏtkösN=JÌ›®rˇÒMö}ÍKRžŒÆŒÊՉݥŽLãû_šwÐ7“²ºë Ò`”’Î0ÏÄÓ[©£;üiµÂÓ<èu¼ä̉¦HcOã´m"Ë/éø¼Ù=Úc´w¥p:¼‘5¢!û ©Ò…0·¹À »'05õ×T&~²>75ÝÆ²Ìf³ ¤•‡ù@Ì£ôm§GMþb½ý™Ï‹0qc%6#Tc~Rô¢QŸÒò)™mE}¬Õãc ¯‡žÑŸ•)ú&)´ ·L~ EÕGÿþ¡”Ò+/¬jæèóMÁÐZðS‚]ïfø$Ü&¦í}ΑFóÃüvyÑ´ªHÒÛÍHáxv–jØR+u?·Û ô¯ÐFέJ§ŽEx?„iƒ&ï±Õ¿†E„t_xk°{ªíÓtê߆†WÓãX±nÂÀŃL{ÄòÖ”dlö‡w²Žä¼zeDÛy±“7ûÃ:*ú³T“II£¢|§©Óî6ÆLóÓ"F¹U­ÜRnªjªÖ—ìÑcd½¤Ÿ&´×B8íDú”ãI©QÛ@2k¸±ÖXc¶.øÛüp;ëÀù"¯×gŹQ!¯n7[Ž|È ‹Õ˜Ø\7ú1Íg£Å¶Ù ;ÚBª?ìó“d‚ÆÜLUžz«âÈû¢j™/ N-v5ŽQèF¤Ü†}¬ÉÓfçZ8äõ¨&P»žßvqW<‰x¼.Šƒ}çC­Ò|ô=#K[25è#ǤãN%`6$1t&èFJ-ß7&d©´ÈûK®ò€Å7’H8ÞªÚ÷ye·­‘(Ë ©¿7Åüyp/†2)ÞÖ§žˆ€¹ ƒL >’ÖrìcäÁC¼ýA’M ½'yÁá(ÿ¹CÚ@pWHídU¬£$tiã¸üS>KŸè»Vdþ`r¿¦Ú­… œ ©Å~Xä)aûÈú;ÊÁ^#v—ã¡2m"¡ZAe!KÓ(é½V±ø/6QD¾ùéf’ãEx‚PñŠÆì,ƒ¢bv¼ÃÒo$aöŸ½1¨ë"T6-Ìš‚§òÏ[ó0Oìü}èµ®T餰ܵo‹_HhôÔžŸ)^Ý6Á&àóEx੊\ A›¨Ù^û ”tAL3Ž èãX GC;²^г$Í(Æ mªÈbÌo`WÂÄ$Z¥"{* 1ød.DÄ ’[,hæˆLÕ)t¸MØ Rí,Û)ÝØ²Yš·Oåy‹@£¸Ä·R;ï\&º¾Ü­ãÔlj݇€§-¾v¦Ñxõ&ºŠ  ¡½ €H3§uþÌ^(Öi™á¨€ItöKRsw_unà5uu>õ¦$äRñ蕾ª2»|¶ïÑl2­uý'ù8ÉwCW9e?õ; àžSîÚÈKK>rGQߡѦïù~‡î¸÷Ö”],û”áuh¡ø¦ú[}‰kv¿jZžÚ—ØÂºù=5:bÏ['Öã~ %6ß]*4‰R³ˆð²¡O^Eq†Ž© Z¶&õð¿)¹¾èÞû‘]«A*ž{g?,ì“[SÞúi? ð ¿Á™Y' Œ: )~!õÁÂi´ÍÿAÞVç<ݾ§|‰i·B+ÈXßùqryJ,îžs~¨óSqPó€ÓWdaÖo]$!b÷7=(—y‡ï¯ÈzZ3Ò*ÒÎýÙòN6[¾Ó¿ég°‚vîÿ~Kù‘aÅ.s!õ¢Ž:š^ªK>[ƒâ°æÖßÁ©ÓÔï ×*Þ)4°aS/NG•äȪcžÙã:í,ävo„áiÁ5ÖŠ¸Ù†°›ù¡¦–Çê ëítíÍ<¯ëÞ7M=)eC‘VÖè À0ŽÜe±è!‚Ägîݹ‚£;[î-«³d§z«ø•Ûþ(ÑÛt¶ˆj¤Ÿ†Æù¬Ú8 Jâd\Á’X}=´Ñè¼µ~ä礖-zl³”5èâÚ½Z6UØ\&S×"‹É´@¯ìÊÉ÷s¬®ÍgÚ‘c2ºytÕyi¶º¦ž´9%”­øÖŸ¡õ×÷ýßâ!TðœñI îÚüÆôÏòj ktí'Æ)âþŠJ¥‹çp0\/\s,ög˜Ò‹ÐÓKý’X]œó}]ëKÓÃ%¿K'Ôiä®ù„\çí‰o1…Èãx¡¸<>o‘iíêɧœæAæÙÜjcZºÙ&±nwÔÙ´;„9ü}oS»’§bîÌÊQZ®É 7Û{EåhÂûœ Ùé¤È'vÿg„uþ’³VÚYšŽ:Œ·^÷<ìZôâçOO“µò’Sz¾n8. A£DcxŠ·Çþ,‡ã¦°”†§£5Øl± 4·mÅVy]u'áwºÍ8¤µK÷žaãÌzM ÂÓ‚úÜ鋞»LfŸR|ÍG4þäŒìCؽ‡„düùßô÷™ñºú€ïq¬ž±ÄÈgsÊ~‰³ãºƒ˜GRË‹ü¶ºVÄ0B2 ­YPJi»x•¼`öó·Ö\ÎóP~ìRu™ý ^Y½¾]¹WÈ[*ð ®#eÕ…u`i"Ú£}•‚F×Z3/"‘Æ’TŸÃ*˜€ÁL÷t“BájC•š÷'°pÉôeî—Á%X=N(­5nwüì“λ顂ùïeð©OßÒÄ[Æ×ÛÎVãÀˆ¶IC=¦Ý(±gç‚h°f,q îím•øèˆæîUk¾kÏ–,Úô™¿¶¶~ïV%†Ü« @:\÷P‚©r^1èÚù.aÇ/è"ÝY«ñ°èCÍ/è8Jú¬=Íq1¹çÙó’‹É5©ïùOâj:ù¢"gYâ¢dPvFQU!D¤oX£¿›!`”Ð X5¥ƒ>ya>&¾ï¢v‰£Ä —c}6_; &¤Æ/*¬Ô˜QqÖ«™³ü¨)çÉ,ȬGÀÆu>†´çåá¹Ý\´½5«x°÷~oÇÝÜÀ­6Âp*üÄ•ÿÝÞ”b=¿‰g´9”œÉÔ´DÛݸ¯G ½4}Ho¥Hï²=#1+©ÔŒ:šSÂMU$8}‘~k¡,n¹×¼ÝÇßœÕ 8¿å‡6+ÛqÞG;Ãooß# g°•V&ÝҟѺâžÑ‚óÊfìRR÷פwÎ $e€æ²4¾Ø@ÇpLT|D¬-O»ú4Á¡C›Šôë¦Ò(V.íü‘𝣷 WªˆdæÇ¦vßSÁ›,ì Ìß¿ e/g™è†<ÓÈ®½¬=K4¦wn4B_æ~jÉ/˜ÄóvN“’I¢sê`®<Ñ3iP^ü"ý]Ü-Îå籪ݔcå=]{Àê©ÛPQ]—ÙÝ¢M¸ÉÊ.áU,œµí×kóa¼wy/¥ ë-Ú‚g÷(ÊÕ®!¿OBÿÂ-ÿá¾ú>öô³h9e&y¿ä{9ËlHHï7ÏÃG‡7¤7tû¼ÙKøü©K¸C†=V»È\½[YrY*}m´+.2TÚø¬T?Ï%ïI¸¤—Î&eÂÛçì/8QÁAË΂<_O–½Úú˜?Úÿìþžµ’0à|A+/3~¥rá8œq³$ ¦ÙžcP"]bö¥T!wµª]ã,t‡<-`ºÓÛÒÒÅ!0öÀwG´\жŽEk4ÄŒ€B ­áÞMi5Ü"üžƒÕhê9¦Ñ ­Í<\Ú yLÝ6Û&=§âÓZ]78±øÇ§Æ2£9,=}aâ®CK—»‘Ž«?±”ìã{¯ÆùíÚ–·s ¥s‡Q»˜&ÃÜ2‰œë=;9ȩ1€>ÅoCV…ˆRõ‰ ¾™)ÁaŽ2ᆹ†FcNŸRä‘K8DÛçÚÑFå•í[$xƉºLÃÅŽ±y9ÿ³ ·…uN6ÎØç~ðØ*"ÂýæÐ#rã6¿ú›"yÕu…¨ËùIAÉ1ó<ŽÆ˜ÏÙ… ÍŽ{0ªEüãz+–²~»òd(áòYR·wþ¥1ÊE¹ƒ[£ž WAµhšfb¼öÙÖù 6Ä´È7•oAIΩ‚`>Ðݱfù|¨¿ÊþZs!Íá#µ‚J«¡öq{øwen{c„¢1žæñÌsUZpq;RLmU¡=r›¾ÄóüCf˜½’°±R‡ôíï[wºœRÝ©OÖëüšBå¢ôrxlú¥àËeÖ?âŪ>ÃD)Úë½3ÁLCÏ?ÂÐ{÷ñqT[ð„Róª6[dz´m7›-RLÕ,½•ùF©vMôνÒÀù%†#3‚÷rÎýT€ã;šHœšÈ€ÄH•Àöämí7wág’›Ì›*ú±ò]©Üwé= '¿ 0mÜd¹@.-žBà;iÜmôž4iÇ´n ,zoÎèL8þ³Â E¢EŽù_Sôí}n§5;`³å‹™N¹ e›O:ª¢ðI¹ß“j®Æwo3ÓöPD“¦–ÇÃ$ö$„7S1éOá›í+%N.Æmn¥’Ÿ™m1ð:#{†~`q&òšÏ ÒKÎß+9±>Oª2:ãÊÀºüþæOà¿e§0Áyx s´?2Dì鯵+ÎðV¾—Ÿ½Úmúòãi¡½H¸´äJ+£,1ÔjtÈ¥ÑoB8‡é¢Gn"aûÉ`[¦¼¨cé&V_ÂfšîS¹7Tç)-¢W_Söc0SÒß 4WëñË•ÿ.‹ß!ì]W{õ!ûFoIX˜G o,fK¥Ö˜‘rè4Þ¡¬uJCâ&, ­ËûHÄØ6Û]êæK][é0³üHdcä&gOÑ–ÌZlÏrPtÆ0Kt ¿Mì[/®£N9ו´©$ÞþÿãêÃ/#ðhæo}mCå“`Ÿ6a¥#Câ­9¹Pì-'W¶Ž‚å¸CÑÄ­/âFmì!àêUXÆl=Ê-ÊØíä,©oùñ“Iaî´„2¼d[EWƒÒï¦ÌlÏo à&m0®IWCÞ’ëAº…%4Jæ[ON)u@ËlóÏ«é!‘S}±'0©qØÖcw ;ëv; '¿Z+2PÒ¯¬#q°ße»âšeq–º(Ë Ê›ôD^RZ™à½Ù&’U…†yì]Cck‘„+‹=Š'°È@ê­Zq¯ç)âaDf÷”žUŠÛª4bƒ~ºo¯0¿è~C&@¾é˜¸ÉžüfÇIÂî«BD®>q^ÜdÍëÁG((ú”aÅ+~{ñˆªƒ–§ Þ9 ×>òr?AÄÄ‚Žu­ƒ1Øì¯XÆë‡7/ôq˜Fí}¡¤týy'4 š=Šs>aF…,9:Mx× ªIŽ6åî!–ÜBLgaZ7!ƒ mscO¼yðGй$¹¨âünnâ+‚ì¦é+úè°£FmM™r©(žy×ì B=š¦Då7©\—»ËkÑäù%®¾„ä!6%69pæûo;ë´®XÑB¨Ùyy/Üz*™íÓpú4íδÔi`Qßsì'¯OA¼îµ‡²Z¶71quÛ‚¤l @Á:oÉFúé Pgœ€ÍBÛèõ0ÃWÎt… 8Êæ‘ÃþVÅ_ƒ`‘³1ÊÐmŃbPÉìÓ>‚¶íê6Ñ\ÑkEýSv&ß!ZÛr?Æ”Z±ïc~ííÛX(5Í=UÌ…YanbuÀ¿xè±´×æ Pr`Eò²Â@ôÙ§à¤ÂM#©än¸aœa~/ ³%GÕsäqˆH6é rôîÒwmX¶‡²Ô9L®j?BV¯r0l¹±¾6™õˆ„ÔþZ7ŽÿÞ–[kDóe‰£ÃÔPÊø®ôq5|ûmXCv®BèÃBSHf^ÿÛ5Ô4BñîZV ÷IšÈÕçüŸtàÙe[w"S‚›¯Qƒµ’ ¡é¨'{¶1$ü¡¼ˆ×3a:D›2­í«sF1ø%%%5öí©Óß ¾Ü©¸•ÁhZ—~ ­t0Áá4M!aÆwÇ ±¸†Rpâ>”‘ò3B‹‹4œ½Ú#O@,ÚÒ™Q¤†“Ú·F‚Q“úuXü>v­9ZØÚ—«Cšø»ð=]/-ª•Þç¯ W™`©„N-W°]q_ÒA¿ &Dz c˜Ìlà ëï>SCCÙ6ÿåéuªwÛùö!n¢´‘ùÌï>uíÝ®_4ô¦H»5ÌÓ³ ¥ýøž„òµÆ@™LñÍÕÐlx袟œî¶úY13nº8TMê}(ÄÚTÿ)€ÃW½³Þ¾ZmŒH«ûN‡wJè= q.I`'Z\îTŠ Ã#¢ÜŸ¬ƒJoJŽT~T[.¤bRKÿ>ÞÈ”X”ªÏá?#¢×!O9ëéð­^ààbÞŠ¼§ºoTdÍdÔ×:[µKùøþåJpÐq TE™PÓA ¾È({¡Öø¹Õ;@MÍ@„ˆÂ"¤(?/ ‚g!)ï,%‰ð,»*‹§fÆÔgùøÕ3̾ÎF¸rêÆ@¼ý'uiÜ7§ï%âšíÂÞYãj£öüGÿÓ‰9‘fó)†¼ÄU·a‡^™ˆ6 ñ¾P—æ‰^ÎÛ “=b>d÷C‘Ȥ¨1Ž¢qO†%ßÇT帕’r¥·ƒ<~h°‰/£M܈ˆ2‚ª¦ 2±®¬ih(VÀׯFÈnÐumÈ3½ÜZžz‹ Æ“DÀêàiÔ±Ö!OðxlŠÉK´ºº±KSQˆH¼]o£h1!ÖþqÃôqÆD26þC—•áÄjW>Î=ë'OòlÂÞë|?bÔGú†—þ<7WÙ©iÏÁAØ{†UAê[Á[_>,‰ðŲªäü`$Ñœ}I͙ޅmëß”›¥Š„ôi-œÕ>§í_t‰WOá[[$ÈY5­HâÒgÝyÞX~½ÁžË^7Ìs#ÉÆT›ÌUûHµëÛTÐ;iòȬc!ø[óFêmCÕÞèÕÏ㣟BœÁA=ªYÁyçR²[Þ³¼]sÊÞQä–°ãc‘—ñ®)]ž$Düªó³ðnº£Žú$¶¶ö¨,â*·!—¿~̆®ôÜʲŽ&×o“ªºbGíG©7•Þ}!mcÐ@1Þ*Éîº 'ÖcbèÖ¶ûVI"ð6€Ê¼5µr5?ŸèÕ±9Ïdä³ç€ñee“B…¡°´ŽÉÌæyékÆè¾õ‰¾Ï@$Ñp´UL³ß^†Ì Í"Í`ÊÜìöorùt;² Ú{ÎA{©„ŸTT¯®Ö28ÇgÖ&Îò‹*ÆÜºåŽcÖ³¹bžáỹ´B#œH€g¦ÐQ²Ç*·—äî–,Ö è(~áµiúíŸò’f?ZÒŠm˜³DÇëéü†„ÏQ÷ÜXúvêþfdŸgSËncONõ¹C³›;õöXñ}uŒ…Ddò•ÁqrµãË4÷ÓáŠ@AT7~\›Ù)±ÉˆAç,i‹Ä~p¤~ÐOV§óé›Ö²Rswû<Ñz¿Ùq©¸[øäØO×O:¥wIkñHSSÏœŸmðc(š Ób½Îa½¼dûã°®B`HbºlŠŒú:.hã m9È à6Ù.î…Zê2I[Æ …hâ‡é† -Ež»þQÞx‡Ö"?ƒÅPËÏib—L9²}Î{1–{šˆ*íOÚx¸ÌGž±*Oœ+‚X®I›ÞNI«Û\ƒ]O* “Q`ÛÐü¯h‡l'BZÅ1ÚTªÂ©ëº:›éëäoÖÛ£hFêpɸñw+XHÜßèó2ÀdVó29|VCÀšÖœð6/:ıˆÈ$±•Pnõ”¦û*Ršå3á"S1ù*@b]t,u^•šPõ¾ø®/B@Qu |J\§°’÷Ó‚…±+:PW*´·ð¹ßjj !O2¹TÝp?âöi9’›JLЈ¼Æsì[¹\ŸÍºÆ œ-Z®PÏs—õ¦0‡éR²’8Â^GÅg§êwé0Om‡rƒn«UBõ*Ø:Æá—ý&Ë…›™ÍæÚ?LfZЯ‹YŽ =ö³(«íùÜì·¸3¦ÌÝÓs«äÕî±ñGíÝÙY>†¥ìP%#YöøE“›p)B}9Æön-ü|8»§Šz*ƒ™š§KFDç3PÉï /]YpÐ+ú24ù%4”³•Råý¸ý]ˆLª+X’IöžÕms#‚0³³‹´Ȥ`3C²Wã|C­á˜r*š±"ÞŸO'=U•’Cy,Ñ­Uš{Às#¾¤ ’Cf\PÔ³®Ê×ûb1_0À ÎÕö“Ko"ÄÑ÷(r lNróó$&¦è”?+Z |šªVHÑâ×ñe+ènÂ;<ã\K¦ÍÕê)i¥½[õ|(8ü•ø~eIhrh- _•ãüºBv¾“95_˜yn‹Ö¿ðtÉ\·kÆo15å@Ù·3Mj:?Ÿƒ³ÓžT Ýýx“ô _ïá‹?lÊ»@î^ÎÅj’0BtÅïßrÍ¿6S‡Á±Æ?—)Î U[á·G?R "“ìþ w×Í: 1‡C†ˆ)”˜·ðÐ-š_VZø™›,l¯ìc˜sÌî°WýrwÏFSsyEÇÞXIѹ:Ça zN?gmñÑÉußt£lh}Ð%rk¿ÞžŠß;Ø(»”%PAŸZ7®7!Îørä¹'Cèp…è«"æ>áÆ»$…ö#׋6Vdb|¸³¶Á˜JÜÜ?ˆú(DÍ%5§šyøßE±«†\BQPÞH˜œ#a¾‘^eŠ;þU+wòÉíEQVO•ý'EŒ2T’SÈ‚ŸñdȈy£öç^«çÖÝqíVǰÎüª-&ßéóD×~¹HyN3ͪM-¿1ÞÄ…JJìë0ßôò“Åìëöð‹Ä$IúS»¯)©'å}—³uãC¿çýß’Ê;*R$oÌËܦ®0Ô’]ÿz´ ÍÐð("Šá}œ{/-rÊQí M¹·àh¬•íÂNpyo(ᓘU ĹsL—n¹›nðMûMÏ{à‘Õ˜(ƒwè ^4ˆ,“§²Wš.³CÈûxùÌü@ž5ï" õÝ’»ƒ×Ó6”[ýoèd_²;êáJJ€+¬9ý®XdþMKƒQŒ7I»o昺…¹BN2ÎT>Å jμDã¹W÷[ŒØ”~ŠÃrWKáû{ õ‹Í&æè8½mEVÃûéa[ß…ëÉNÁ˜úcTÑ8ïLõP+6¶Sè˜1&àxsÖU³™,{7s˜»:H°|‡f”·Er>@› d´½*ñ›ìü½[yüR|öÌ«'Z°É'Ÿ‡f«r¨3—š4qãº8.xŒ‰zͧæn\fȱ£…Õ)¡š²í~ ¡6&#¾/zëóÒò²)szuŸÝË2ÜøÓŽ¨¸bؽºªëëÏ™R^Ú¹<"-S×4;\nŽíí'Ý⚣]€¡Ð™F‰z×­=¸Ê0ÐsÚÄç‘òÁ2Ï´X`Ù˜ÄX4¡d±#ÁÄ,ãHÝ«õé]E}×Ù1xü¬ê&:'Y„Ò¸æ6ð}Ôœ­Q†^낤j÷Ú­¹ÙHŽÅÉýª(<—r)÷ôuŒ™82þe0IÝúÃæÚ[îª-~™ý1jS©l… }nOlßäŽÓñ¥"Ô„Çx©U´˜C¾7¼ÇAä翘ÿÒr™¯¬²ü 4>šVz÷Ð¥>Èëá|j³ònQ|EY‰ Ç!n¹K8+«šË»¡ÈdíQ€ÐHS껌‹¯qì)+ÙY¬W¤Gþ@„™”g¦D«­ÎçV"£¸.Ç+•„i'qÁÎnºiI°²ŽNiA”%ßu›aŠ-]g<'ríÿB?:É91™Ðf^FÙ–‹ºx‡Âè!j¯k±â×Õ5ŽûH9Î;wÅÇDçrLÑÿ`”C endstream endobj 162 0 obj << /Type /FontDescriptor /FontName /VTYAIH+CMBXTI10 /Flags 4 /FontBBox [-29 -250 1274 754] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle -14 /StemV 107 /XHeight 444 /CharSet (/B/L/M/S/T/a/b/d/e/equal/ff/fi/four/g/h/i/l/m/n/o/r/s/six/t/three/two/u/x) /FontFile 161 0 R >> endobj 163 0 obj << /Length1 1562 /Length2 7641 /Length3 0 /Length 8685 /Filter /FlateDecode >> stream xÚ·T”í6NIФ² ½KJ7Hwˆä²,°Ô²tÒÝ%-)ÒÝ]"!)R‚tǾïû«ÿÿœï;{Îî33×ÌÜ3sÍ}že UÓd—0ƒ›BeávHvN @JYYž¸9@ .\-Òú—AŠp„Áíÿ!…€‚‘÷:i0ò¨ ·(8Ù8¹œ|‚œ/A $ðŽHƒafe€ÜêˆË ·wCÀ,,‘÷yþy0A˜œ/Ùþ¸$l¡lP#-¡¶÷!`€&ƒ"Ýþ+“°%i/º¸¸p€m9à Qf6€ i Ѐ:BÎP3Àï’*`[èߥqà2´,aŽ4áæH0 ¸WØÀ P;Ç{';3(pŸ )¯Pµ‡ÚýVú Àø»9NÎ…ûÛûw ˜Ýg0·µÛ¹Áì,æ0(@UV‰éŠd€íÌ~Á6Žð{°3f6½ü9: +¡ßWøw}ŽÌéÈá³ù]#ðw˜û6ËØ™IÁmm¡vHGÜß瓆! û¾»ÿ®µÜÅÎãÉfgfþ» 3'{ ¶ÌÁ */ý7æ^…ûo àñ¿äæç@PWˆ%ðw-7{è#çoõ} ^öp{€ù}P/˜9ôþ×Ãì  NP/ÿ4ü·„ËÉ 0ƒAS¨Ì÷ßÑïÕPó¿äûù#`®}Ð=ý8 ßŸ=Þ3Ì ngãöoøŸõdä4Xÿ.ù_FII¸+Àƒ› ÀÎÅ p‚xø/ï¼þ;ο:ðOõ´j`Øß§ûˆòvæpÀï¿«¸oß?•8ÿM ¦¿÷†ðß)Tà÷„†˜þÍ/rÿÅùÿ¼\þÿÈÿ;Êÿ•ÿÿ{"Y'›?v¦¿ÿ;Øfãö7âžÐNÈûåP†ß¯ˆÝÿBu¡m´2Ô ædû¿Vy$ø~I$ì,î‰ÎÎÉÃâùKs”…¹BÍÔ`Hˆå_dúg÷9l`vP5¸#ì÷Åsïýí~÷ Ö÷—‹ãýÌþ2ïùg¼¿eèýªý÷9dì p³ß;ÉÅË#`7Ü{JÜK¼Îûå5ƒºþá<ÈaGÞ»îkö˜Ã¸¿ý’|õ[õGâã-~ßw÷MùGÇ z Zÿ‡ÈÚü‡(Úþ[¼'Ðî_"ï=Öþ~öp³ÿ@ð€ÿ“tü÷îãhv´ü£ù¯J!NÄ}+þPô¾ ÿÈ®"(Ô Á™‚C„ü­*ý›ÏË%(]Ø×‡…ì'Ÿ¿æbÎ5ÂFöÈŒ¯Äj¦§Í*ÉÎtsÊYµ©H:œg,~;òX«¢©vã9e§‘Ý´ 1žº;Eˆó8£¢›"¨GÉÖM”|&X€èAQ£#lÇ3³èÑd ð|QÙ5çÂHZ(ûR! Y¥µ½¼0M‰ŒJ@g÷»²Á´_k÷˜üEæwÛ(¿Õpƒ$•÷tŠÂ­¸±.e„Ë}ýóDÝÔa¾ ÎïÖÑ"‰d„ú©¤y°Êtæ?<ºÎ,pÞyOìaúŠD|ǬçÓsây¥Ê¡åÚáŽ!-S|ûKK“xópÎ]÷ j"ûyRÉdDVÎF¨Ù\F z]ŸhÜ™£NW L®s±ä;µµBP€¢ÛìD×èòµ“b’¼þH¯?›r¬ÈmñÚ®W CK„³y Zã‹òD¢5V²4æm/s¿½ô6éó§Lº\úüÉ–ÍZ¢ùóþ>¯‰¸¹ñaÉ¥Ú€5?ú°òôN=Üyn?µ¶J2Î:”…ÙE‡»/WÍ{¾Ï;Üç~®†¤T„K¹»Ø®œz–¹®*õÙÂó¼JÜ›my.#Š ‡ h2>n·…úGs4†Ð•Ì­vŸ<+F‹6C)TÉútyìK6Ô oFáÆu.ô ¿Üq¿ÙA{PÁµ¯vP¤öXHg¬Í‚¯ïCšè ÛÝhc’ª­hðFƒ»vª…´ß£•õYã±ÑJÌi}D9~MUœÀÒ‹dŽ)ÿ©z¿ßVlTx³ÄòqCfóxåÄχͅ"¾Ø¤ís[P>=JyD£ßjLsgz7~üK’J'wé²÷ݬÚC]:šŸhkµé©ËàÃ-øYGÕfÿø\†}3®Ã—p•¦’q9Ñi¯“_Øsé1=z šVWpZ½)õ³(|„ÙÆiÚÚ¦Pö4iµŒ(0}ËÜá¢ç·ÑgYÅÿª|òÒíÜ—$Ù’B³.àヷ^Äö·ìcÛæSFðÕ”1n¥ »ÎÖѦÆÑrµqT¼¬ŠÍÝ31&AÆQ'0ÈÙ—’*¨¹äÈ=eÅfnûþ—û—l0Þ—cIÌÕm’ÄóW½Ã—œû¬£³D㨻º5•\öð4é«´O!è­®¢æßäª.õi µdN;¬Þkô‡zY¯ðÖÖȶï“ lø×Ü_ÏÇÚWg¦¦ËÑêœÍûšÕÒÖú™ñ|ÈÑÊ#˜ád[½t&}QŒb™ŸbuyŒõ:¼ŒØßð$W}|É¥GìÐkÊ·Î!Ù0¬HÈ ý:y#¼mÞP+üËJñ:rœÞºÞæt‘ÁøØ–Þ0E`•½Û/ký‰5XéËÛ§óÉZ#jœ_}Iž’Úe…DNfÈÎz˜jµ 6›c~ÿ™Uâ¢4¶ÃÜÞŽ;ð:]`u ùòl¯fITÌ—dv­Z+kº¾§áò~|E7èY*´axˆÒ¸IMÕANævõ³þ‘—Vrcöõ¿Fº—>‡HÿeóK¯vâÑxæò@~ Mñ× nOˆ…Ó«¹¬TšWü ÚFi§7,{ˆND³ŠË>JÙ—ÖAà Å^ÙösOÌ~xX’ñˆ†‡b¹Hçÿ‡ª›=êFßÃÌôF–ÅÛjİí¸…¨*}%{$¨¡WWÏúŽO¢Ò•(B¶6ŒqqE¯?_kÁGErY¨Hê?¹tËõ™ynO‚IŸ¢=LÎ÷©ôIçUçzÃ-Hž^GÙ/¬÷jÔƒóü¢#OQŽÎÇdŒP¦;A˜ùøø-©ìrB`à•Sž£;‘}ê!DJ“³Û\™¥K‡œâL…§Áñ´^ˆ IÍSån6–šîPg^/Ž¢<ü'å™t|àæj¢GP½­÷^Ñè|¹¼ý@{Æ:ådÃMáXsƒÀ¾vï/! CkÉØàÞ[›=Q—ØÅ×ÛÂßåô"Ê{1\‰[H¼|ÖdÙéSéRMIi™jÜ­¥Õ5L‘BU}¶¬rë»Ó­ñÖT(NyJÆ1y.RŽ—ªæï¬$XRM,Ƃԋ**q˜ò}ñ-WÇצñ—²7Ý:ï’B€n1Êê3…á~¸¸ˆ¾È&@ „þLnn4>. À"3WÅÖ]üжZ˜YètZ8‹‰°Æ–2–ñž<ü¨Þ¾$ã½~N)˜ð탶1™’šXLMßÀ©Ò MåÓIØþ$þ¬hÂ#¢Þ‘³àõ‡ëÜ,߬žëv¥Koóo†ÑŽ{fÐÖɆ. †Öß>ÝšUŠ2~‹k¦ž¨ O_ۘإ×Ï4MNf«á°Ir–£ Oëm>Eˆ.À–ø‰¯êûcÎËœqo^ÓÎG*M¶bœQb~ØxGS=Kn6LïV•PFMY4èûÚÑÄ{»›8íŸlÅÇXÈ®¢µH¢çdÐòtU-Øg§: Êå¶ì7Èå0ŸÑa¸çÞtÇÆŸùËXé<ðHç 9âôÓªHÐQºãuÓUôt÷;ZMúå9[‹Äʵ’4Û Ð)uŸážmךRðnÞЯl­¹ä6¹qκµ·Cøi?TÖÑ-J=åøA¢ÇŽÜLIÞ*/©ärOŸ<ˆñÏC ÂÖäCrÖØt/˜4™¾ßEÉlD‘ß!¥6fN“r4a %”y¤‰ÄÏÓ†ðîI­ˆ‡½ƒ÷ðö¹*IµI$‡Ö¾½éQɧþª P û™fÞëºÁ%Í”ønÐ.«rv*m6Q42ú1Ü¿k¦9Âïû%b»ýÙ‘ŒþGvô⛺ݓG›~…¾î-‰ëQˆÒÛËcôy’ExJhÀÐè‚õ’d'€©ÅoŒ>¯(3Ɔ9ø@†Ž&¾¸±Ç žïã˜*Èx2— ˜¶~IVÞ°Y775dô&Zç­_5)>+µ [_4Εx±ñ­ýMãx;16½ÇvBZ½$¢=ÂÞû˯Ò_!x˜¯çã$nøm%ÜgN~¤a˜µªÑ­¥x“cŽÆ¶Ú/5Ÿ&=®§z•ÿÈ'Nåkfyd÷’§@k°]bél¢ÏÄd­ÕJˆ‡öåMU”ÏÝ­v>Ë%¥ÁôQ­äÆJÜlŒðÀöºZ8½=ºU‰O{ï–K2€V¸+ÍU(šÈ¨»ž´hçõ|ù帩טnàõ× )'µµ?pñ,ˆ+½²hÀñ€A»W¦  g—Q¶nÜxvrx$AʃlÎA‘9ÁLd³o¥°“Y÷†¨ê©fÞÔßÚÓÁÕô2E±²r¶(ÌKOs¹#—4Öa©6ô WkÚ©A­ÆÃìM^ÖÞJ£â?~wây%ÒmôÉrz›Ùº,µ†Ão:s.îhôäÜõÕGL 6Á¹êYàû7a{Ve«²¤ZóÍ_ñÙèÁû~O5æÊ/Íã«sr§ l} Öœð Ö·ØAƒK>2ÛA¦ûalR¥G]Œ7¯IväsR{'’1-sµï>ß}¿Ò€ÂMœcWfOìÅvG&JËÒÌ'¥†cV|œjÐ}pj8qdùÁo¸_"‹†iÆPyâ!éé|´‘oÉè¤jB…ÍÂÈW7ªãB#w^™p_ wúÛw_ ?A_¬5Cí£Z$~¡Y ñZ‚M( ÅÝZ‡57 ¾’±œ`Ü{ìÈ!Y.¥4IH_£M†ˆ+ŵ’ 5x»îme/ž²tœi ²ËŒ>]ˆƒ7i™~_hã]+«k»náŠoý´«èêÀÝ•·üÙY@]’ºýÕsT÷C0(gPdC&F¼¬1žcŸËhQ•'˜ÉD-'Z ÝœU\¨š*;›îû–íïe«›¶Å~P£¼"1ìîhâhê>sÓåX/NjçØ DKÊX• nó'P•éü”d³¶hiðÊÄõüŒ?÷}=Óâa¿‘67I™ÃûꉓýÕ#©tŸîœÛÂêO¬n‰P"Ä’3/ç¿HP×mðr: ¶öQ Éq•´TŠÙ´UWBH‰×nQÔòÎŽi¡Ø9sÛìHÎÈiàS`_Œ©p`BÜüõpÝc sk4ž:œEâ5Ô‹¾º›ÇÿŠ(Ä~¸ùóNoòàxÂ¥ÝM'=DÓg‡’—¶(6£”ú}V<€6±Ö{Mgü9¿Ð÷هÕwGŽÔ™FÛå"R¿>ÄTû.ˆ]lî|sÇŠ06ŒkFxßÿû”‹+ "¯ñºŽ6ù¤>¾|eÙ|ñ™RàBRD€þë o‡œ>•¥Ž/æä²ßApBë‡C-ÚüòÈgL·‡£ÐÌûìÕ-H&ye%wQœs­6/ÂVªSäð0f°¾ìS| á”ý‹\T7Ã¥)ƒ´yG.Û½[± Žé<ÅÚËS!“­žw„í™Q*ö'—1[­w–»Í–];ä-eDúü ‚ó c ­Øv/üÆ=ùwW?S¹(JŸãça¤Ün÷èã”'áNÆBœnÜ´5|­—Ñ£ïßHjB(? ù¶ú{6¿V›ÈÒiéaÚr_ݶõpn‰ìRA²d¼‡¢H§T >Å3BZO,²§¦oóP3Ô>-¼ØO¡xx¾ð³ò)*º„j&Si ãgó ¦ù+ûaé99:.ÆÉìö¡xŠûÞå!¦«ÇÜ´"N2Gê[ñIØL;ÒÂBUVåÝu—K3òë\ޤÔj—®$ª-_Å ©hö…Bz¹&®¿!ˆ9V_NJEIIf­„m–“Š, ¢GMIÓlJ˜¸ ÚRT ”銛ñ *ê]±‚1{Îij<£ˆäÃG¤‰LÔ¼5ïhDîÄd.6)SS«XBrô\8ôúß®SöÜ­(;ßõ´³‹üÔ° ™d!Ï$ðJâ´ù{ûzàÑ,öŽ©.ðeòNm¬ LÅíÔY…4bÂí2bC¸ÜFËÈügj½ž5m*nM+êhù=ÿÄÿt%<#Á^F°Õe =c”LBŒ—ÙUÜ%"²R Ðgòësükf ×ýÅØ­hônWÞQŽYËÂçØÒrÛ™3 ~4HwG™BÞÃÕÀú}ß@{ƒÄ'æ·xû°‰)lz‘–Ù€Š»šIÌúLH?ãÕÜÛ·îü„/5öŒ•ô!Ö'kCâ«Ø5ùÉa`eŸàÎÄ'¤Ï*¡žWÉǦeߟ¥à=D*ñV€’‚=GÆ·[UŸ1/9|]'”M@â$ªf¢åˆ¸Væ5ö<›ÅŸÎ7Þ蹋#¼aM*SX”ð$Ï6À[q3"`q5ïø¤ý )ª})›O;ÈJrv•_,@ÌÿǺôƒ¦”*ýÈc7éø™6,[Ý|ã籦aà»DOf"y“e‚’.ì îulaçPHײ§ãî—gÜpoùIö}ü3­=ÅsÅK8:a$cyY»/7b|®.|LÎéì¨êÓà§…Z5g=É›döÚñ2Q.²ÂÏÌZ×þ広›Æ˜pß³W<‘cö4ç`ŒëW#¤^åz {ã²vfÚ­ÎÔS±ÒûÄU]‹°¨·ˆa`A#§¬–—ŒáA3wöR&£r½[DŽžTn<ŽéÅj}~+Ž„ËcÅܳUILNŽ ßµ."H“çö\yÀø©¡VpŠ÷‹dç2ê+1u7\«å€¯¹+ño;ð’=ÙË!J„þÇÕZD™{îÞýDDhiw”J—O_N䕼b}Óþ%S2¼b)´m[¤›…qÐWëå'~ï·AÑϓǖ{Ûl:ùi×ÒTö´Ô[*\ÕåwdQ}`²Š¸3]g!ñD†S²AÆâ@Ä= ›ºýòê!GaF”â>αø³lš(Y ¿Ã$ö®¹ª ¢·îp^¿þ¼ùOUfÅè„2oã®»HßMcöäž¿UjàU/°O®ÎjšH=Dy÷Òªõ>—¬@Ø4ÏÞYY·8VŽÔÒU5 ¤ûÅáêJïëúƒè òüu=EVñ ~ÅW¤Æ{ *Zß)ø±{¾®ß¯Á/0Á>LÝfÖCŒ$Ūæ¶ë)- —‚´Š[-ßñ!f·•âuõB»›Sb«E¹5Jf¢á!AhŠX©øâWÜ“{š*‚üÙ9d/,0¶ò—°µÅ™×&4LF¯fááu>É›¢¡|ø«Ý}ÞÌÉ8ª±¸Ÿ>ö½váÒ}Yñ´N)d‚RÐÉ>µ¾Â«_Ž{ÖwÒ‘AR>?·´ÕÚbè>\Ge×ÈbÍc¾Ä+Üíçâ ¶lÞÜoô”çàuê0QWË9›zÇlrð1I]½¯v‹éëŒ'Ž—<¡Ê¨ÀoÑÿ©òR<˜›÷‹‰Ø†¬r!þr—Ïíä Åjä¶}»ùìšú-J+o/'YqnCÌOÅîb}%\·zœjÉöZú.ñÁ|[´º;˸ÃÑ—2k{åöùÎÙ®äµ:èƒ"n‡ÝRg‚öâPåía w:Ë Crƹ¥lÙ®Á†NBÕÜ-úçý¡Ø´Ò‚…(aD( ÌhX¤`òÕTe׸›þ>:c¥¤K1ªN3b–KÁ )Ð>—áKW¦ÝF{¼R5þf* g^ê Ç/¦Â'‘U†Jê }–óZÅŸ ßXëÄE¡ì³ð¢ñ¨Í[)ŠR ŒÄì^›ÂýÞQo ÖÇôÎ]ðDé¼”Y‹À%ì[7ß‹í¬M0MðÃÒ*vˆM–ýÁÓR÷¬RËs¿™s}_ÆüÆ ö»‰kŽÒ°sê¶…¯yAOº‡óvúlâu\¹O´Ò‹ž2(™º?Å4Õt¯† FOj¶Øyû?¹xªq(O^…=–z .Ie‚Õ|« rÆRñðØa˜e×_Í`OfÍl 怋SÍ,TÇV‹ô$ÑänYÖÉ´kã»mÍ‹ØHœ&ø¼ê§ëÜÓÙÕЭ ‹úÀp~šÎNÿí‚@u4fÉ ’6m%ºHEŒwûsî §ÒÎa·æñÛ®¢71tËž]ÈFÙÚ¶èõ,=Õ§?îžTÿTÿ΋ébØ»úmž=Qñ #å’Ú¦ô§øí¿ÏÕÖwò³…ƨތ fÏÕ†ðXâq73m:_ ˆóp Ø¡FÑæ)Ü¥æüÚçãH‘PŒÇXå+ÀœNãO«QfÚ5Þ&8¦±)QgªÎ&~1…ú¦¢ Îl€¾¤Ô}5 á¿TËàÁ1ÑÃHÔÙI7YïT‹ü|ìÂRÞI¢Hç0P­â{Ýî-`€¡ªa›ÙBœ96-„Œ‹›Õ×ç+é3ÿ2Óç}}€:|&Â{XS  œÝm,“”ñþÂNw]Õ¾»™Øß»ý†%fs‡Vþ“ î‘CZ“Ô§øÇßi?NoÈËx;ØtÜuf΃\n«š·ýUU×è³ßžiM.¶p´Ë N'·V£Ü)6³Î…ÿ¸]eÇbÚÏßr,(o)õ «£x{µ"®²:Úµ7r|Š9çlAîVòôû³ŽÜë.Þ«œˆŽ·¢äY¾žŒwA}çV3î÷S ''T’q¥lЏĕ~÷‘7€“åß·Os§d½é¢Í¹»á鮪ý£Ïã_¹•HûIZå`öâ¼{¦x2BìÞW$!L0M15æö=L˜þÑ„½ ¥ÇÈôÌ´›¸¨}«—}‚(BøÆO>8Žn`S̲7­ÓÐ3ÀZ†Ê -•š<Ûdv]ïk©’åu£ -·ò Ò°åªj?9̈8\ÊOÙ³b²t¢Cãá·¬z®<óŠÑÉÓo½Uùù:}oË+¥ÿÍ»“·Ä,%zö¸‘‚Ÿ§ : Ì[¬è¾ì×DG%D¦)1“<ç阤ñæ1–§ßD((ÎÊàW1¥(n™;'¥èaE+ü,Çt§”ÞÈ™ç0}ñÄé¹u†« 'EISónÚ²gÏ^MR²ÎÚŸ!¡C"®5i‹Y–LP^€ Ðð —ðT ||åTà’M+´Æ§Œk(þëçØx‹²Ç¬K¦V¼!Û}—nÇÃæÞ‰÷é®0Ö›‘…øÿè»ü/ endstream endobj 164 0 obj << /Type /FontDescriptor /FontName /YJFJHR+CMMI10 /Flags 4 /FontBBox [-32 -250 1048 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 72 /XHeight 431 /CharSet (/G/greater/k/l/m/n/period/r/s/slash) /FontFile 163 0 R >> endobj 165 0 obj << /Length1 1422 /Length2 6165 /Length3 0 /Length 7134 /Filter /FlateDecode >> stream xÚtTÔk×/)ˆ„H— 1tÌÐÝ Ý) Ãà 14ˆ „ „€Hwƒ„„”4"­ R’"Í7ê9ïùÎ{ïZ÷®Yë?Ïîý{öo?@}#~E{”L …Dóƒ@Re q$, Æp4ö—šh óð„£RÿËAÙAct*4ÆO…hz!`aXL ,.„@ É¿QRˆ7Ü #ÐD!ažD@e”›ŸÜÑ )ó÷Àå€%%Åù~‡]ap( Р`®˜ŠP`„‚Âah¿¥à’qB£Ý¤}|| ®ž(G9n>€í0„yÂ<¼aö€_€ºWØdD@€±ÜóÞå€öxÀ…!=1^H{˜S`¤¡ Ðsƒ!ÿ8kÿqàüu7°ø?éþŠþ•Žü BQ®n¤ép€#`=5m´/šAÚÿr„ ìóîYúÙžÐÆ®¬È¢l jq™#£^àw!OLS+”º¡gŽi²/“®é¾Z݉w´\2ªŠbÝ“¤]z1‡½È¢øa‘‚%n‚í#êÄ8Äkb«»H^²Ÿ(s×=`fåÝ飃¢øÁ”(Æ;Tx‰a”ϵÎ/·$zü7gXçÞ™ä\ÝäÍè{>'UÑœkI)uAž8à*-³¨#87åyº½K‚rÊ$J—2ó®X`½.¯%ãvNË™0h݈»(™ôix‘ÃkŽŽ•®#˜QÓ§S¯Õ!ˆs½wßüZÒÀÇÞýj]\Ù²D¤?ó¥ÙÖ\»dpL&T÷"FãRÈÿý%ã"Ö¹i]sÇÐñëÖ–LË‘äs\í¢Üz‹‘·,dÚí¤ª_`6¹Ê/û= ‡¬sl¢nˆvÒÖ•ÎH6³‹nêÈ­Ë£éÞÊ\S úLkþûêNO/£tºíÇ8ª}PWî×Ùø¦¿ÖËmøprešüŸ–ð·}I)ÓÑAa´DÓ·Àå<& ehñäGÇ›WÄ÷çÍ]_Ÿ¦" G?N=‹êц½öÝêø¸ž}E–sÛŒ™¡MH·ëÖB“+õ5 `ù±…Çæ°›šÑÛ*‡"bœŸ¹“\¤EUÅ¢v"áÒB-AìûŒ4´]äD¸ÊTîÔTÖl±>â›ÖûÚð/„â-¦ºYõÎ\ÇÅŸ…¿ßsëÿèÒ„GöAµ&ÎìËÜNQ xÔwûyŠLßÇ5ïËsŽ&—¯†*Í—y•ö£e—vOD×'ž¶õ‹8Z„ß÷™žV }—¦z*p$]LÀùg¸:¯ôr/GáøãjÖ§ºp7*|20BTÙŒ;÷IjhAÈÙAÔÈ´XºwÐe¡ˆR”)NoñÄð¡{9pÿáW™Š ßÛAET÷h¢ªã¹áŒîé,ºo Ýê—¼Ô@þÂäˆÔ7ǦY¤±%9f<öxÈtæÇŠ/kô´*Îáà%&ÜŒ¶-+ÚùbY$IME:ò½y‰NK+6áó*öxM£ô’D]§Ü/U$ïìgû^à¤÷›+óE ²S$03ï¹Ð¶Iª‰ŽöWß.…~Žì/jXšl¬q#]UÈùR‰¾¾Å;_]ö°ãô«µÉ>š´QÖ0¶4$KCÛ‚!cwvevž RñKæ¡fúFj1ÚpÓ|…¦ WÌÓ¦@ ¶ÊY¯ŠÝ¥×dÖ×KÑ{©$Œ¢Êz·ifç~Í+Jêû ÇÏ„zÖSN‘rQOÇîuS´‹½Uw›–Ö4nK½áÔ©UîmþcÉ-ê i¦ðì>"2ŸæÐ(m s•ÌÜ W4=_Ú´4ãžR¨¾ì`á½áIEÐgòhaûé&¸Oä·ï-ØÓxãÎq½e´›ôˆ|T{VoG#yÒ ÕÙæŽb»ZJ¨¸Óµ2y°É[æê¹&Uº†zabBƒÛÖÎ(М8¯hÝ‚¤ÇEÖ=êñ S‡,Z¼K$òmÈàiåO„÷nsha!)†l/«KæâWZiB™ºewz\™ug*¤šÌðeº'¥bȤPgIà1S:i¯ÎáœJ?„ÛÄÐorb?Ø.5^¸ðÈ[ÙÉ6á$Qç.|#g(xsåÂÇ-‘{‡ùCßàñz½r#>n‚ÔÄšÅÃh =‹Sé˜ìøvÄÜj&¸î±Øîaå‰ä°aõùÌíÞî^·(§›ý[út×Tª)E©¬)‹ÏG4šCqî½z±> %ì®_zl›R56F›õ~*UÀtÔ6ï/†#ÚñlíI áHéûF™C’ìiC²þ=©7Éß šÎ²á£Y3Êä®ã öÃêú„“¯]¡ M^|Ý•†c—Âøz™v Ø^SÆ4¼.%ÛÿÍQU'v«ÆëÚ ÉÍ4„ÚCÜRÒ}žÜ¥ñýò¢Á4/AGè¤'áÐÉ…Å\qñåÑe`ìà²Z‚Gé)á32CSï‹§ÖG‡x{•7±‡{JøŸ¹ÍøÞÛ¹ÜÅ-#‹Ë"–ç$XuìðŸ¡FÔ'Gžìmò½Ze­ck*|ѬøZY­"=ÅÂõe¸õ­m…'…3žS-‰»r ,g¦5É_M|P¾}ï²Ú‹¶eã£uü„ŸrBk¥™ç,õW’îêeŽèÚ crµ‘Gš;í°¡C²oqüµ0vÓWc.@šÚ›= Ô;)Þ¶cN±ýŒ[±u'ɱ$ê‹íŠ¡3âyªáÓQäÂ0 Â9ß¡á•Õ(A?:‡{D›r'ØîÖ«¶I!gµ]Xäk9벂pm…¯ð:7&¹ÖVÀeSóÌ»6ü' }N¼*!lhÝÁj÷œ]üqÒ¢Ð|öÛØŸŸ?¦|j¤—ù^*wSáiEGlÆ?r¦ðŽZoÙ0AJ÷cîk5­GAš'ï˜EüÉçÀíϾª³ã¸Ðñ…€ö ©:34 Sx9et1§UŒŒO#Üô?x4(wÁËÓûg\¸+=dæ(xLUyùò™U£¾±™Ug‹(é»ÍÛ€¾9ålÿ¬˜Ì.Wó'ª·øŒž.¹ùßPûõ’,a'3ò”¾aã©Ëª ÏnWXv`w/'½ ‹‘àbë`UœܼHs—0â§ó}ö7lù=;Ö?µÝÀ³šˆå|wµ1´ÓƲ¬Vÿq<Ý¡FB©iÊa6¼g¡ˆ‹«®*Õ n h7®@ÛëΛd­ß(¦ø~Å‹¹´'h /L_ê¾óã9uÍ «­áܤMvšt ·åÖcf!áV€Î¢³ O­!ßÉ ¿ìª’ÜpêóT°ÍX®¾¯Á°Ëê"žûInS´ Ýzzó'I­B+!;§"-Îö`e+·ôޝîsES}gt¤Aƒbu¹ñ¬Ä$d/êÅ(!I©­êTsøª ´ß0þv†·îwµÏ&ÌœM+~kƒªXydz L5j¨W¶]Ü<‰bH¢Ÿ[VýçUHÚŰ#ó?”¤m/=»óÖ* ¶eK…ßMo@&~¼%<üSPú{-Æë~âü•þ~ê‚ÄÍ¥ýòŸç]öŒÃèýÕ´Óü€ÏŽÖŸhïž:VêÎe½) 9GâÓRá¶iѳm¶—MÙtHQD‘Þ³®áÆ_6"¿#Ñß:xŸ­¤^щ»fS†¾ÒjŠ&–nÍ*#i.ÅÈ»åø È •j°³Ì XË ®!¸¤‘ŒcoûG¥N¨2²ðsâæ\—Þ·”N)Nk®¿˜$_÷ãS]Ú?]úhzÞû¾_38štägï!ÁÙŠÿ/œq}ŽN`Ÿ©½ ¿É@›C=É´¶_+³tf9¶ÂîÇÔ—=WÂËÍ•„ïëÒú±²Ñs¹0>݆®ˆ~…ÎHN,le½-ˆÔ I®˜º3äófîÇ)l€Iœ×ÑŒùaî;.±±¾(ùY¨Í¨sîуù6ÓN²ü¹¡\6}Ö¥O˜¥lFä ¯•:LÎ ¦ 8rZ°o¬.O^Ýœ•Tïq7:8åßÀ§B µÚ塚¾•O§¼úÖðDÔ[kMõ nú™å¬iý´¹¾FÚý9YÒ]2Â5tâ…PÜÌ?ù0uÇùaM×®‰£…{kØêÎzB¼Q'cJýâžÙ¥ŒÃÇu¸^ëðŽ\¹V¼ö®k¯œd{t“Ô§½ é¯Á7Ò¶‰.Dª¢$jÕØŒ´JΈ ò@•é3™R¯úv­9†]ºmVÙ l ^ašË7-Ö3ä["ïÒØfÒ­=SöOz8½|ƒ>fò¤|^¸ 7€}€Â¤åáyq:|õ£€ÛHÄnßèkYz×Ä›cƵ?çùð×÷žŒËŽt—½¸£œEm»ìLr¾¶¤¶ìX»ß`1xŠh€My ú,ºõFüØݲ{ô&#MD¸Y­³¶[˜kz˜Ì Á:Z&Ÿ' ÙSXˆ¨·7¨Ê”§mÀcÈÃ>= -¿èœ›%!ïÒˆœ!æOìÉx´s¨?>ÌŠfí”™Î~®Ùì÷|ý€µNÑ©í|ÕѤBÂg^¸]~½û›X?´vå¶§y Y(Ü&_j¿Ÿ7þn"-qzq#YJ;ösàÙ]w„OAvĵ4õ?pä}6>5‚ÕÅÂWü–¥¼¼à{VæüMrâKõñC͇Ry/™(‰¿¦¾7ª|//kIõðÊ^pÍDm†™ÿ¼MRV_#üu†ß .ÊŠ(¬îL…wǘ“ÔfR¦>[£‡ò-jv”DéÖ—Æ5´–ƒ ÉßK0’ÒH‘¶¿ØæoÜpÆ6þšóÚÂuŸÍ‹­9FÛv¡Q»H±Tî&EÄ4¢èr­;(B³óºDw„z¶Åªç~ò„5&T‚¡ˆƒ[cn3I!©üÕ“"W.ÙbK÷Æ`÷ûw½WAú6‚Og‹¶äçX½’›wÂ_·åK+<©T~œYËŽI‰fµãÒ¿²7å€3|¡òEË(óøV׃c‹‡L“PÇáPéüÎ÷ß›bn1BNc«Ü€ýëÁˆâW×ó7y¼Xiu†NÅÒøV. ¢)Åz?È9;’ý 7îü®½¾Ó[4GZO1@èIÊÜ‹S䜀ÅÕ¹VR–LóZ¸± ê  {j‹ª Ð Åã>¦ƒíy9R¼þF¬Ä¹LsfÇÆ-“É¢ÐÏ# 8ËŸåK%"ã=“!¨ ó÷xû|݆6Œ‹£ß û‘Ï_æ‹£âÂ÷¾Šy‰76¦âÉåÔƒ0žM¶£ýŸú{nvüêÉ6OB|†êÛ¯(%B£öøØ2¬îUÏ€E‰"WdÙøI×+C»¹…fïõào4‘X!Á*ó~ŽÈØÌûÓGA=—"Ÿ¿¸âfÍ/¬‘–¦Z=¦H¾*Õp~T¿öðýBã%€ü8Þ1™ *ן×óÐN!·v«…Uæ—ßXWò¨WðãÅbãáiÕ·ºYºœ•^ÙÿhôØoÙqÆX®ìè„ýIJ"åŽyr€ xMµ'¯Ué} ¨ ¸Ên™pþœ™~µAÉ:  PÞ À9tì-Õ§m†OIß1ÎÑaµ‘ÁP×5QK›IŽÜ‹êé‰z¾ÒM׿D4ßùj0´]áÞnN9MT»›ás4>bm¶åÓs±Wj ò€6£û¡‚ÄC®g¬W÷'.M²¨D;_h±bOˆª_ÁSÓ¼è=X"j|Î{2UÁæ´¾Ê_[Ÿ›KÝ:Ì~@ðÆ}¨iöj|™s;™ˆa³½©r cßÑc=¶íÎN@GÖÒäDgÙŸ–&þ<𠋺)h‘ûmöÑ—‚-?âC½‹¾G¦8£¡veàYÜ’Ayç‘øûÁ·"„Ž©'Ë)*ò ZGO‰ïfã!ýåµS ä"ˆï?Žzk¤³±Üù~r*ÑËØËê’=™@ôa朵x,ùUÂÝ1%[æf.$u²Ò#ç6ó·Á›ÂsÕýÇ[HUº–`[ã-Ïbˆ×#sÙï ku«?¦Âœ—T¾ Ýñ*"¹%¤g6 ¡Ë>r†¥Ù³ן¢,ì°vîm%5„t?Å—Ú ßåÙ¡¦lð‘lu}OÛÚ¹qU¢ò€Ùúu)ÕZUjGÇÕÜHœ± Ë„£’‘bõQQî¶XƒÓÊI—ÃãÄèÓ6z×Þ:/˜eu7i48XÀ¼Êq5JaïÕú·bõ ] ÓÖmƒ³Ž'ãA; ìU¦ Í 7&·à¾Ûo¶xy hàF+FÎg ’SéVŸ)ÅçS5£Îvå¦h^È1àDÜ'9‚¨$¦íÎÔ4LÆ+øÏàe¸O ½Ÿ9­y’Ò1™*`úÓ¥SÈ–ÿx°Î­mÖÿÙâ{œ•â†hXc×ç¼Õh“åÀÊD4:ñcO¹ùÆx50<¹Vö¢þjŒ.¦ +îfWØRʜ浻QQäJô {m\œî[ßæ@á8ÝšTzbw“É'%4ŸŠŽ?›¼¤˜ºçQБ…‹U7Ø>ÑÒ:1lý5î{Z i¾ —‚‡&ÅkÐ0Ì哯VðKåì¡ ÏýF˜¸‰¤jU‡Ô'ÿѬÅ•ÌÆ­eÏ)Ž’b¼ÈòñÙ~« {=i³w!!o–´óŸ Õ“êój±wtNÑŸ²ñf~%ØGû?X#H’XÖ38&®{ª¬C•Ðdžä7ðªãýµê RööÇù{y×Úyב†9µvÅJš+_φ¬»Úšî¾¼ŽØ+öšµ'MK·eÈb¶âç”ÛãÝ·˜p‘º]5̾bá[­ñÝU=¬Éòò¤Kv:ŸbˆC稉ó `2ºŸ³6´aKÀÐ4Á±n4ܧ¡4;íšzMPqÉÉ¢<õ}÷®yÞÌÃoÅ·b…¤ò"xq„œã¢+ŒPIèë˜Ô3?ölá9<a¦°~¡°ÚQ3¹‡ŽµÇ²zPkÖ£ZS{k™w\´`×èÙv¸~^j¼?C ÚòvÓ|º¢€Œ÷m÷cgyŽNÆiݨw=2¥#aˆ…«Þ5Y«'8ì³ëOΉÓ¡âÀÎÎ~ †2í­N[™ORÛ`·ÓšK¸Ñ 0_Š ÕcÁcw™AffÛ’—ïï²;ź–¹Laß5>ºQgP ñì#L¤-Èý:ÖѤ endstream endobj 166 0 obj << /Type /FontDescriptor /FontName /CAFAUS+CMMI7 /Flags 4 /FontBBox [-1 -250 1171 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 81 /XHeight 431 /CharSet (/l/r) /FontFile 165 0 R >> endobj 167 0 obj << /Length1 1408 /Length2 6096 /Length3 0 /Length 7051 /Filter /FlateDecode >> stream xÚTX“í¿¦%AQG ÂÆ( é]"!Ž1`06ØF H+Ò¡tˆÒ‚t‰„’Ò5)•Ž3ãû¾óýϹ®s®]×»÷×ÏýüîûåáÐ7*Ú ­á4 ¥Ê::R0X‹Póð!pHø75 ƒE QÒÿ-A‡â>(ާƒF4]‘aQ€ð-ia i0 Ký•ˆÆHT n€ ‰FÁ±Ô<ÊhgO ÂÎGó×+€Æ–’’üUPt‚c0(  ÅÙÃaP$À CÀqžÿjÁ'cÃ9K ¹»»ƒ NXc'Ç/pGàìwàX8Æ nø   u‚ÿF¢æÙ#°¿ý†h[œ;H ŽÂ*\Q6p €0`¨¡ Ðs†£~'kÿNü¹€0Høïvª6B ~Ca0´“3å‰@ÙlH8@¢ ÂyàP”ÍÏD(‹&ÔCÝ $ÔšðëäPDÑ%ü à œqXü QègÂ-«¢l”ÑNNpKýó|* F¸vO¡ß›uD¡ÝQ^ [ÊÆö'Wg!cÂÅ®¡ò'…à¢þÇgÇÄÁ’¢’b¸ î³úÙÞÈÓþ+(üÓM@àãåŒvØ@À}¶pµêà0®p¯ÿø·E-, °AÀpk¸EýOw‚nûÛ&,ƒð˜ƒ Ü€þþ~³$ÐËBzþ“þk¿Bú¦C]M߈ÿŽ))¡=^@)PD Kˆ$/>ÿnó÷üþ—WŠøs8ð?5P¶hBŸß ·÷·?¼àû£~À¿Gè¢ d†øþá¾X #<„ÿß øUò¿ÿg—ÿ‹ûÿy ˆ+ù+Ì÷+þ?ÂP'ÒóOË®8‚.tÐu þ3õ.ü·–uà6W§ÿŒjà }(¢ì ‹Àn… <à6úÌþ7“þÚa‚룱ˆŸŸBü1‚ì`Ž„Ï –°±ß!(– Aܯåþ´á•ýûª(Úæ§EÄo  Ô“š@‚%ð&èÖîñ‹ð! #”˜}¶h õÏ5¨rüé£þW_˜+Cü‹„¡Ù¿4‡{ÀaÔã£hØí ‡ò †ýRÅ+îÀ¥~òÍÄ}S`Ö}J\‡ê Õ|¬aZê„V>d¼]rß¡IWÉe?}f웾âz¥§Ø.ð:dÅîºuôèÙ.ñpœ×;ç(}-QæÝx¥kÒ¯1DúWÃ.4SÉÛØuòÐ{ß(oûçÎË” ‘Ð nÐml.ÍMÕfa—2Y_¸ƒ«³î6ZÿÎz#cÁ)*p1Üâi‚n2§–Lãu¬{É…¹®žî)†ö«-aþšnK[Üq ª·»ÙUÄΕ˜L½¤;Îxí¶–Ìèe­vQaͦ£`–?~¿\wÇ¿³fÉqÓ¥=½†µr=[[-öQrfdO¬B_Lé·‹ÑÂ'¨&áþ&yÇL?¶^£ÐȃÇÙ=ÁJ¢Z xðQ) ÷ÚüxñV<å5’·TdÇ££3°°ÉÔîÖŒ}âv§¡?ä“7o×ýS’û†:üü‚/Âe© ÷Òõŧ‹GfVµ©Ò‰(ØÃ¢õ¿PûZÚR ç]R%ÒÛÙÁ'ÜÌ›« 8"°Á†|}wU‡½‡™ô ßñzÿy~õX$Ö»£üD´¤”¢îåm¢¥$ßz¯¡›"ï«ÛLï:EìM¬F‡­¸ÛFa2q9ú>x–DÞQö Ï„qÈ×` ‘PÈ>îEP¯°ó1èÕXÇ„»÷…7ǰÄïNhf‰á¥ò¹½ßO Èó'¥C'Õ¯C^Êw0í/(D jœr7G^¨v¸„¥ã»Qo?¥¹YûH1&Eæ Ì#nZ5院UBr-ôùœbá•U…•¶MÆ"OúÕº´ò <:fuiIiÌWfz-…h'Šýˆºwy}5.ÙBJ„î ë'Iñ#)6S–uäWؼá÷Þߘ=ÊûžÎ Û‚õð1ú1@ÃÊÏF×S™Ü Wƒ<ƒ;ù«”^áêæ½öº~Ü<Ö$ÙÓ,>‰QÅóc‚?†õ7´òóaØÈÝ|ø ½4k¡è½Šƒ+!VnŸ7†r/î@WÜ.^î¹Äôù,¹ã=ôÒ‰û.ØŽïÙãž¾È^}›Cûœ Ä!9tŸÎÁÅâ¦kË«¿*Œ†ö–í¤D‰&ÈZVõ—-º]{Æ )ñÓ²`”θšµTС‹˜û¼‘e¨"|”V_i&ZñQ@G~§QÅüþÊŒS¿ò%åÐÒúÐd7Ûè{Ë]ìf!·uª[n¯žÆ½xi»8¹`–Ͷsã)5o<‡ZN. êCÕ¤zž._1åÊúþÄ"J>þzWqQ²&{+åö#ã›æóõ/"ï>´èŸÏVàÅ][‹†u^´§œ›I]gª&5}èͯ¦¢4Ò˜Z37»(:¦cq o”ˆµú5•Éß×ÞJ¢èìøBFá5%ÂÁ9as–¤, "«„RP«`r¹îÆ@[؃õeо É%#Zê;-Ž9OI7N÷¢!Ó+oé¹[È"à3Á¯dxÃcïr´³`·‡ƒJ>“¾!ö5ªP׿fzÑ9%.ØÑžÀFRÚk ‰lÅ[•W ó>¦9ñQ•hÜD]^&Ž!žJ ¼&m€^ßîâ$ºk·vèêú–7‘Nà ‰=ñ(÷Yªn±š‰Ü:J3ùñnÖ“nˆ\õ ŸjGÁÙŒÓ3ãÃF•àÔè¦qÏ`ä)%WU§9ÇD3N“Ñ0XȨá‹ß\ùV:G–Â’Îû6KÝN ãHЏl#G÷xÚ¥žGÏxW?—¡_Î4(½7IOS–÷ d¶ÄA,arI+rà]—$@Íöæ}A/Ü÷a&†šÕê¡Ãœaš=g÷ª¦möÀÐNÒµÓášÃ†ÝÔ´j¯ãŒ\z¦«‚«|d ±EXáCô" °Y«ó´*òj¤D(Ò®aßotžlc,²È´ÿ…D¡OÕr8ÜŸþtÇuާ]>:±Æ;Úp¿»C÷U41bÝsayûžŸ˜ìç=Ëóräž µ:€6jE¬âÌ·¾k‰qOò$kE{è3á“¥¥qú:Ã9ƒƒ¿EÍÿ\·YË5Åw£äٜߠ®¾³ÚZ‡{þf³«èTƒ'â•S4&öìï]Œ#èõóIžš¤Y¾¢Øô+Y*_vXFO•¹<NÕ˜ÿ¡^òþÉç™ÕeSý^wdQÌ|j_¶~åð´îº¿›@7”¸U±ôKhGÁÌB¼z¨WFߪ樔¿rH©~âBШBñ@kCLý‰rÐíüóç²€ö^ûþµ]¶¤Ìïs©Ù¼ N[äiÏ}‘ó \»ŸḴ¥Í´éajeç™þUJÒ'{´0˜ñxÏÔ€/˜te]Š—zÛ%ƒªFž‘jœ(0`Õ.Ë|qIºaË–gÊ0z;¦l(½ÿ›ØGLðx˜øåUú/W<§UM¡,wŽgjÖ÷Ù®1ä)Ôº}ËÒ•¼úàÅáîéãÑG­¿¹¢“À¢{ÅÒ ¶ÈÛyÒ9`Ö/Þ*A kàoŸ¢öès%Þ7ßݬ¯¯T»:±¯Deü,¨:kab¯Ìüý3‚?ÍØ-–WÐå¿2%z(?Wiž)X;cêQcçÞTÊþèÔT¤rDdKˆ;‰E HOsh`Dz·1Ùæ¶AðÄ5Dp“¼Ï¹“”r/p¦1"¾pñ4ß@]æ³ø}ÿJúØÛ’çr©ƒ÷Þ\‘ò Ä@»*¥S®3°pS¬é}½ïË›úÖ[7±ºwŸLŽŒmðø¡$š ‰ÝB~±ìv>ÿ]7¸,uGZÀJ írtÆ9éy/œ–lþéðbX1Õ{Þú–2Ê,*«_DÊBßZÙsVmÍQ&z´œOÊ@ä -Èû*GN+Î -Z¹fâè­_‘Ô#9¨Ô(2¯{x%i„_„Êo¶[ÒÍpÐ[¦žîšÌÌÀ¹ £Ë‘9loI‡¡ÜÔ•Ârß?N¥ò¿Æ>YÁÈ:í­> `:#0ßr ¯‰¬Qvv¦—¦5{ú•—¿­nœù–ÀØ×oo~<ÐÊX§ó³•yá˜%> -ôN¶Ï$ NÈû(ò¥f:æš5¿$Ñ ®RhG×ä¯0–kåùîp Y1™O°» ÙB]šÙGe –å8/²¬Ô#°ùµ«µ¤Ï-³¾-¸ñÂĤ n‹çŽl€Ýíª‹²3…k­ß­Î».^/kÈøÆoñ£çÄs¶FºN»ô,õ¬0šï×¹±BMºº#Cò9ü)±Ò ù½lÌ%3 .Z‡L0¶MÛºÊd¶¹}X¯`]Õ ãW…hdzh1òMÝ…ŒåÛéVVT³W{ö†¥]·¿Gh†¸ôGI ‘ ¨Çý`ø éå ±Ï® ¿5Û nÖÕÁzÓ’ªÏQî8±‘ÛVm£Å}.µ¡¨™)²˜++ XFúSö¡v¯â›ãK“.!Ìì¥2ñ5»jÃøƒ5Ýfý"”ä€Ò§˜úü°c_c³€“ŽP[¯CP…ÆhàË Ð lYK_&S_ˆª ˆC†fƒ28ÊM•yêõc7â·K–ç§z›G1 ¦‘AäÆO43ãC¬ùvjjR£ wòÛU—Ð xæ_`ͬQŠLMË‹ƒLû½;Ζ_òägyóHͤœf—UP•‘ åD8$¬–E¶r°ÇÏ?Kþd"l¾GåKG;‰¶™UIYµ¡z£’oííËÌ639}W’¥Êн5U*ÚO©MýŠÓñÓ¯œÍfC}mHªýØX¶Ç(Õzø¡ß¼;½Ùƒ%º³„ÅZ,ÐWÞ]Ä L{Ìsð©]õVÍvÿk±¶¨ÊÑl•‘ÑM«9nC¡!9)Î]® cÞøY"ƒ°‘|§½@”êw'š‘5Í”nïL‰¼å iž)G¶¥`ºCæ/å‡À´ ¿`ƒ®Ý-Ô´S3£#ä¥ó~Ÿ´LÂpêf­?IôZã©÷ë-×!«Ü”B•l™ç¦óŽyõ=oI¼_,qµ1Ò0Ëy¨ù$ùÆP‡u¨­=þè#é\“²â€mr[Ý_‡&–óö±eñ«·ÌÊù׍“í­ûm]ñ€¯²ñ°îèOVµB%¢$ì]/r•²üðj÷Iu]eË Ún'W:Þ=Ž——¨gÐVuzƒ£`’þŽÝÁû„è>¤ 1Q‡fÌ2ùg9ò«×|öû¡Òð¬:[TÑl?/§À¦ ²¡óÐ_ʆ®õÊKxa€ôõê¤ý˜fU¹ñE³]|ò³—6^¹çë×Èbäß0­œfnd/QÔÆ0}§<ôz†ØŒºñzhϬV–` pïÝ+žs‚2Ý‹rr3ˆ@5-í9¥©f=±lt1u˜¹Kâ9ß;Kš<6dk­L4@¢kzO&j ar“cûÀº!!õ¡o«£'/X ˜À1´ËÊàrç°cýàDûƱC¢ è×Ü&W7~÷,ïT´s¬±/jöˆ‰;‘ÿ ÛFn$d·Á¾=$Óoºœ“ŒŽm™®É:ï᜴ùúðÛżÊõQi‘ÅtåBzZ’ gËË«™FÛÌ ºÂ_@ÃÂØzÔNü³âZOF¥ÒJ*ÄÖ7e‚Ý4d¨o¢Å¿“])€ÒÂ_n3\«fMd ų}’÷£V(‰ãªàË S[hÊN £õ·ßƒM¿ÕœÁÑÕ¿Žà4ãlK=E‘õùOÎQ8uN/ÁN®8mÕ‘eVWÙmæ:)uˆØ¯$]^*UŽ{ÀOø½ÕqY#Áç‹KçtÀÄ—By6Ç¡LW[v€9KœÅ÷²l-ñ T%#ž£ì^¿#yúµMè0.¸ï™üÃG™WøývâºN}MX1…}ëhãÃk$¹Þ=EÝ)yñ|㣵ä¶©Î £0œtž-ÌÑè’ÅW¿½S:9?éÄÐÜVf-ÕJÄ´ÆÆÓ “êÛ)Eãšý/ÍöŒñ«ïIGö_ÜìßÏ ÿNÖÜ(ßéÄeÙÄ.Õó˜aèM¨Hw¿¬bƒ±áór¹sçIš=laÌ—|ª‹‰x+ÃPXìÈüs|«¬ºËL r’?üyñòpÝõdénЛÅ2…ScíËþñä4 ߆Πq¼N8±gï¸VŠTí}4{cÜŸR`'ß#‘Nð Gl4*`ÉÐ ËL”ß׈øî¼|÷ØÆ› u^L·±äˆåå³1Œ štR©þQ:‚©$= uÏGB(–ËlXªîÆ-´Ë·dÌtœÿÜ[6TÅúÆòéÊÐ5³¨œwfs4CLrŸ|µ†‚S«¯ÓÞÄÓ:Wy:`"D|»3œh–´ŒVCH@±b&þ[¨}2íOä“G¶½ôñÉÕ‹¦†Õ(,Û“ÌlŒ÷GÒ0I’m;d“w=ùøÅWp š/¯øÝ‚êo½œíÌ Ñ“žÛi mÙ4½i:¹/ç/ j;?^C\åw}ào|w Š;¢î#å8—Úxbßz@»°h@MžÄ!wÐï1¨)d¤]5½SRŠžÛ~JR—÷ªGnO™ç¨%£Ó¼Ý©ñó­"M6ÈxÿEõæ%—´õÝãüîhdiË醤°Oãµ´óÅ‹g2Õy"gE¤­¥êx\(¹eø³UæœiV‹Ä›tî÷M ©< ž×Î66‹²:fî;ÖÀ“ˆü ËÄWÑb/ÄKj‘‘¾J/NX§X*šI.Õ¬krZÜ;jIÞŠÈ.³ñ-{& H¹ªåM>Ø×85išûÆ‘»·‰L&É7Ü@¯ã w—‘ÌÐùªÇWÏ+éiwТA* à´—p#CÁˆ'ëɤǓìÔhomšõ²çOõærWÊî|ŒÕñ»pFmgZJ‚Y=«:{¶ÖbÔû”4™¾‰fóîõ Ø÷†d‹a–µ‡OQ1s8¼‚6Ÿ.Ïâ#=”,ÁÊÛauBé=^nÕ½‚“J9YòâUmUóö,ks*K4—e?¦¹`)’å\%µÖrúÏ6j¬x¾ðïjK+Ìð«¬0ŒS,N¼ïp³ÚÝ~Á›¯¦RïY)Ý=uÌ•àyžÝýVl§At tŽ7eí=zhöáômƒÝiò@›¾òG]Žj–ÑRœÊö+QQÑ’• Ü饿;?ø¾Êãðr¥<`ú¦Ü»‘øry5ª—Ïêê§dj>IÙwÙÅ㤶µ?áKóhæ²¾§WÞQ¡¼‰¤ÅœDfór1\ƒÞK¼Ì 6î?Ë/Ä<ô¹Œ´–À9¼eÒ8“a3›Tj’­$Ó#•°DÇ?¢p:;Í>õ zŸÈnÚ,¤%R\K†ÿºÒðC¼í­öøë Ï=wIWUܽ*ÓZ_Ôkû0պͥJ>—+™ÔYt~T& ç™J#¾ÊPõD÷…©´Rqû¢¸ùðPÖMYXù©ãºכ̴̞ ïù€X…ásiÉŒŒªë[#M¸.ÞÙÙá‚ï[ ${æ2e8T<^,p¹xÁ‹^ûÚ“¢;c[Ë5ë”Ü^A«­Ï3nH…+=ÿ8‘çV,BþiÍÑ<kâU§·L¨Vñ°¥`?\s*¶ âguA¨ÔT›äö¹«V¾°Ô'±Ò9TàÐñT—/þzÁ:C^KŽòï á†Ôê-=ëc™­Öç†ÙZûR¨-xlS(6Ðv˜ß dÒ¦ß>vk\Þo†@&䢾êŽ_æô¡ßX×gõÉÖý¨hïn7ÖsÎ|áøÝVw2p²íÕ‡žÍÖÙäq†µ€ðVã³³ä»o´7 ï$^~—ùL& :(ã)m×±'àY/_¶ÌÛu†bùÕ³BÞë®$†Y¯0÷J‹n·>¸íqê7â¬D)É÷‚©PÉ€“:DôsrÊ4eÀXÃ\›‰íú1xê{tŸòTç¢l‡BÐ÷çë+û´«ž\Ô(šW/ãT‰Ïçbí_Ǭ‰ãž÷ƒÈ ãx#uæ´£Ó'@tŸ‹‹r¤ÕúŽ–ÂÅ«ºJ¹Èd+67ô¯ Ô÷×”%tn3wç:¥ÁLuVS†·½—Ûµ ±—Ïì›cR šæp XêNFDŠ8²”t[<q^õØVJ}DóÊ•ö«di£··œn@(ÊàÌÍÒNѾm’÷°·&·t‡Š.F5v¾†ÿÔlÞW‘‚%*ÐPF(eT§ÍWëÔ)”=Ã8, zŒû¦ßb„ÝÊÇ<¿¦§3BAyç:œÃÄó»¾ræDöV]zö¬mèæVÞZØþC}ÎY’Á oÕOiŠc‹Æú8iövÒú£3Wvä­Î# ºô! Ï…XÐ9ÀÂåÌñ6Ⱦ…‡Ý„0ê*HˆÙXô¨h‰êô†¥¦î3^g;j\$ªU†äL,Ž”ðð ÎF“îR¯Øãưü(ÐÔʤkã³ÿþ&¸š endstream endobj 168 0 obj << /Type /FontDescriptor /FontName /PXFSNJ+CMMI9 /Flags 4 /FontBBox [-29 -250 1075 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 74 /XHeight 431 /CharSet (/k) /FontFile 167 0 R >> endobj 169 0 obj << /Length1 2679 /Length2 23466 /Length3 0 /Length 24977 /Filter /FlateDecode >> stream xÚŒ÷PXÓ ã.‚ÜÝÝÝ=¸îî. 48î ÁÝÝÝ]‚Ûìî»É~ÿ_uoQó´>}ºûœœXI•^ØÔÞ(aoçBÏÌÀÄ•Waf01±201± “«YºØÿ#kœ-ííxþ0u¹€dbF. ;y{;€Œ« €™ÀÌÁÃÌÉÃÄ`abâþŸ¡½@ÌÈÍÒ ϱ·:#‹Ú;x:Yš[¸€Òüï#€Ê„ÀÌÍÍI÷—;@Øèdibd7r±Ú‚2šÙTíM,.žÿ AÅgáââÀÃÈèîîÎ`dëÌ`ïd.@Mp·t±¨Nn@SÀ¯‚ F¶À¿+c@ ¨YX:ÿ-Wµ7sq7r@K 3ÈÃÕÎè%¨JË€vËým@øçlÌ Ìÿ†ûÇûW K»¿œLLìmŒì<-íÌf–6@€¢„ƒ‹‡ ÀÈÎô—¡‘³=ÈßÈÍÈÒÆÈdðs#€„°2ÀTà?å9›8Y:¸838[Úü*‘ñWÐ)‹Û™ŠÚÛÚí\œ~ñ³tš€ŽÝ“ñïÎZÛÙ»ÛyÿÌ,íLÍ~aêêÀ¨ngéè ”ûÇ$Bø-3ºØ™˜˜8¹Y@GÐÃÄ‚ñWx5Oà_Jæ_bP¾Þö3P@_K3 è‚·³‘àâä ôõþSñ_„ÀÌ 0µ4qÍ-í~G‰fcPó,=:L Ùc0ýúù÷“h¼Lííl<›ÿÕ_Fy yEYÚ¿+þW'"bïð¦gcг°3˜ 'èƒïÃü{ÿ+þ/©’‘å?äþˆ(mgfàþ»Ðáý¯·Ƃꟕ¡ü7ƒ‚=h–ªß£¯ËÄÎdúÅüÿyþrùÿ7÷¿¢ü¿þÿ%$ájcó—šê/ýÿÚÈÖÒÆóÐ(»º€ÖBÞ´vÿ×Tø÷*ËM-]mÿ¯VÚÅ´Âvæ6ÿ£¥³„¥ÐTÉÒÅÄâïú_@ám,í€JöΖ¿.=¨aÿGZ8kÐ…â êÕ_* hŸþ›RÜÎÄÞô×â±°sŒœœŒ<@­!v€73hCM6€‘ÁÎÞä•ç 0³wBøÕQv£ð/Ñ߈4[¿'€Qô7â0ŠýFÜFñ'€Qâ7b0JþF,F©ßˆÀ(ý±e~#ÙßÄEî7q‘ÿ@\~#ň‹Òoâ¢ü¸¨üF .ª¿ˆ‹Úoâ¢þ¸hüF .š¿ˆËûßÄEë_Ä ²4ú±²9ƒfËÒÙú· ÈÝø7Ñ5v22±‚ž(3—ßrÖå/Ô¿ P>“;(˜‰½ h˜þÍÉöKbkû›Å¯)c4ý‚RGU üOŽ_zGWÐfþ+”‘­)èVý#¨>³ßägödû-ã_Æ¿!;ë/èö‘_z{W§?ƒLÌÿ€ €¿ëõËÂÓÁø'ì„L Ò¬þ€ ÞXÿAGgó«íµ€Jþ™äjZÏ?ô bí“9ÛÿG *Æá·ÌôÛý§ÅlÌÿHÿÛ`VP. èÍýÔã/™¥ýï6²ÇÁÆÕùœ ‰ãn}ç_7ͺÆÊýKaÿk*ÿLËü«_>3è,g99m-ÿ;kì¿l€n´€ÄôºýËTŒ³‘³ÅAµüN z ],œ€Ìè°\ÜíÿpÅpý‚úæö1sÿcÈ@Þ@PxÏ? èP¼~“Eò:ýê?—¬‰«¨/.=ƒ øø¯¯:@ ÐaaÖÞ„7Ī&¤õ®Jø;ýÎ(ÿùŽf 5½÷‚ÓwרÏÔ•AkN7Ÿ:ß,o‰S] -={5ÕÁ†7'(·<ú<Ä©Lì´ ÌcõŽå ×öÀãÓ« íú<;úhZC6ÿ!ÏvtåBQÊŸsï–ô¨í)Y›ÝQÞ­äE|*™¤VÒ ü:Mžcœ9ƒCãBOGƒ~î:}}3…þeì•H&ŽÁ÷8šµÀ[{åÓýŒ×J™‹s;.®6ä5úð…·È~’ öœwQÁrï¼G_Ñdºäeú7 û,é•–*‘v ]Õnà mÌÛÙŸ!”ïz1¶ª‹Þ8‘(bV¶Db¸T³Z öÛÌDVZo4:̬’ñ¹'k_ÓÈZGÞuŽ+ƒ½ô·aÉÍw ƒ[¾š_{ñÍÝ™iÄ-t"–—xÒ ’¡K\F Ú5ÒoßÐ-º}æz‚6 åóºyÀcÞÌgbÒæ‚îÆ?eÏö¹øä[^®Ð¶>6g㎮üÌ¡ðjü#ùü<ׂUÜ0#Œ*']¼ãcÎj ¥2o °~:¸„ñ|½‹A¬Ø“H.~“}þ¢¬€MZ²kg®b B7ÈÓêž;áT£\½%–=O™xû8’~d¿>°_$8´›ûÆtó¦´TDóÀ^ãþ¼ÜýƒÈÀ§ 5Μm*_ÚS%…#! o·fºàIOÔD܈mbP5Õø¶FÚ ŸÜéJ¤ÅÈ) ä{døÂ}ôæÅ ºp«„°>^7°Ô|W¼£CÊx³ò‰q|þ2é!™£l×Wú.-wÛ²’|61‹xnAŽ »Z'+ íçV?5q”Yèû 8“}´H8°-¾Ê·ý51I*J¬â9Ä!ô<Õh”hë/ãÂ(2¨• Ð Ý5¢2£`2.%`]Þœ0±Õ¤ã]ãíG3³R3ï®"‹Q$æÌÝI$ØcÜ/T?ùT¾Ú+óî&#"Nú}ãË$df*öK}åk9°=«k¸ŸÏX°8_ÍY+?€«¯¯ªJÀ5¼âL:ÂB4ΆÖùÜvÅå¡ÄÇÆÚÁ¨¹OØm%Ë6UÐmLÏ]T¼™*Ðdñ Úçr$–3¬Øzgä·Í¬ÁÕ/Â/Týóᄘ)¾C+ÇÞëžìä~ü¶/€¼»üÇĦûÆê‹ž}I× ÂàYPÚbÕu?GÄöT›§žn>É®¸ß“ã6¨}q@ \‚#gÇ®zéNQL4UU™%éuWÄ}ˆÃßO¿M5üÜ*ýd¡ðP7ë½­ˆ@Ia†”s3™±Å„¶¬/l§è'‘?>´íjМ +ÇÉ/·]6&gZH¦y0L;‚íÎIXK`4»îÊ´ùN®$Î’ÃC¨!L­*"ǸËW‚uÊŽQ"š%œ·v›iÃ[á=ÔŽHEÚ<ÿÚN&ž.,,„Ë[eÞ>­£[ ›jÛ@óÂXøÅ_ÖÇ^Ñcv*Ymí?î;²ç¶üþ+G@ivµþ÷[#—,"8!Eæ£ÆL0‰ ¢Äo¬ž„¤©[&¨òòsã’=ÚÏ+:¶e¯Í^cQþ0ðè6%÷¥$2@¨y ‘M|ß= êX¨eÕþ%K\ºœ³ÀÕ¯g*èXXß[$¢û K¾+e2ì—ƒšð¸ƒ*Ä1Ð}¯ñ »ïê§rv%²šÒëµ[pö=p.Þáe/ØÉß"á¡1Áë"6$ÊÖÆî¨|;k d†ÍÁŠ'µ¦dä6á…«>‚iPõeäm¯v)3!MÉv_4zeŒ¡—8!Fä–»)ˆµEÊKrr“IËY¾P$Ï›¿Û°³áð—‘P¬¿ä“…ß9RÉWü$,Œ3è–à¿:i“K±W§µ3WG¹0 ¦¹8¾LÑžË( xÁÅLc´„·\˜t…7ÎÂëEàêëö–*˜ù ŽàÉp©“íÑ´¹âÂ,ìZ^’‰ä <ƠÖ§:ÏbìžHkp)Î?UâáXà‹ ×¬ ö¤úm—òÒr:èæ»{à¢kmJ"诰‹WŒ,ï'`¢ã1XnJ’¬¿Ý8? "F²iÀ˜8e6\ære¸r¥=ÝZ y¸à=§ó÷¨› G°o©\Ëö€ìgJqB›íÇE×d–ð;ÞO^˜¿ØÆE×{hx^×/¢Md’è‘zùá$up»ì@Î$‹K½™ï)bpáþH†iר%Z.ÊüÐíRb*Dz[Ä6n­>)[ž=Å›×~8`(ñ@ƒ8¥pQλ¾Q`úRÖùx_þæi¦5‚¯·0çóVFF ¤s{!7_½d ²¨¸a¨ÆA®Åú÷nrLå„Q‰{¥ïÝ›hÁþd%±ßI&XY[o•¸ç¸µ£¹ÃÁ) ·Ê ‘5ïy Žû§®ûˆ„`Ì‚‘2ô 4WB)XØÜÑ‹m¼wɦY4Ï0jÜWB{¹_óvH ¿` ŽhvÑH ë­0z–D)WÃHÔUþÜùN‚¦dÙR ë"z__pcj'oœ¦J®V«Ð,ËS G«’:{¬ãTþÔ¯u݃q¢åôm­žÇG*ˆ¼× Wzø‰0*®.ž{|õu>%Ü>ƒ*EYS/®­,4Š*½°îBž·ýš”Ñ®SDÍÙMÑö”m1j—‰T{ E9½dÔùM­ë‚ò½“ÿôZ*£ÝgH¹,D8ª$!„š½ì¡ñ4„òzoY‰úµ¥s}ëtãÕN»C?¬C¹Ê<=¸%£|õð¦ï§èn›grkËÍ»¹l ?™SÈü1œl…_O?¿í콺´Ó^ƒ¤Imá/¾t¾>·Ok,äç9‹G,*JémÇ é¯ýíøŒp— ÛqÝØ!ÔÜY)Å”Œ~B÷¦rt:BŽÏáz#ª ’O“_z×þÃ@wÒ7Z³Ñ>/Ï"·`¢ ƒ¯ŠÁð/a?Yݦ[á` ¯Z¯ç»ރåsáÎäÛ"$-…㘻/Ã"ÀÝqîHÀk yªêù]„~H-¿·±™=(K€'JÊt#fºßoˆH BZY{8-_3Òùdv§äÁ šés«ùTÇ»$I8ûö «ÈOö…«§Ý» )]’©R˜;æ¤ÑÔv…;îN™‘ç«zgFÈÓˆoæT?‹=0•éP\t*6¹F${yˆTȸõ8ÞR|x°õ¬ ¶¬Çp8°ê¼Ñ,Š”ëVÑ'P1²ùqäQk=§•ÉSÃ.ÿµjm÷téíY,Ƨ–rÔúwþEŒVù¡ë= 9ľ«†‰§Gbšøý%Û³Êï›È`¤Ö¾î¡»Hç—·Âû÷Ï0,há_ÍÛa–:%½1øyl·Ø ‡Ü¦ø´å"¬M/‡l—™,m°Š¥oºdþ6¾Þ/ «7†7Ú°jü¤HV$|õœØý­c™¨2®A qßæ‡²C\^i®ÿu{Ø·Ìûú‚KÆh^XU\J$ý¦kžm(™j+¡Ã·¥µÁâTL’ƒ¼£Í˜KÊŽŸŠû­Õ(›Î³ÞðfñÅ:¾³›ßv t±‘eNxß `ÁKFpŒ›ëvœ,ÜŽ÷bU¥mÇÏSbîò#@¨²Œ ²–Ê$É/†|¶¡º˜ª'ƒ#l(ï0Ú:(°Ër‚k>#|¨»–æW"¤’Ê×µ›¦*Ù\£Õ}ôtïuý,‚y«˜ JÒú||vO< . 7­µS4õW–|ߤ@¼²ñ˜ð1_daXZï]€* ó-€ôjªÍeXG9L΢D‹~'ÈOÕéÅÓˆ ¯¤%Y<3ÎKÈ ¯U<­†*Ä¿²6A…‡p—'€˜ÙÜ0 &ežûfËÓ 3Èc9 a—¡S`q|¶²2gÌ:¹bѦ›—"©’”oo1­êKm6±-á•nØÐ× ˜»%m&¤*E‘Ä÷ Ý t³ãÂÌ”Â×ÝÒ¨.aí¹2*&öôlÝ⹘¢}›eBœçqd<&ÿ2ûqƒÑÌ—u-)ýh¨°o‹D²8 ­|ÒLÞyvšè½¦ú³ïÓM}C£Vw}´>bÀô¹ÕH±TÛY¤¢Ô+ÜÀÈ'"ƒûo‘¼ûá5£—þq›2n9(5zˤd °%¨K”¢‚ì©|!ª8Ï-'CUB å8™ðiFeuôoS…ýM"Âlì5Áëä©.c`œÀ¾’.ÎÛiy[-²úØ@¸T6SJÛd?û¯WïÔ=å\O)u{'æÂˆW¦œñ:íë#Î[)ZCf6œ¦o9Ü= •s¹z.“9]&­\}vE0ó5qì¢eïðô#~^Ñ›É|xw×~Œ¢NWÞæ’M½kÉ#u™Ý¦Ú½DUaT < Ðh{q‡Á(sÝ_聯äù°qÑ휚.¥­K£~â6ßFˆ<îµ¥³>$íI  ¶Ùø•§âýѺ`«í[™ø;,ú)Ö[Ë­9)¡åØ@³±àgëF†£ôëg7Ê€>[tÊÕ­N±–áÏ'"ά\$­ëYÑÚòÛƒzýo•’®ì’é°wõ Ì…¨.ŒQÓˆ/ëÑÛçël«™Ëí><Š ø:ÀÐîš•˜s[<õ€ë ÉßÎëO6IÊÞð²—Âä»÷µ@mK;9ž ±š ­i¡Yº–t®lw]~Ÿ8;žD×rzs@ v}ýhJ«R¹HvAC:¢/‰¥{K½ÙlT’?Ðl±9Æ­3ýÕõNu‡[67­[M¶Øè=Ù¶»ù@Â7Å`MÈwŽ}ÁyžPÒTI¯­VoØå¾–H·›ÔûúX¶“Åy‰mb¨uƺ·hEÓ~.Óæ=ÛëËïÉ`þqYoã¿l×nèz'çUvL„9»üa¿.­W‘ãÝ)c–çÄ£¡Ñyza?r„NåhÄÃɶañ¬¼Nw¼èc#ÂwH9^»–—rF!Øè¾VƒU{By;¾=þ¨»gšß aSwìÂ?¥0ÙÑ x£TÚj{]E~DhÜã:!r —› èÏ{„<“5Ö‘w&åž®üp.lvjéÕ×}úH9û¬<¸Q¤`lJ»ÔÚ¶’eO½ðU¾ÕkâÊüÐ|ÄhûS¬kDöD*_Æûϕƒ²qˆšVˆ~ó›W6Á÷,z±lERi#¹és—iúãŽr@ûšŒõ“+?¤Û‚øøqNcêÞü«T)»Ø,ˆæ¢raN’o±0>F—gùž¾Ÿ÷Î;…ÖÜÒïÆ›ågL@n¾Ž=?Òb,¾?þšô¦Ÿápƒ¸}¼‹„FfI•¥}Q‹°úÌj ™€brAx_‰¶t÷æ8ôEtþë$…œ2·U<5-´¤K8rɯl£_O÷ÓÁÆ(oŽo»îý%°M5$åféh÷°œ1Ë$_ò×õ‹뺠nÀ-¢zPËîïµ Ë¼BÄŠ]„Xoèié_öåç…¬¨ù4- ·å[?¼Îå¼úm×O4Ädf|’››ß£úN|uŠèÇîUëîßG4Ãy†HÉ‹OTòå…Ž ™j•½™"SËn@‘¸}ÐÝÃ{¾ÕŸN€$ÀƒDäM…o÷9Tˆév!K¹Ns¼*÷<§Pf*³öóz6~"b½"Ræ)±2F;Y"ot‘‰ƒeÌQ|=Í pÒX ìÄõЫj‚i Þ<ûÒQ¯`“yÉnßöFg/g\‚÷ E%†eq„nµ‚r‡ô¥ÔôÈÏq¢vA5ž¡y‰3ì=…WDXÕ÷+LÕ|eÔ-ëš³0ßÙÌš$Ä,b–ækÕ ¨õU¡'è CíÜ}Ÿé?h+4ŠcŽ‹‚ÿ¬¼EÔBŒVÖ{uNßœ³¶Nê"|›w9yyÑÚ`7ŒÁ–ð3H÷舆TÏò‰¤|_ß")„ª>û†CQ—(5doùFà‰g@Ãàb@`¦›FšÉkª^—Ä{îŒU}Ñ«÷bÀu["à rx!?ôZi­hZ<öjГzAƃ;uŹ9FĦã4Ϻ©iASå2æ XÇ>Ä‚ŒVg{dú&¡xYHIΘ-’råñpˆÝ’‡€ö¥—³Oho^·ÜL*FDO€YÉŒmë×NaÖ³˜ÙsUD–n~ܸYZÓ†ù„'™ ÝåZ,ÂrüK,“ãEœ€§{T˜!—6+æ‰Þtá=§—ÌŠö‰ŠÜa·N:Y"pøËºÐ±Ï«±±)OéÊ!u:Ë«|êïyð¡‚—MhoÈ׫áOZ–ETÙ¹Ãî‚;jÁ£K²Hºf»3jÍ÷ÕZW¶õ‹5{à`–¨jhÈQî0ewûÔ˜Q [¡úoˆÊ»´¼ ø Â(°’y…M¥Eß2~ôE ·€sxéÙ\¢?GdȲáÑŒÊÒãέh¨î(EŽT—HRwcu/?`׎O‹Ÿ±ÌK)qv`WžhmkÐ×H  ‹ËÇÍé¥õ‹|ÜüB†¦wÁBΧܴ»é· i¡¿A¸u0|\åŸ×GºØçmZèà>Bfù`yHdÇí”0¢îmç5äË¡ªwůd°u‚ø±^ Ъ¬æ \  ¢ó5âVÑ>ÿYS‘£„Á´w£Oˆxo.y_X¯{O±bY´—Üeyx6´…zW•¶Q³Y§#€|„d=*%Bj<Å„@ä'y(Îû©„°?J!yR¢³ýç¶©ýݽEؼ'¸hƒ«²ÝæÂpÀ6Ý0Š…–(2ü·ž/`–_|^^®€uÎüì’x¢ÝeμM´¦ðÌáý×Z¹ÐZ輌…“ÐRøúÓ& ý¶‰P¨ä0 ȯ$uÇXŠÇíj»þšÏÅó¶$Àba±” àâ·åZflM9Ñ¢¢qÇæµïRŒ±Âà4sà®’åFv)T A›ˆ"nûGÌ9)º¦u(Â_­¡ö FŸ¡¢5´¿-fÒl¶ð–û¸{ôðR„y••ËÆÞ#Ÿ}çžy =ÌéaEÂoèFrºgºP™9ç†Ad„ð¹·ùvqp™å¹0 ²Ê¶CÞ³N–8ÅÐä? xmjpJ¾É3ôä!Ìb¦°_%¥½n µ_­Q›pǘŽÍ>µŠ”^ÈaÕúìà'=€êÔÔ“Èyn›˜«ð!¦¢õV¾aHÜ[ù]õ3ôT®JÌ$áp?š F¢$ý¡eÃbgPUæ¶ëñxþP´1ÊÛç˜ÊIVÞ42§<¥&µAÏ“ª~NIë§»jAkºß P2‘¡×äÄ&ù`|Þ>Ȫ±Tžq4E›>’í4óâ >+=ßå9*¥„êræ¼ø]}Qö²eô·Ê¾hy×nÞÚ]œÃÇ¡xïp@U¥wøî]Ë9Ù÷oHjrÒ«äå“ãWi|¬ï|7%|ᒹ柚'¼«ls©’¸‰í?¶¼£êiå+…µÜf¦>­#¨-zk]#=¦ ÜŒÀï3];FÓÉÓbmçG+âí€WUÑŸœ¡C.ŸÝ#˜ý®u\L*()5”?¬t‡A ³átE®·Se?AË« XÚbÂü=åŽã OÃXœÖ@tåXBAëB³4k¥Fw;üw¶Š¾£8ãþ¹»r¨Üf*j£O4‚)EÁ:ŠƒH$ÞH¾/›ﻟóI‹ÿ&mŒ¢¤ëtCóÆ–+Iñ»§¶ìµñ*þçO§Ê¦`ð?ÄNƒi1ÏCW‹\_ëܺ[áOpi[ãä…Cï¦cèñ= .xÛ`_¢ú7¨”ó|ì¤7œ³óÒ$qí¡hÂÏzJV$KúÏ‚0º‰ª¿«5Q̪; )ÒååFSQ¸Â±?k®ÞŸ¼Ñš®ç™e©¦~¦bú„i‹ƒoÕZ§¯"µ|Q_Ë·t¡ýÞV§ƒªïó'Oêý‡|JòGÏÂ4ÍÌlªiëùÂ~,…™¤¤Ã·l.a²š”g7ì߆yôŒË4QQµëÖö=C½­¹÷–Œçß´Ç÷Z9å°ïÕX[ÀkE~\R§ê{ÙHÑ~™é™Øl]‡ð”vßšARU|ð5àœsRÇõ’Åpåsß(Süd„ôƒ‘:ÉÃEGÁFÆ ¦_ÁŠ!«ÞYŸº’FýYA§/ˆlœ¢>©û±Ì)L*WxÄd[üÀ[·K|u’o£ë¾—Åøök¤Šd46ÛabýÇÑäý´&ßtH–Š«FþLí4ñ²¤Îïø‚q©Ë?­:UÄÊì5³-;Wü ýù}k8•˜Wê^8=•ÍFaŠß•»J®PÑÕÕñ"“=¤wÏdrÞ$àÛpb}Û¾&¬oÒb›’}}ëFrVÚR*æÜ çö°Ä ¸ ?{ªIÒg¡eåŸV/™X¯¦“ïBW‚.>®Ë3ÁNAF™o\ðïñ7³ZèÁsìõ!óôDÔä¨Ïؾ÷›ÿ* ë“D€‹ÍÛQf&P¶_ž´CéÜsàÏ|azD›Rm-ÔFþ’~‹¥‚s>€¤^»Ð¦ÊÕÌž*ä&GG/ (›Óð5v‘9ºO¡ÍgLT9 (ÚµTÐàRôr CñØÉNO¿æ¡º)xÿ¢1­ÿÀMìýO¡}” ‹Ô¼ÆCY]ζaù;YgŒ´¤õ¤mèÇüÕ¦šÒ½o÷†É„?j1r·5>î"ÂG-T¢.÷=Üø˜;{êQ8(œÕמdHõ<×¹ä]´ =áϲ1–¿`_µ%çrì}ìƒëu-qûzá »6xpuÝëÏÃFƒñÑìo<“Ö—¦ÏbKx†8ïµÓ¶¹S}[JƒnË|Á²G~¶Çxˆ·yNJ³š]#³Þ7ûºíãõ¢PåÛt‘£S¬ ê•3µ9 w`†j+Q¦Ý÷bùX„sÁ²„ÎYÕ #Çz6ŒÇ+>°Lê%û÷A( C¾j£´Ûˆ/ø.`O”ëÍ+ÎcKð¬h÷rÏÖÅÓo=´É~œÝñ,Õt”öR9ZKÇóÕ[]|m?Ap·òië>˜ç±æÎñ~n×…A\E«é ˆÝÔ.D‰ mä¯WÙ ô}nˆ}N®‚?V{¢K¥Ó§H˜AŠ…ëþH£RM¶&òŒ«Å£¤×¼“.-:ã¾ÏB¿Çgi¨Z¼ÈPÑéÕè#dÞ¡Ö¦ž ßÕILÓ‰IfWpó5üœä Á6ŒP¡²ƒòÃz6¯jÊ ä³Ó1ÒJÈ\g`µr߯eBf9¾®¤»ö^Ø–cq¿Lµò"uÆê Ëö:‹ä"„0Uý7ŒtîÖ(bTÕÌ‚V˘ác¨´&íIÁ²‰™1±å-¨ˆ´~êI·*W+@e|ž¥ø¸]‰™'« À'/ë y?OÎ-_‹Ðn…3µl±Á.HMF>¡¡J|·‹¬§°y¿Úƒ[‘oÝz`êíHoù5·.nÖIÛõ1ãR8¦ÐÃE3²±åæ„Wéä8ÊZ/—Ú#i›Ò©‚i¯,‡ö Í îýÜä¡ÊÝ×i ©ò4­‰Z-C»Ù:Ž]Ýi~, J6Rx\<¼%NøŠ K‚y5O™èázʲ{};…] ˜%Ö3ÃØQj0=r¿ó‰Î.³ |²*û´ÝàB-t$QŠ{挳©oÕB¯<÷›“Ç€ÛTû¶ ÇÇrêçÔ«x½²cQx£/C+ªÑãåKN.{=„£ç:¥ñoµ¬L”~KjŒNk ǘKŸƒn>q'”#&hîËòºj×£›Â:'$ˆ”¯‘À}·}˜BS}œw¬‰ŽVh÷hòa-1žf.LÉ­­MÞ®ceì7«tižncçk 6(EúPî/E+tï ’ä^¹3É ›"6 Ú'=…‰%…׋…WhH¿Ð¢ïâh‹½ Y)Òò?H²ˆºÂ×{×sXQ‡G¼Ê‘3Eß!p["È~sTú]ºw l!“ÿÊ"Jîü §Åô@‚ÄŒ’€ôrÌ •¢,ï ¤ƒÈ°È²µ !žæl"eQx)~ÕßȆ0³É^V9¹\â+É\ ‹•:ª$%Õ¥‚Jn µÎ²» 3EÏJ îÿiIEmÙ_Øë$ ˆJá0àÃwEGn ÷!eÞP©)¿œˆ·ër•Ãf>Ú‘°'öú‹{¶¬JFÏmpua#P.© ƒ/3#ec½ZÂ)yVæºÜ²¸Ø)'¬-ÑÔKÀ?ÚÓ‚íg ï¬Ú­Ã0t5kû6T)oJ ”†¾‰Šµñl?jwc*Þ<9vÈ<þaEJ¯Ë*tÅþóœÝ¨§·ñ®j,—y©¬ ¦EŒa$7çâå¤C¦Ûqã`0\JU{:W(ÒÐÒ’”Lw«…£@±>Ÿ6á¶Ë‘e‚tI}­j0°Þ:èf * Lpf¤’ Þ.‡ì¹ Ñ7ùe+ÇaÒòk:‹‰ªvL—²3 ¼¨•’Óªª^ Œh•ì}—8ZÞ+>£Ze{ó ÌÇ”«L©`ÜÒ!Ê“I~-·ˆlkI¤ÍµoþG†oú# žO¼gÖ_‰1_ ?à–MmâÐ-Üe« ²"A•¾¥;¾eñ6ô µý ud¥•SÇE(²Ëaèð‚Ú–¦6>fM¡£^*º‰e ­»_AÉ TÜ‘x%Ùþìÿ¬Í†·l¹áÑCkP—ÿÕô @f8Hþ1" ù& #Yý¾?ô¥¹©$YRåí¡Ó!áØÂ^o/ÂhÉ;s†ˆîm\Û³¾“Ò,?¯°ðÙG‹{:v‘úŸ+UÆtçþb¤‘Æ·/¹,ë&µŸ?–ù³x› g@gãKx*l­"“²¼¶ð}zIC,ýˆ‰´¤…¹–ÅÑúâ€õ̪Ñ"¶Ujd_¥°ÎF™8^ºHë1j´ETöð·†NÞvz賓ÛÊI?<æÓ¦|NQÉÒåæGÍÏ8§SQýˆlÔæœ±™L MF ÙpPáOìûýýhCÅ\þÎØ 4eùÂV]cí-!R‚½IÏ{úÊ~„•žcDt¹…n°âÁCÇ7úmêú‚‘|i<Ø‚Hw&;|ËL¸/é#¼1yæSb“œSÓ_8™‹Þ|NÄLvíÔ® ‡ôf£Gb¶ð™IÜÕ!8Ÿ/,œaàóD•±!,O¨?ò˜ Æ}#‚¿Ê…™)ûìY‹ºs8¼è”ìK¬CÔÁèUv“›òÜo×a_^7ŸY½Š6 ݤ5Ûaí-ÅYïów¿„ñ ‰ ’&Â>$Ù¿º¨¡ã‚Ùžº˜aj' y¯£ñ›þóòfñ¾zÿrÚ¨d=¹ €JÄÍ\u¬Tö¾å…øâ©)YEÌñ|¤W ðì%øm[K–ØtÕ·áûŒüˆ<΢LÊS›1Mðºñ»§§,^ÀÙg9ÙýÆqò·ìÛGùƒ©g]ÆÄ*ÿLwÑÅ—|Š=§uRpŽÍâµÝ>Ï"– ;õäø˜¾`¡ Â8Ê—·¢ÑËOQ g3ÓµW?qyTÝ5ln`j†[×{ÆØãnv?ù/Í÷õÖd»´½‰Ö!êEáH:á&J<âùñ¸g)‹òÕZSbe³1áÎå†0›Š¸Ý¸.òdyo¿½ÌÉ޼zp¶žÕ4#X}ÙõƒFbµ]´S¦:¼.uý§|ÔÜuTœw(-‚]¯§ã³¥ÞîS6/nè#§ZùšAÌ'¦hq× ÒBTÞS£ü,âŠã;Ï"™¹ïП~Hå†DÇ‹¦“gº?ÚTzÊf7¾S-Þ`gCñq&ÐHóM›‘nü‰L:€Læé5®zœ+¶tBÙ'ƒ¥ “‰å\£Á3¹bo¹lÄóEz,S®’HÇ£‚­|_Ä9Rõ2 “?~å`¤¿¨„®) Yªqe‰—J€;ž<#âŤ3˜úóreêCQþZ‡áX.N‚ _ôÝQØ£]Ž#b¹>#´'ãû2ÿDöýjPl$Lö½ìFŒü)UùSs kÒÇ3ìŸ5œ38ýò}ïG²q c- 2 Ûði,É|)%‘„Ü0ªÊŹ%¥hdí¦Ààó9ìÙR/ šÈ'€(Œå8¾¯0Ǫ°UT%’9¯^3gbW9èªßÂÚßæYàä±ËJ;¾ &|Ùýය'Æ“·d24VÁ¦óÞA¥Mn±[ÝMsÂ8Ë×?œš83x>#Ø+êúšfïU×ykà€=S\/#îÖ¢AO‰«;üc®#o¨“Ê#˜àék¸°c‡}dÛíAò½ ÒémÉ—nÚ)þ¦/Ø‘Ó0ÈópÅk{‰¬U—§#Ö¢@òè.Ø ª¯ÖäŽ&’E?pöê€ R:†V©“½·ŸI)½Å]øõtq«Þ±£w0%òx›$~ å-J2E’>RYÇ`g¹»:…Æüô',2ˆÈŒ”tÚæsì d°7©š¸ˆþ@Y­¿×í¸l£|LQ1 hºoX¡—ßÞ¬1^¨¤]ö¥×šÛ‘ŸÇа. •&óŒ9h9lM,ˆ<>únò¼a$è‘ýkkÖgìoèt~~1Þn¤„ «š×Z—g2àõžùØËeÔ/}ú¸’YT°Hi0å{G£ˆÄ±Uù߯íÌêMŒâWÎk§¨'%޼WVÔ.$Ìß­Jqðx³‘æ)è¯ÍŒÖM<˜º^Èá£Ã¤$Ž!vØÏød¸úl`%)jË ©©ô /”aùì”÷³~ïk¶¦{kríGÕüiÒS€€mù,ü½ô–tÐ’Ä®—ŒäÛ…ûu¤¹„ïgÄ»¢ßyôªBzŠïv#Ð…ÇkÅ!ú‹¡-:/Í¿j˜ŠÊ9\µ ­k ¯Åñ剾@Â)jb‚lÛFøBtJ/ I“ˆ˜ ÙµF® ’ö5]Ôñ±Ñ-Ãè#ùVÝ)óT,׋ÞÙrí°Æ,¸Í•RW PˆQ"e°†ÏÅ”€E#Aob¹ájÖüBþY¨?çôpë#ªÝ{ñÓCg/ £Ç "8ù¦å·ûÖOa¼Ý´÷†¦/CX8ßÙNvqBS&8%´Ûr%óU7 K‰3bÞ­Öm)£öl%dä»/‰U~ÔÀ猗4ݲ¸!ó\†”sÐÅ ÁªLh¼ ¸Œ;eõ"µ_y½Íœ’…**áW*m¼›oL,pl+ÝhaÚ|‘Ú&u=Çef1*ªÌmí5.ÔÿœÇ«“XÀèÿd¬r ö¦µ½XÃt`Qü»pÍìºËx[lØÆC¥´ªZ¸¼TÀí±%ìó@½Ëåª6t$ûÍÒE(ÎuŸAFVÌFîDQißrÎ5áFkQ¿¬ ´/¢I6/Õ1´Â‡£Ÿ\~DT¸TCö|áz*è]Ã.ËUúÁ®¶à(˜•u)›Ê— œmßDÖ8f¼GÖÒÎÈÕx£†ZJÞ¦×P÷tÅC:ÉËÉÅ1èW½—y½à߀ýlq# ÷+v#Q+;¬:Ý Ÿ<'°Æ–¯ûÐåZ³×:{6â ¡2ô øÄ…ös`11×Â7,úªŸÛ$˜ _‘eõC®¤H›J… fôRaߘÞå"„ÐÏÝÉî¸$.RNwxmyªîàlZå¨ò»½¸·ÇžÓŸ1m5Žõò¦ëI=¾ÕÛœ[ºF’e×ó%›Du\;•®ùýûÎê0«'ïñùCäV—ûÎ5µ„EyG”pbâ‡ߺ Ö©±8ÏG?éîÀ˜'„2ýˆ•‰ÈlxÁH7zA}:L°‘0xmw¸¢«€øÒL°Ë)R}Ñ‹Ì`W SÒ]°ï B!ÉîïQ5SûÉ¿_ßåDâÀô®ã9hZ6(NQ âŠÏ ¢?Câiö-7‡TR+}qó š‡Âï4øZ‹ ¾K®'Ç–d­eS jëëÖ&n¼sÀ—ÐÙ¹3@óý‰%g=\ñSloÞMÒE¾½ø2©¢›¢ñae-7©šùþ——1b@i…ʹЋ¯O;½çB,¢KÅ»ƒlZö]h!’ñjWô6ÎÆ¤½Wypy=±è&<‹˜SnyYü‘Ð<ã  7ŸJ–|ºØñ˜ØágxÄ…S8^ßG3ZÕáBêx£ð“­@ÛQíUx—ä+ñÂv/¦zŒŽoïQeéÀÂÊä:ZËŸÍã~ƒs¡‘ x’äu‹«Ä¹4j%Xû^ÛC÷‚×B80Õ¾½Y¤^ÏkOσâU V '¥Ÿ—5êeû€y?W¿ú\0§,/Á¤QÅŸŒ¢í„¥e,CV,ô}­JÅJ*æîüøÈÓûUmöaò3­£¼ÔËÆ¢ur•†›‰xómñŠN€™è~˜´‰p7×_>„Oä¦Àâ.ñŠÉŒ»k'KˆICR{7?Âg6·çd¬BªÐ 9—›¸W@l2å þd2nÆL tkÈcïywñXÓM\y°$Ž­ôSó…ϱI½©µÚŽ%Ó½ÏιËw›ÕüN¤ž¨¯6Ñgi™q…dd¦®7«u'ºklÐÝf²X¯gèÝʼèïà.ÐDÇêÁpÎên¢0ÂdŽku]ƒŸÊBmîÞ\ˆ­ C†*›øéG绯巌Ðë7t,M(sÙïÝùIÅ~BhM2¨æ ýj!¾>—]¼+`ë…"ªc]àÁìW‡/UækÚʨêË{-_Žñ ùo]3ë'“Cé [õa¸c…îϼ š\ 0êá¿-ÔR·:eÏÃøQ ÄïFX§¢ìm¨"rq›íáiôÝ0HŒT6Á6îúÚ'"`Â>Â_»Ï ÄhðÍO;šµcŒ­™Ü ßí#ÚÕ¼YLÆîüÚÞ¦Ïçµéd¬â}FmòÎPÔP"˜ªOJ³*cÓjÏäxÃ\@:rÝ*Üß%Uÿ1‘Ù4Â;ð‚½ô°‘ò;#ƒ[ü-*ÅYN] &Dk ùÍìe£`ЧKdý…½]†.A2ŽZ^,ˆë“ÝmM–ÝÁ>¬›ÇL¥ ¨î®8¾¦$Σ*§µèb¯ÔÛ‘°\Qø2#€¬6?_ð»ŽÝðæ£æ©|Ò¹XV«–W† * qUK¾Nw)É•«³lªð´”´ÅT‰A–ÛMÐ<ðÙ‰ ¶U¯7×¶-ùÊ·¸ÚCúC÷Æ%_¯ðcÀPäñ^®ÆÛÑž1 2¿Â…ZM·%©ÐahETTµs=TLÆkbäy!íõoXDÑ&V¤9cJ>ª—‹Rˆ¸o›¸ð•÷€‹gQh'ªqâEÁ“>Aw«}qó ï+ÞLD½Q¼Åm~ÁÂè’'¦çVq^ˆökº„l^^êQú\­ä?ª;Óaö î|Öe0 @ÒŨGùÅÊmòQV•}N'@G‘‚î¿Ù”Þ9_e9âuå—$/3öÆä¡Û@ÎâpÃç¶›t­Ž¶hƒ%ãÑfV”Ib¯¬ðfX•¹Ìɸ’J¶ûl]/%ìþº(ØèHàõDœåzù>F“'ÂPJQænÁÈš0©³2ÌvMþ¯{¶¢êÄ/±¸²âÒ×õYP†Ÿ(’ªÑetºä½KxÊs Þœeº“EˆèS×#ïÀzDÒ^éÑú—£ÄFIå4²—îñ=ò!ÈèCVSCA«1s¨¤ñ·.被ä¤çáõbµ^•)[Ó ßà¡·dRW[ë}q-yÍÞ—Ç"‡”°‹7n Z›'ýÆ3£©‹®´1‘=CÅÇ’® %×ûè°M×~¨zúí=j‹â¹¸ÂB~’/UK~fÌš™dìiù¶t@ºRl•.²²ržåЉKFLt®õcÛ·Kgrô¡E&§Þ>ÓTúÑ7ØœüG&|¶… µ¢­w­êKõäüFÅ×¥ÖU‰\·Ü*¶–õ½£eÇu¼q¬}Ux¨ÕäeìÔ›’ÅßÝ ýý «²GmYU BOy[kE§ Âë~îufùí-é…®BË,ãZÍá>š­S2+Z`–æP£û÷Ñ7ÙjŽÅH#MåI=§pΈ,ú`Ä"u'¾Þ~Á`Z{iø*šÐÛ¿À\ß\‡sYĤWúlW嫚쫸O#ßµÞœ@½HXÓØIHp=Ó8Œ(Ùöäy{ÂäiöÈÍ„›õR.îxMß^B#@j µÎ5ÙÁ]f×rJ(-!o |X~ýF›eHI«þJOáâCFF'ú[žoesŸˆýÒ/¼} ¼¨iÞéo¬.«+W‰Õ*4Ñ[óBŸˆûâOeeŸ‹?b/åņ,—¿‡k>žÎ"™Åeÿ¸C¾œKAùòí–ê )aõ6!áÜÏXê]~M„Âõ_ì^)xÅ]/ËNßF«ÃGö#°1ø H>Í€¯•|ˈݹ*-¸à»˜ñ°K!xG•*˜E—Жä‘—ØÈ§Ù ‹`SVÓ%ܞǫ͒øØø×9py6¡Z>ǰ¤Ü:CŠ.îiŒ°ÅÉ$JñŸ¡j?&jO³³'•MÖFŒkÑá¤ÂŒÂ_>‹-—!gßÂ?Ò Zq5ŒTU9k¹¯@°9–å抗';¡Æ3½oj"¿T3UçÝù’þDÎâÝ5ªŠ-³žc,Ç;ÿBˆ*»#×Õ?­‚4ÀÒo‘Š ¤j3kƒ†£mYp°HJϹ•Ž#˜^ã~a* *û‘9/NÍßÔfAæÿPM2 ¾íBe.•%ꢴÀ=3ë)s¶%³ÂdmÖÄ®ÿBÀÜ8»Âm—½ž›É`ÚSß ¾ÛÇŠ›Kæ%X8SIñ¡¸Î=ÜåÕG)•uw‰ÿn NÆó¸ÞâÊ›yÔé•¶i5!Ÿœm©ƒ‚l‡\‘»½ëЮØ"Q3Ûø9ÚÅjv3} J‚U'´….´}aÉï[%u(< lÙöCˆ 3Þn„Ð+8ûê¬Â̬ó¦y`sò be…ÙL'Š®K¾>MfïfÈ¡fr|“JŠKÛÌx¶3§õçlËÔiÈð‚\µ9J¿ï$4]cÖ.ãø;?jóLó1ne9õ&ÇGe…C /=Û‰B`¬ü¢’²Ðp Áw¨à °i¦üœP%ê¿û¿Q&?TÏä°â)øDGCšì8{E¨+¹Í Ñø„öॠŽ|ì¨I§~ ¦ŒV7›{¶%}σŽgð@¿«¾T» ÷Ø®åˆô®ü¸®A‡q⩺ŽõÁMr4™dÏ­èjñîsX¯Ä´A‘Ûg“®u]±|‰Ÿ¨Â4ïr"ù7ÛÂlDdµvÁW†h°jC‡s Td^Ýód7œ ˜ØÑ—·¦Ú­œÊj?wp3º Íï¾ä&G¶¿ãÃ÷H#'¤¨MŒîæ"_žS‚5’©®Ó¤¥ËIŒ}B÷(”©a6/‚THHÚ(Œûø ¿îÄe\£‹ä«Ýùm%¡3½L ´kmKïíóÇCë?ì¶5b7à>395Û:Æjð´ôöNEÚ`üG¤¼–Êmàjg£jöö—lû2* ñ”¼ '´}Àu€ØêðiKÂ…°…ŽwçŠT¶Î,Ø šfÌ,Áî …ÅiBÓf‰·ÛŒç)€…»‰;ñ]ÞÌc­å6v ¦šbK'J„^(šcnÝúįC„K£þõrC´b¬†Aí'¬æÖLyk?ܥܕ¢Þ6Wì¹[Â’xÇÀ˜°Ñ_½=çãÜzO~~R˜ö}°M(ŠºÜôÓ~2_X5¯F­~áúøtßcÙ?dG³œéƒ{acP„²,&ls Ó÷oBÓºE¢'Ë…ÑJŽnn½™h (Êjœ 5- M½rmEH¹£ìŽï²¡OýÍÐ45j)CÈ@ÿ׿º²~+C¶’˜âòfMQêö1°k"BLiKMЩXÙU…9ÊŸï¦ÓêßU߇½üðÆ]uDby`‚’¶ez¡¤HÀ'@íõ ›¨¼‘ºŽjÀ°¾>è°m QMj•‹Lâku[°6pfä§Aw¿ñýä†ÁC°‰QpžçsÛ†ûÖ‚¹¥öjóÑãåÃD5ÚB¼©†¥/x'ëoÄ‹* Pz±éÒ.Å#&f%zÔŒËú®(ž,ÁÓf_iFiìɬ¯›G¬¯ú¬8ˆjj¶P’ïÁ¦Gâ6çâ$:Ô²]!»½¬‚öðbä—ÓpÞuúþ<‰ìúš¿jez!òuÛøprKmÆŽ=R_6YMoWÿ¹*L¾¨ñbcœV>-r¼ˆÞ0pú]±ë7VïéÈsy1ï`à®ìDÕѹ/qÂÏã:’6^ƒ{ Ë·B'ÐS)ý¯ÓùŸs›‹d‰éÔ ,Ÿ9ÁøËo"ÈFŠp»¼8Ë ¸ÿŸ·HàQ}UAÚ”–rªn¾ (Ã+â¡üÞ¾^æÝéN@æ’@ºš©üE¶bTúIÌ6"ÇÜ,uý…°»jzŒ0©?7½™yžîˆ®¨1•~ûµµkFlÎïÈǤøÔ@ä8£ˆÍçÆlñÝJ¸%2ן‚Œ“„qœjz˘z’[3+cq´ÙÙ  ‹pZ^©ïg¸ªo€T·0aHœ¬è:”ˆ{ìÜ=3ȶ?”ÚÀC©òêÍW£EÈjÀì—t$Sé1ÞQõõm:!PeHÊñÔ/Ø®âôygŽÓY—Ÿp?¬By‹›6´ã,Ó×äV¿I Ø$Ne¢c©÷ÎÜåe”1åëÇPrŒî®ÅPÈùcð€À®³È}WJÕúx}­Þ8·ºÜka ø î* ò fzN ]Ð{ð7˜1)(6CB7`íup¹þÆåàÁTJ@¡˜F’›éܾ3óñÅ¡#AºÈÞ,1’Eçd’ì ÏÝ6‹ÖÖÈ>D toGd!ÇsM{L&¬29r‡CsŸýp”õ`{Óyq`w¢ !‚ò’Ä™ÉÝ­ÎhE¶Â u½»óç®Áxôˆ_»|ê:…âûzlÊê SÌ“®*:dek¶ˆ"E-³ HÛ–ûJê°Äd?i ´BŒ""Sü|Béâp#Z7RÆkÛ–RÙã ßäå©^ƒãcþ?ô³Ñ‡£ºñUEÚ~ÛN­GÊÕî(ð·«¿oû¿h–ŸÑ8-íÑÈ=DÏÖaXä–…QÇ…9ô9§x:Ñ %½Ù︣"Nû¡\á{"ð–ÑÆíoÅZ$™ÎÈÄ¥äö(¤ŠÞiLúï"@ÉëÑ>Q› PZoh”^ã©BËR qgíù~Àqk¸V¬ïNH(Ä>”é·Å-,òØpˆgÀFGD‡ù¤•Ê6¶z&žL,ìÝg«5ÑÖ³ˆ¯¹ùà(®RøxïÛË‚«„ŽúcòJ˜ /›g©•ÐâáêB4¸ j²"Ä,)xª¸Äè]B?@5œyŒo¥ùËÆÈ ¡™×Í›"i&*ô Ì»@Ö6h°åŸä FkE¥½s$Ë}•ÃÇáÍ…ÏÄBÀÄÆÄŒ¡n*‘v•ý5У޺ ”} PÍ5lŒö@ýlrÞyTkã­š©I,´B&5¢táÙó‹/¯jÖxt±¾ò“Lâÿ­Ê{‘·ÌBÿK Êܫ톽·í¾òc[äW ŠÕêBí.’®Øß×½â®ò&ð+á{A»í”dt°LNJ¢„@ÝHï¸þ½¯QäÍý¿Ù æ2xúÁtOÓ)‘H:³~.…ÉÌÁXÊlC]ÅÊñ¨Vï}sQué~¼bóýÕÔ3?êRT+ÙŸAØ Úϳ1$öÆÑÆú,èó§Ó4z–dÄZ°vàé«Qìµç­´DŒŸÌÅ-¶Ì“ar{¾2a7J@ŠÀÍ’;(¡Ð8ˆ2é¸~C('Ú>[ËŸ MZá°ÐЖük ·‰Û³Õ±›~9]òTùî—¬k¹ù–ØÉoû¥°©O#ê+RЏ»&!X jK6ÅÃrnñzÙéX7Y¢ Åf=£•çëŠIçˆL3kÚÐËìøƒbÅ¢œýt ¦±Ñ1&.;œãääé2rü8räµ#›êúR+qHP‰uAžêRÐþIúš ¨Ip$ôì…Ñë2kNׯþÂý§n® B³/& 8ÿ«±¾;>ÜxÏÙYWzø*«,!xÔÁM>§}bz…sT'äùL” yä„ ³‰øD .B—|›†˜€í`<Ëc K¾fŠY{ùÑ“€×lü=¹ë#½Ø ÖÍåØÄб߸IvZ=ú¤ŒÃT!#{ºIÇ_fߘyм0d¥˜s«v>;…zmú,$¨R.ŠÊñ5pYÏ ¦çËà•¡U$YJÑD[+\¸6H ‰Ò“ìÙµÎ@þvÁ{_€†ûþ5ÙA.fìÀžUô)|hƒ{F¼tòx܆)`‡F«tìhÉÔU¤´v+W 2¦q“uÂÕ@+Ù §%€Ç}Æ e´Ö&®dKŸXéÿ~×£ÿY°-n«"é¢ãME^ÏA¾r‘à_‰ØÓ4 ÔV:Æ(žÂ¿u2…2V¹¹EÂRFæªÛ™§¶B ¢æH½ŒwdèÆMÅÁªªL›é²Û-è ZSÔÿÕš €V\‰º3ÈÍóÅ1®£¸ÿÊkÙ‘>g™#ìŽYßO·» ã·HäÓ˜g‘¾ ý‰'C‹€Ð¿uR\‡ò#,gá'©v?eGÅBxGìu‹’Ý.Eü©dx«a¨n¾`éæ©Æ#²ítŽï!i$Ò×þ!K++bcb1K˜7Ø a.Æàú¼’³ØÖÀuч;r3ƒ#±Î²1ýå|àÊÆ«_ñ4Š€Kì2Ò¸Ö$$”ÕÕÜúaòÙ²™nà—®¶ܶÄ]¢QJ‘6¬" ƒuÂþõ]@¡N>™Òá/ÿ«gÉ5™Zæx»‹/¿{ÉŠ·È¥Ù¸©*”? +]²×ÑlRg§ÀÍ9¦ðó}?DoŽÃfàµJ˜Ñ+´VGÇL=Dž/}Z11[Ø5ú›ôm\ï¸Ý0ÝÃÏĬÀ'³.˜b¢xñSó%ñÄ0ƒ4E5`é£yý*‹I5šëfù©º©îިߊ®k:åßœqþ]¥n„¡”äÒÝþ³NÕjV+´â¬¤ÊaE ÁáE7xöqŒ´ÓÐ÷¢1WÍÀ‘#õA¾|~šß™’*pz™™…”þS‡ür>w“o¡Ne‘{]]φIõH¢˜xwo7f ûi©Â, »ŽçùUB .(­PI .K‹…5esÀ–2ß²äö– &^¯:ÐÜÈ¿dÚth’è ú¬Ûƒo »l´&Çœø¼†%2ë¾ ãÃÆa¿ã¶D­t-ry}¹Äãܹ£i&²o{Ÿ¦'×ÞÑL?æ¢ê@®aüïZ©*NÈâ¶„Ö¼?÷MÇ'Êm(–f„mS* ˜};”ÿ ³<ýû“Ÿžëú6%͕Ȩ”uNf½4d´4]…PsÅôY†z\anƒÓlJ›¢ì ª4ðò,quÏ5ÔÉÐXz?ÆläãD %–âá~¹óO€¶KJQÇpÊÆuå3uÿB¿öðuGÀoÛÎ1çªÆ`ÌCïûMÜiV=\ø^±‡î ]ô\†çZk(r?‚&Í¡æaW§Ø'¦ø-’þ$-F“èYIì:=ÒÏýæ+ƒ)•:è ªä-¬XÁ«¶}tŒ-ݯN «ülüÙ(kŒ±d`±UxÖ…À«/ZÎy²H)r¢÷¢ZŸ |.Vc[ø‹B¿ÞsQNO€‡.(ÙkÏ«ˆ@[N2SˆT%~Úq.Œ@kYÜbÛè;¡kÅ­e<ÉíEf´VñÊ•”š× ÀLU²>W’" 2¡û}!£&Ï"¥ko9»ô~7ÕBD%E¨f-\iÙåÑ÷žU?úÝW*""Š‹ ÅÁ7ÀY^/6·ñ}©N#¸“Pžùíïø –Çd¶ÿûˆGâë}”Ž˜ñã…x˜€ØoÛ [ ÖK§$W¥Ïndàòs§-ÈRe%¬Ÿ~æêÞ+ó3;÷z&ŽÎß5b!Y3êíÙN•Ú¬‰ é˜&í»”tmSè^€Û­…é«#J"?mš…ø˜*ÏÚJ³»A,˜×^²ŸZagæÌ~ÐíåÈLØ•ù„ãì¦@ÐœÂæø?؉è)AãñÞì{·Ã€ª–;•…ûøÞ·ê‚ËY®Í¸AyXgp+˜fêƒóW|ÿÁ(YT„äHëÁl½0©ÉJœžª·fó>¸].ÀÆnw Øò’Â23ùT‚æJ¥ËÞ‰å)”ßx;ó1N9_®i³AÒ5Œ ?ë‘ï ºŒë53ZçÎ`86PÖcg8Wóù+úª¨ËóùàgMºø¹ 8eþi+Le*l÷zœÞ˜—XúöpõP*ˆ³ò}Ý \™oZ}2ÓÔTã)¯UŒóR¨}Ør¿öÄnï1ì;ŽÆòÑìÊÑÄ7«ruÿ&÷Šñ.€#ËhéaøÁºÐí™j0]‹ç"¿P}ßôˆS™ÛhŽœÒ§zOk3ïÄf[ŠÞÏÿj}Î}fA#›ZpÑ=ÁXpU„e–jV#莭àWÑF†FaõžR/(¯ÿ }ˆN÷±5z±i«xK2G#á}}X$"Äw½å0KˆÃ‚Õ+‡-çÆí] €QƒÕ…À«/ZÎy‰v3ëEg@&Í y‡¡1NÄåzk9­¨Î Läì® ­˜Ä/àýQ|tYÜ‘ ÍäVtÍâó÷ðå]¿¡±f.8)Šœ±”òi‘(J›å•û”'{*"Q¹˜?¢âqûa'±Xñ¸ºQöº§\m¸×ôsÍÌww\¼õÓã”Ôï~ØÛ¢\è27GìQç4r^dVe%¬Ÿ~æêØ«õÇkécy—u^YÚËùÂn ‘ŽšlDòvûP¬ï0TÉ‚*šPëS¤ö^T:‰-Ÿ¿ØSvÿ¸µ²£ÁÄ8“©ÖÎóžè¥€ýåASpDÊÆrTxÖ<Œ¹"K­ü˜µÍÉwd­ÑÏÒ\äÀõL„êñ׿_Äl‚baµ¡îùÑETuhx£Œhr`QAIlŸR!±ðËÌïß8RmçÍ•˜ìXçôÖ!ÿrñ°{1¤‰ ¨V×¶e›×Mõ¸ÌY[橵C*¿)] ?d},@G7<ò°:]¢`” öŸ9ú£®Ú¿ ,QŽr‰¯‰æSÝwòÐ×,ÈVìµï_=./ZB–h~ojýþ NÕæ†oÀäàEÇ—VÚñ7u×Á3!0øjsð“^øàâS¸Ø¼ŒùV˜E± g•'Q•²uaK™ùˆ÷^P…Bð‡#OsQŒKS®-GÝ%»Ž6.¬£C¾@Û½fÏ &¸0èAíC¿8.Aá™saÇœ~°/ôsšÐ3æ?ÊèÔ¿S@®ëÎ6ð­ ­žU*Ä c†GzžF¿$]Ö‹QË}úxãjë‡(»/ëáafÀ6¼gÊWF±¯Y âÌ[€§AµjŒèÙO;JªuàtÒÄxþf|ü¾_–®²C„ð”+É*&-YðSº*ˆ÷<Çrj” 6: uOwaf+”«ææ;꾸GT®9)˜;¦@ŒF–¹}k`µî¹•+/‹}fBümIÍÚwEŽö-³§ïkj/9UŸ5ÔÃçgcÿ€®MÁÙ‹ÈЙ4ì ŽÉê^1Â[³¶‚$-S[ Õäþ©þqkyÚ­Ìþ޽ÜIb¦ ¢hv×YÜ÷ygsŒÁãù…BÄqi¤—ªUçQؽÌï#­)2i5–Yhòàå› zLÎí÷YÁ±<ñÅš‹‰DN '‡3ùëËKörÄ%I 5~‚÷I×|»ú÷ò>'ªpR.Ã7fäÙÆ€EÕve¬w  “e‚®Sù¸›A‰†W¹ãp‹¯ýbúoTÉ?Æ"#Ó–½î’NÚ-@¾*ë~íòs°aQ®žz"¾MY/#H¯-üÄåxxs¨À° !ÂOx)sÌ–¥×áZ(‚r‰~YË€R@ý¤¿dvbeòNUÎ1ÙÅßÖÝ>¿ÚRé¡|´ÌÁ¹ª¦Ñ($ÕÄ…Åá]g^%x©Ín@åúdÙ ¿‘´òÆGDüüQ$}9}É”-ˆ—G®JÀˆ*³ï*7\ÄuvÕ´¾S÷Më_³¬çÙiqÛ CjqÃÙsò:Ò .²”B’àp*‘5ڵ내Ÿv¢vO€ 5r6¨½s¢I±`bîoŽÑˆÙù¬Æj=lL j¹&žý=džÈôz{ +-åÝÆZäÈSi;ý=õ,½Åtûî ôcu°?Ñ7Øs¶1>…Ï…Wš¥.×ÉÈ–ÐcÀîõêV¡«ðHA,æ(k¯Þùœ©ª~IMwWÖØÅÃç¶ :îׯ‡$šÐó ¬jwtÿUíéWlÖøÚëØM`$!ÏÙ’ä QÿZTÚ:Á ¸¾y¯³Û›>O«ŽˆÊ[·ÿùîI@þ,m󩂺sÛ°¸›Ú9æÒøÞƒ„VæŽû©`œÒ¹†tÑ:ùÍ Ÿ¼»FŸ‰ÌóG¿ ‚5>˜ñRŠwÐ ®ÛI'.`ÊOE--[Ù•€Ú3PüÊ. ¥è÷o|¼qp|{uº3²1ë7DXþYë¯%æJ0ÅùBçPƒÊÁízzê†í•óÒïq’ ÎF#Á ñ³<÷{ÌG(¬z`G»“Þf€UŽia™‚ÖÍÒmE8¤‰9ÐO)Ïycbš:iºÅ‹”ìT†êož OAiSÍ~a]ÌHcKÜø„E;·‹wThñgc q¼¡šŽ˜–ÁßOÙzS˜ôWœ.O ½ã3áÞW©˜æµÃß,àlr€d<#j¬Å‰oÄ‘n“Ÿ_ ò‰FÝ×<"“Î;P(<‚?¿1 ˜0)ùP”þPzàå‘V3¥rÈfïŸ]1Ä®>xºŽúþçƒI²åHûh{ƒútR«š!øù‡"g{R²ô¿w¨Sþ¸òCh¹F¬ã÷—¥úý|RŽÇgrÉ¿+±6öÁo#R!ÂÓ`ú· ]ΫþÅ&](x¾Ä#DØêºÉBs³ÏÞPL ήRë3EÖ øš…`È'Cb0Íá­/3œ ©S°¾TAù 2F %œn8w™È”}J:0B<©B)íØ+cTúBV.‹XÊì2sV:À‘¸½è/?MOôïvùp­?Í•ˆs¶0š“~;Î…óà¦ØoÆŸ¦À"©áq•Ë7)fÒú¥¤bk ½P $s1”Þk*Ú03žÝ›‹Ü]H±†4\ëHZmIR9–Ëó ®*0e-Õդƚö¯ŠÕž¸:ä_{î®1ÖhÚŽ°Þz|(öÔ£%à—Dâ×{µü÷Îý}›ž–€½¡ê]z¿$žALAÌ¢êeÊ:pK‘Nƒƒ;§ößÌWœq-« eæÕX=ô§cYéÜ2 -¦ü ÎlBÐ×ì‘’|Öá2M¯ìúÝ ‡§ÉZ†Aç?äñ* VV•³òfõ9T¸Î——á„o£ÞxωAÈ •C ÿIr}ÝÙ*‰˜Åa|ÍlÙñ5ˆ­>Ptº?\QÙ°iÊæ¼_xe3á”Ýo.Žjé³øjf\²œA¤9Å2t‚äÍËxÌ0Òé°oÉ£›<ö8¥ðL%kÎØƒ».ôƒLœ[lÐgWаÑÉ]`“{1[®¾ãëÁ+“€~楙(:W’õWsØöªf ››“6VÛ ö}¯çT#–Å€?§Í÷§ê°Å,çlFÅeëkéÞº±ƒŒà×ñ„MG™NÜ»$jÑ:tâÓɨ®Á‰óM…°ùJµZ‰"=ÕéÇY¢ÛØ*¯:݈8_±&MË£X¯Ia¥ ndøqÂ&¬Œ?î醨!òy'Ó endstream endobj 170 0 obj << /Type /FontDescriptor /FontName /BMVMOK+CMR10 /Flags 4 /FontBBox [-40 -250 1009 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/a/asterisk/b/bracketleft/bracketright/c/colon/comma/d/e/eight/equal/exclamdown/f/ff/ffi/fi/five/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/percent/period/plus/q/questiondown/quoteright/r/s/semicolon/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 169 0 R >> endobj 171 0 obj << /Length1 1750 /Length2 10267 /Length3 0 /Length 11372 /Filter /FlateDecode >> stream xÚ´Pè.ŒSÜÝBqîî÷â¤@pw—âîîîP¤@qŠ»;j¸·åÒÝ=»{ÎÿÏÜ;™Iò¼þ¼òÑQ«k±IZ:˜ƒå ®lœì@!€´Š&'äf¹Péè´!®và¿Ä¨tº`gˆTè_ÒÎ`ë³Läúl§â(¹Ù8¹œ|BœüB@ € ü¡ƒ³@䱨°” `T:iG/gˆµësšÿü0Z08ùYÿpHÚƒ! (@äj¶Îh²h9X@À®^ÿ‚QÄÆÕÕQˆƒÃÃÃdïÂîàl-ÆÄ ð€¸Ú4Á.`gw°%à7a€*Èü'3vT:€¶ ÄåO¹–ƒ•«È xØA,ÀP—g7¨%Øðœ ¥¨ PsCÿ4VþÓ€ðWoœìœ‡ûËûw ôg……ƒ½#êZ¬ v`€šœ2»«§++µüm²sqxö¹ƒ v ógƒ?*ä$5 g‚Ñs±p†8ºº°»@ì~Säøæ¹Ë²PKi{{0ÔÕõw}2g°ÅsÛ½8þœ¬-ÔÁêó°‚@-­~“°tsäÐBœÜÀŠ2™<‹Pÿ‘Yƒ]¼@ _v€=-l8~‡×örÿ¡äü-~fàçãèà°z&öƒXŸP}\@î`€«³ØÏçߊÿF¨œœKˆ…+Àl ¢þýY ¶ú?ßâ 0>ï'øûó÷?ãçõ²t€ÚyýcþÇ|9d¥tdõ Xþdü·NJÊÁàÃÆÍ`ãâå øy¿ÿŽò7ÿÿpÿCª‚üU🀊P+€àŸž{÷îmã_Ãøï ªÏ« 0þ³ùF@^ Åóçÿóþÿáòÿ·ö¿£üß6ÿ ’s³³ûCÍø‡þÿ£ÙCì¼þ2xÞd7×ç«Pqx¾ èÿšêÿ¼d°%ÄÍþµŠ® çë„ZÛýÝFˆ‹Äl©qµ°ùs…þ3…çðv(XÝÁòû­°qÿ£{¾7 Ûç÷ÄåyV¨ÀÏçôß)e¡–¿ïŽ‹—rvy¡Ÿ×‹‹—àÃù| –`Ï?6ÀÁup}v<ÓóX98£þž(?€Cú·èÄpÈýƒ8òÿ ^Ç«гŸÊßHðþAó €ÃâoÄÃóŒžoùë߬9,ÿŸ³‚ÿ¹Vÿ‚ÜëÁç¢ ÿ@ÎçPп!ïsUÐç.þKÿÛáŸZž+sø—š‡Àáø¼’ÿª†ó¹^çÁç|.ÿ$xNçêáð/õsF· ×s:¯Â?·Åìü§ù ÑÂÍÙùùqûãÌž'üüÇK {‚-PW—,„Cß4…vß5H’y°N‰ÎÓêe0±ù¬:÷¸=`"§2Õço;ßH¦Ž}ÀÞØ—e¼–X£úéóå] rDg²F×£ïÓDÍÙÃ.Ô•Âáé’/’ÍC(älÚG¾?|uƒláßÁö*Ñ8¹ `ªáÝy Ê{6U­O„/jÕó½BûQ5Ç«cT¾@Whž»HüÉ•â3î™'ÖÂõÍZb øk܉Yz©ã4%¢eŸŠÒmç‰ôEžÉ]ûN»cFïCUÍ;ç“ zºi!Fbx|Å·1Û IöåÔIH<¹gJÛžŠüïÌ]XÕ’ Ojvüͼšh‚‡ýùÍÞÇÈŒMúÌš6©ÍTÐÞ ØüfzÌÈâC둱D[F#›ã›ø­‚˜f²ïz÷¬sš<‚N6µ©Ç6~•NÕ“d}m@N Šr|Ü};\ÄüÌ®ÌnÄ®RdÜ/Æð¢K½Ú—“ï/O‹Ù€"ìUÖZRXèªv)xyj ʧó…q¼d&‚-ø¿„Ê_u2#ú~—C }òˆ¬EV-ɲn“ä=:uÉõ¼š¤{~IkÒúÅ ?pò-à$,ªB‚>&Lâe0¦~íÚ°_G(öÔ¸²áø‰’3HK·Ö/~D¨¬o« ti ´\ö ±GZäòø6‘ŸöNfÍ;ìœ6z ƒzBN&(lã?ýírI„[k–#̲·Nif‰H™Ò‰ùíu/YؾˆgKÐ¥‰ªŒ{q[Lv»ü`‹´ÛÓàô{I¡÷|ö#{®ÖÛd•+*¦ðu‘±ö˜ïî?ÕçmiD8iÔL]6KºGån­Ýö¿šï¼YgqE ¿{JN*<{ÄÈ·W¯fòdxاçâó1s´Z²ÁŠ"ºþ Aøi}N¡R=mÔ¥Š\s‰yNÙ(®›U1Gä9—­þnAæ)…ÞŸ‰u’οñA\#ƒž0›nÐ`p)ýW i”½Æ ž ßîŠ"?RHàA&nö%•>°ø|¼#ëžåó´å¦±ÔIþ†øH’u9È«íT²¬iÖä ½Ê )þZ0‹—ý’Êó^ ѳ]¨¿øhcúôµŸæ§ië‘CAÿú™×;oê*c†gñGqf+ªí;߄śYÆ"Ù+ùþá^ Ä.t¨m¶¿÷1øÛZôP±ÚØÀÖ¾R^L³d>SÞTFu„á RW ~…NÔ€èOD¯ÓXbÞkÇ”³Í|ÛŽ <ú`wg^B0CÛNve“^ꬫⓤ'óD1í.õ†5•&<±B  yµ°f¿.Ì7À¯âÔve±*«5³\ÖxjÇëìøaÚƒüÉÄmÓÉLâïàK¥_l¤éšãó›ìÙfçU^+ ×X` ªö¥0_b¬ÆÊ“÷••ì¬úf'- PFꔘ'Õ‰»â½VbQJÞ¯Çâ£/ ýšý˜ ‚æ…û™ÆëvºJrõ¦]û  æ:‚ø˜¾'Bàp!ß»q(WÞ!R°obᥠQí} &v žg„¯µÉÖ{YвUãÜ÷±vˆýSN,‡yêÓWÒÌøWë¸{pÎ/NƒªÕl¦•$G2³š»ÅLÊqÝó缘Éí];æë„,UiNÓƒ‹S”çÉŽ@šžÔa?,©{4Ñ`S²"³Z™Ï ‚z ˆ´ê†d,ñlWH“ÌitÏG«L\ÓxülxÁ‰[ ª‘΃ µŠ¥¬jíÈ| ;¥$»Ó8vEÍTáÙ¨¡OáªjŸ‰×hÚë*1‚»Â"[š:ñ~ÇÝ–§É䟻®­¹„ë}Ô¦œ€îùAKç&ŸÒ–èIû¬ÉsÆ,+m‰=ÑÒëXÞﮡ8>'@ͯ:u½¯ÎcÈYéƒÖNȨŒH‡k6fŠ8•¥ª§qi”š`[Ïú. œwP8 &ø0SúaJ¸8‰¯ø ”e^‚ŠS¯¬Ž9+ÈÅÞ¸0Œ q0Æ(æÉæ¯!#ÁŒ·òE Dd`ˆ„°6U:ßîr<óVÞ}l ¨ïì=ôP|OP6ÜæŒ–WíÕWu”ŒJãAÒq16¶N„¥ŒeSúsËAP³V7áˆZI{%´?Ãéy?’r1z`–ˆ¤Û—zN/+ —$ÞfMŒ¹t‡.½ž>’ÉÏßÄf6²J‹P_«â¾ü™â3¡os½Ë`ÌzŸ>õ 5 Ôr:Â0Ùç 4Êj¹—î°à@u[nö5Å s_d³« .²‘|£ Ž2ÂS%A±×µçªÖÖRFû³Áö=úÜÀ›Áöàdˆ¯û'YAs-¸N—!)dï„Ý¥¬ÑêÖ,.ë3¸’¥ø|Ø;ë“æÈÎTï.ÖõH91$_nCõ‹&Î9[a»x ‰A¯(úÕ¤ÙU%+wE‰¬yE¿é™xNN0"zµ >­åÉP6ô¯¹ aû©æ_-)ÆÉŒ‡¦$eDõVg•RõR%Ám!¾4öƒm“ÃïêK\•ÕÆãµ×„ˆ ”}pæG¾ QSZí%#vEkåÐëøè’-ÁÔ!­›>aTaî –·r¤gêY ar&¯ðæ{% 4“q w.!évî×—_­–¿¸ ÎÅf6‘ó#¥¢GW';ŠëdCúqêŸFj?àÿæ,%'é…œ;¹î0€*êÕÙ ;6²Ã뢛á¸+ƒàè|¼XЍÈ%ß#\Az䜞!Ì-+g~¬Ý¶@nh;@™7J÷ð‡a4\9±arp š¦¸œè‡Ø¡üà4Z©7ÌCýõõ¬oô>¥j®Õ¹ñ·8a|íº{co‡ÅO½qF"èœú…4‚r‚mæ6(@ÝÄKKÚlPq¯£“ùCm\Øßo½«çÎR,4z”ôÅ8æDÚ=•uç{dDX;î¥?£óYpš_jÐy‹ÒVèÀÀº‰´(ñiʧߌ·lLD¸Ûo4Ñ]ßtå7Ïá׈ªKû…þØ0åÚY°ýyGÿeíDÜ(Ï¿œ„Xª˜vÓÔ°êçèL¼A‰~¤"Ù>ÍÎSkíùrÅ%ËÍÇ.%@ ¹…®åß$DÜ2ùÛ¦fM¬ª0H¾-_ד&ïÜV1ñ{0·T–rë`ôÈ¢,Ê+1c.¼×ŠúâK{;ô–BTc_I¨JdÄ|Áϸµª<ؼáÚj(ùYr.äŸE §#/ÂóŒžä)åûMàcû·ÐÀƈÑ"^[ÿE¡_=¹2Ž/«…ßœ7H"<Ô¢L™iiµ½FÀldŸóPÝ!ú)ݘh{è…Wí¿å¦@sÂ(€9­Êß pÇÚæP$¢D³>NªX‘ú¬$=ÊqS $džhy(@ýdß¾\y]€¬JB+r$¹ÅeoâØ5±ó¥0a·ƒÒ-¦u|Õ.*XÞéPж8ÏŠ®FD%Ô‘A~¶|â5›H-fÝÙåX83qæ'_9ÃÓÈQ]–7€ ‡Ôlßæ$Z§‡;Šú„Ï›bf&Å?¶¸éõÌ—zûfkO´ìë*ªì×[1o‡ò} @ž°øT·f"’ž£É;éÎæQÇ|¨‚µy™Æ¬[T†‰?( V’² + ÉýB¡Y‡ ñ9P iá±Ac ƒ- ³òïFx϶·ü9¬g_âŽÑïk6ñ¨#Bí$m4•ôœPõÚÆ`³SÇ…ÈB3ïŸ_ Ù9‘žèQ§,YI¨‰D¾‹¸.' ªf­öOlÛ)*Plºäˆžº€±&ö&ˆnJ8•¦ª*™c—z+• 3Ûc]˜-¬¯%Vüím­Ü+¤6ÇGðBÃ10µ $âMpB&†áËC üŽíÕ\m©ÁÊÕÍüM%Ž}í„–Ÿ˜4ûŸlÄ× íÃÅi¾z§Y<ŽÄ¼›/²Û7^(J)`1|…m>‹#ÒÕ«"ˆ¡Öç[géw]rø¹ÜyMæf}c\÷äŒúÖì;pY͈DºuCŒ:º"úÔà2R,áiTB$}¡SÀD¿Ýg¯EG†°_0Ñ‹œe„ ÙÛ?3qÁï(]SP¬\Ž[ª$õx}ƒs­é_lÿÄ'W‹â®¾Ç„'_ÿcÿP˜«Éʘ.^Í5( þÝá>±U·¤-ò^!®ØØR~Øn+•_›D¤ét{Óþbå¥>ý§ &Dšû©åÀ†¬˜¥G–B"Ú±®#ˆif¥T®·;©¹±ôɈ±Ëq`ÐlLgh "sÈø}kÝ¡ ð]wømá²Ñäè/$‡aªõ˸KûN]ÔJÖRmÃîK¤âÕ%Pè)ÃsÜÚûÕö)Q–öWÓÖ9V†À²êLk—3åyÎÌó8»l1m³ÁRQd—€ü˜pR§µ‚Ì"T™Ú„¯Ó~”ebáÖî÷ )üü@'íîgŽKß9͇v6³²zôJa¾#•ß¡ükÿ‹ÀÛ×·*ÃF» F‡îÕ'¤… kÒL;Y¬¯ÉíýK¡,1ŽW–kÍúvøñ2únTøEyòhï(͹TàÀµ‡QÌàåå»mˆæº¾§À;ÉãtY¨nª‘&A!RWºìü.VPöøÌ!do¦h rŸª'—;×·­^kûκ3½wôT¢µ>‰6$$Ã_BÉ`7ICæl³ï³ ƾ/IJÇ.ÞQI/É宨¶p˜]ï7¹+nÞÁµ£Ájàná^æÂÊ4.|¾|´½sI+²kË2 KÌÅVª70ú¿¡S¯ ïÃBm•׳KUš‡ËÌ8h=»/»AØL¬¤ï¶q»†¡ï¡”„ §ÅŽ Ž] {ˆ´0RG)Ïør }h¯êþçukøîWı¾~üÔ9lï0ò˜üt–—Édøk!Uº{ Ñ™I×k$­±œòkù· žÑ{¯±ºO´›&çªÇ`]صbªû¥›› œ„Pƒá=ÁHÆšó>ÞÒðâ^jZKìG,;Ú4f?Ì^®‚P†msl¹$³ÅéÉCLš6I4½gE­p¢NÒ˜î¬ßHn&3xF˜K©[ŠÔï—šÌűÎSc º/Ú¯ )Q'62‹Ô5rh5Á~€U™ôÓ§0\×äÞ}äbQ ±üòrÏFŽEö:Éð”«pjÞ@U5X†ŒbÿÃ'*b‚˜b_*ܳWŸÄxçÞ²ó2¾Ú} ˜cAaáéòZ”¨ ØBÌ›‘Zünøšª£;奆‚ÍìNLjTJâùd"ui9›o嵦®Š3Š%-ΛØÛj:0i~gmì7F:v3ö› ×¾dT3âóрȼ㛖x(ç¡ ê=»ÖÌÝ ¤ÞÛào©5ÀýZ 'öøà¡æÆ¬:r‡i ãi›ù¤[¼Ð/X£ðÁI k¬d‡û¼hêâb9`1ûª(„=H+ ‰e”H‚«':ÑhpÖ¸/×\o»ºHu«Ôq•4ð˜dßm¿ íšG••‰EoqD>–v:o¸¤À9\øª Z|“xŒ¿7‘«×JO(àC™h/­³Ò.Ü®áú‹l?×°.Ú`» çÍpV‹ïkx ªÑ#iðôÊw"‡ƒÃ™0×`Íœ×ó_vËŸš5÷t)äCÎÉL‰£H€NûßIÍË®‰ÐÜÉâf?+¼%*$Ò™õ°: t†•ÙPc>ÂÅìYNr»ËðݦwÞ6¿owÓ¶pl?ýØbKVœþ«¬dÿÝ|L–Í_¡iëðÚ#iíbA4óä‹ER¨}AÙ—dÐ^ÿ€$â´¥o¡föZ’£êWq¹B5éUÁ/ÐÐD n¿Â-ÿ”ÐøæiQv¬±š=÷¹+úeIüÄ:zœ¤úiÒðuqà„Dè´|ç‡]Êä7 Ïœ5ej%ö½ðÕnJî¿L¿ùÊ·{7l„Kü­ö;’Îlßë#ØëF%Ö÷ xK+-~*wÉ®d˜éØh¹l‘zAN -3•ŸÏ`&WCKÖ„"s)TÝέwp/g ÇvJ)e!§lÔYxÆÆü¨yp¯®/uŠHºýnV:ÑÕ‰ÙçKÚKHa·T‚B@"¨'ÃöbT[z^MàôcL>Î-]035ç Œ›ùÓjÜ‹GÉÁOnT1Â%‚¿Fr:_™ö¯[G÷wç‰r9¶÷Ñr¿mÐ mVŠž¡ m€‰Sœz×’U9ª§ó´ÆL|fßü:(åÖ`ébæxò#Þ y¯ Rw”UÎQê•6¬Ô¶êòò+b×bx‰áÝë¯.OmžvM(¹¶×Ð!-¼ìŠÊcÃèö÷`ûšð­ÿÁ àO×ï>h$1³$¨eO1ŽÄ6»·ˆ©YÝ#Ê{e4qSu±|Q×ò>5æQ}E¨ í×ÓP˜N”Ÿíc/Î~%†åÍu¶>Ïlmó¼ËU·ŠewL|#œB+žØ²ÓÅÈiâÓ¨ñÓDÓ«è×þþþŒ¶,_bë¯9ûþÙÊŸêü÷´à«?W;u(y“DС}Ä ®ƒ!z¼Å`1z²v‚Xb¤ 7Ô¨7ghKBƒ¬#lUp8ÈäyûÑbÔq¹ª¾ÂÿÒ1bõÓy„–ZRƒ¿*Ž28^.ç®ùÀ}¼´û(1>AGmybiL¿òbe*‡JÞõ´ò1^°MÚ‹S?CÜ#%;Dþ{çøÍ£ó½f’äœ;óëýjÍ„ó6gQ½_>_s6ˆ‹‘x •Ü2j1Õ=hüQ­‹×”rüuê¢l­òW]x×F×[z0Êw†F1 —×!´ yžïvÕ)®UFB›x|wj„*Ÿ>áÈ2P™)šöšº+óbÈŒÞ e¾ö= æ ¸M°Êü˜“rÔ¡dEêÐÖmx¾Tr…Ú³·Ð®£W…ÂSÅÙ+›m=¦êȃ£Ãbœ‘"’iIì-ᯋ©ôèvRãÿ¸ÇçYJûÓ3ˆÿ›AÛ㔺åÓ%¬li…Büä@ÀzÄÆ’„}7+Z3 é)j];CÛŠ&*°Áô!r_`Å#_#µå¢;Ûdmƒ†t£|äÄ@Dè60|„®ÀœÆœÚºEQ£-Q^ñPONÂÈ—!ºå‰øÙÕL“Àv§;yšzüÙ±o3C‰äó8¿2b`³Ñ™Z†ÊÖ‡Z.>e:ËC/Øõ ÒÝ­‚Ú6rÿ±PzâKÚ=?Fùp$˜m‘©îlZ¥9ÒÆWvȬ^ 'FâÊùÕŽ²bŒî< œïÕÝ£Aù…Wuï?'ïO7}K“2ý‰Ÿ(r׌žÄµ‡þ³hUA}ÓpÁojcy~Ï÷[bžQûGÉGU߬8ÙmTæ¾âê’!Óm鑘¸r÷”ùfE²ŸŠê•h¯œ€~ŠbÌ‹Š°jÍÓâ˜5•Ê-|ïûYÞe$‹sóŒiýàÛ‚½¾Êö ’Nõ9Ún©öß9ÎWUa6–ýäé½Ôgˆï£,¿YkU`FIsÜ2¼XFÍÂ[ipÑòþWƒnâWVƒÛ9ٸŦnª ¤ð%¥ŸÔ?}æ^ˬåa/u0š©+ú‘v“3&T•æÀEîÃQg‹µÖºù¥/z62Ø:4žå_à1¤ÙW´iuà4B8:aVì¸aS;Q=2>áÄü Aq¿Ç …¼ð«{Õá´Ãš³°D§+[eJ·Èb²;ì.³çDØÕ+¥GnŒSüñŒAßu RêĸïŸmY{û!ú*zt[(£Q1&G")±hü)ò©„›yf¾ï†p‚¿à5®ú£ÅX\¥ÎCÿÑ·¢BN”²%E+ê·® ê*õi§åÇZ7D5\4DT‹¯Î¦PüüÎ]¢QrïnÖÅÊ©vÞß„âÒIòT À ´œY@ϳe}‚˜'må(L¢lØ›·Bû;)r„Û2d*/=¸ZÓi¤ΦÑ­¸ÁæKÁ¬ |7$2*§ýa­‹ƒR0Æ’ˆÎ}%²ýóC‡`ûÕ»XCšûh¯€”Š˜W³Âóƒf³gtTÁ aÑúäM)”c«àª·e¶zrâé¯‡Š¥ì»´;õúBÒòqµ„Ê›¯;%¼ßÜÔJá/Xe \e ¢Žg7æNMјQ¼ï‡ëÈ}޾ ðÔK“2_ׄkè}‚€¥ßuj}ÙòÝU1Œ‹nxÖefÝüžÇÞ{º(™Y8Á›sV‹‹ÖõGãg”Œ‹$j¡Í~‚ÍDŽO_êDø¨äX©ª÷déû­TŽ“#~ÒãçËsŽ´ü}$¯zö5‚å:åÓý¡ù™ƒ#µ¡¯o4¯nR»6¢Í䈳gà˜Wf5ïü²HF¤­ë°YƒÏµÝ–Û´E‰6Â?`¿ìb9±ÜzèS¢v1lœt”2­Äóg Ù^ê_ÝLJ­AƒÓN)ѪüÈ­'Uº¤¥J 1ÓnÒ“4$Â$Xeد—ÔÁ±ØMi ¸r‘ß³LY¿l'°ÍÓfQ~s—¡¿KýÚÕ ¬l©a˜,Eµ–E{gCáwJŸNAÞ(‰ù}’ÍÈcØPb€Ž”´Tð$ $›ÕሦÄh=—|Aœ#}"A8HÑ":Ù/¼ɈÀßÌ¥Ì~±ÜøÅ žYÒÿƒWê €Ü Ö´8›?Žszºbmâ¸ÑÛŸ©ð1Ì×»J8Ú¬&§Ýr´8ÍÛEÀŠjõxßÒo8É8à+êãÞÒ­7+f'ؤ£KÍnÍÑ£Hˆf{ƒ|gÚüxßkD•Þ<ÏÉE•F‹ ŽQ.}÷ÊgóËÃJKM Kv‘Ýõ×j…÷VË{«°’Šù¼°ã‰È8\m˹ŠLýÞrWø ?–ØT÷°¬&´²ïgù{Š~.ÉÑó¼Wt‚Õçœo3ê<žÞäðEø¡yø+Ž qã({ “ÈEj°DZ‹L4*•°Ó¦žW®?ìo ÛÒûÑq齩ž<”EéWti²ÇO·óÌå¡gf¹YË…UcÚ²tZØFF ”¼ ªáÜÔ›~óðBLÑÏK)“ë#”¨V@þz÷Ü ¡ãÚ¤ˆ²øS!ɼðDóiËJ”¾ÚòJлžÜ±‹‰Z5BæÙ¢„ó8iŠ%q“u[B}ËPi~À|R+ö`„áklLÅÌìË3#ˆÐ¸1’•ô«¢¿ˆ#\ÌĆPYvðýgbÈ …¯N)óÄ©U>ÁhH€Á›Pø5³u±[¬‹9oˆÒ:p”âEÚÔ…F½2'Õ«ŽpT+WMVI“ƒÈzºT­_@`ò†n±» UÿΞˆ-?Üž´0€gTÀ]~0qÆÒç튃`Óî.0ú± ¬-ÒdncÙgjož±TÎIWcÏP –ž%¹>dj«¶_…šfމŽOf í´hâQÌ òqFyýuã8_Å|©ÖøÞwK=÷ª„ÄQ¼!Ð:!+*÷”ñ^OJ®ßÝŠÚN8õ‹’7Úb©ÁA:«^Ag!éwC¸LŸ„§ïxë%H´tGÆ3‘’hB2ÍàŽÚ¥¹]QMñ:Y ÿI¯d?ÜàŸ£]@äJ2…–hzQ¦7[_ÔÙ2Uçõͯwz”ÞvF|úhô¿þ9}½#0%‡Õò5Y8S•íÐÂ&HÛÓð5Çõ,L³Ù7c„Ö1V™<,†Ï{v Žäñíoâx/Š«_{Áˆv´`?ÉŠãÏš•™šWZ«„IPÈ¡V s¦MÐ:гÚPc Ì©Ê «@‚±Mšá>IRlÿ£Z°ÅE–ÞGü8ò"!œ'Œqä(¶“ÿŽÌÕš2æÅtš/åe#›¤­ú‹¸q¦Ý¯(µçf¬«”»î¬DªÀDñò]õåùQefb!aãפNWßzBýº v†Ù?tTIûg¹ôN¾Û{I§™¹|œÚdäöЩ/Ç7¿º»­¤=Äh?Aؽ~`>Å|zàR’ž” ÜÕ‰oò¯Nß.™m»Â)£ÏÜs<ØÐ¦¢Î•$ÌÃá5a Þ¡0¾špÙãØ-{Iè$b)œÈ³ê5Ìé±!Á¡AÐÇOx‡J¦½wWꊊâ“Àõ“±ðg GXd}«Á±¨¢–(TbS.‰ï%Ûz +O°$)C÷xèsƇ«ÅUîC]ÒÚñCôv½g-'°^¦ä"­TŸ3:eKFzÎï ÚºSÙòšŠõ”ç5`¼EáK;Œs€fš˜q-þƒ5å£#Ò-3¶*Nà1ÁB€æøQþ…÷° UW½2BnvX ¯«JôKBΆªÁ„,Ù…Äü¼†H8àgÿ2ŒBwΩ½%(¹ø\æZÞ´šó­Ëï*ü¾ûÆjW5:…˜hSL¹¤-¼‹BƒßÁ•3:+$se·j!ǰG3\ƒCŽÆL„v8¶N¹Ö¶4.o²R’9¶ñK‡zß't©œàû=²_¾´:GQ3Þ£%L¥ídÕǂ彀wYùÙÎtœ;¶äåâ¢Ôm•BîÍü–L•å"1 &S–ç¦J¤–²äžœ1 *Ây¯•빃žL¾ç(aóՀʤ·m6hfäòfÜ/R Ÿz½¶ÎЄïóA*‰sæiÄ5/?h fH/W†©yx¯Îoת© f>øé¦€ÌJ~6¢TŒPÛ=xwXJž|¡KöáÞÓ=>JOEJ*»FzY-tÙVòv¦ólƒm[ÚÔ¥³¼±ÁQP4¥…°nLÒ¦ÍÈæyާ—ĦGmM¾øЋy“§=„v´[%TJ¨G0ÿmFë*ÓË”†üSÊHئl0§—”jwì ñùgê™jl#  Š~È8°)ßUì¾Ù¤ýÔ&·õxPo•nJ›yU -o$\Ê×´/Ða‰j‚‘á=¬%XcÈ­Ã_zÛÁp;î(Ì_‚â†*awŒ>G#Žó"Z3‡yí{!¬ ¹^WúéšÆ›4=ÜÇn”‡B¬ŸŒ4šKäK_ó¢¦^÷7Ï·Û%IÏ̔έÌèNE¦…¾mÁ‰›Ø„$8çÄ®bH…-‹šì¥Fuh3aÏפ‡~ί¿Žb§¥cì+ã.Ä>äâá1UÖMæ75DŠÑJÂä<õß ˆ8ý :Môܽœ¡‘Šýô¡&¸úvx÷ÚíÐ%Þ#6þÈGã ½çÙâ„ö%%+(¾ ÷GÑãÛÁÈØ¾‘a}*GŽæ§p–N³!‡i9W&'ýf7Éœ›ðøzìf³fýìaâ„Á'1¤Â­=E––d¾D–r ïÿN ßø endstream endobj 172 0 obj << /Type /FontDescriptor /FontName /EBUEXZ+CMR12 /Flags 4 /FontBBox [-34 -251 988 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/C/F/G/K/M/a/b/c/comma/d/e/f/g/i/n/nine/o/one/period/r/s/two/u/y/zero) /FontFile 171 0 R >> endobj 173 0 obj << /Length1 1673 /Length2 9406 /Length3 0 /Length 10478 /Filter /FlateDecode >> stream xÚ·P”ï6 Ò t,ÝÝÝ-Ý ,±KwwŠ 4HK‡twHw‡J# /úëÿ÷ͼïìÌîs>÷¹Î=ÏR“«j0‹[BÌ2°+3; ›@RIÀÆÆÉÂÆÆLM­ rµþ)F¦Ö:»€ `H:Í\ŸeRf®ÏvJ0@ÁÍÀÎ `ç`ç`cp°±ñÿeqH™¹ƒ,J,è‚L- qôrYÛ¸>§ùë@gA`çççeúíw:ƒ,ÌÀ%3W ÃsF 3{€ÄtõúO:!WWGVV3ˆ³µ=ÀäjPºÝ–€_ ”Í€tÆ‚L д¹ü!×€X¹z˜9Ï{ìòìá¶:ž“4ä_Tà?Œ_ÿaÀøólì,ì‡ûÓûW ø·³™…ÄÁÑ ì[¬@ö@€ŠÌkWOW&€Øò—¡™½ äÙßÌÝ dofþlð»r3€Œ¸Àì¹Á?Ûs±p9ºº°¸€ìµÈú+Ìó)Kƒ-%!@°« ò¯ú¤@Î@‹çc÷býc²v`ˆØçO`[ZýjÂÒÍ‘U rrÊKýiò,BþGf tp³±±ñòs€N §… ë¯ðš^ŽÀßJö_âçü|!Ž«ç&€~ +à󲋙;àêìôóù·â¿™` ²p˜­A`ä¢?‹Vàçá;ƒ<lÏÜc°ýúüýdôL/KØÞëóßóe—”‘”Ôaü£ã¿uO€3''€™ƒ› ÀÏÅ àåâøý7ÊßýÿÕûo©ªèÏÚØþ (¶‚øÿháùìþjÃýOVÐý¹1ô€ÿfP†¯+ä_ð9™ó¿às6—A«ë¿às^·ÕýÊë7üϹ[¸9;?ßG¿7ãy(áß—è ´@^š‡X†ÚÖ†¶ÝV‹y0ïMÏPïé¤Ñ3û,9·»Ý£!$ÓW½Þp¾OîÁXÝ‘¦»[&{ô9üTÑòN­õ‡ïƒI‚úÔ^+òâgÜÉÂCñº~$bfM±}ßG'_í ;˜OÐ Ô¹Nn|hªùØ·}²žuýe+cáó{jûU<Š(eÓÌqZ±†AųÔyæYsøð®Ì$ˆ Xgžè³W×3X9“Od ŒÈ~GqœE>ú›oîæ¼×*49\º¨ôñI`®°Æ¦h|$¾¦(à-ø”|ˆÁhfåÈTÈ2:ŠB^T §3Þ ìõ±PìF:ºÞŒ¦ñ†·îßúÁ#žyË´IÖ#Æìë„éÉzv ·8¨C’†1Y,^`è_wúÞι+Lgà‚ÌQÇØ:Ö?E¿y圊ƒL' ­Ÿ]öÖÉÍSc±°»ãÌ:_º?ʹ—¯ABSí`CuF4Yv9?nE5·}-³{?UÄ4Æñ{[+Vœ šC°Ðm켌¦ÒöIí¢%¹[”» S^ú²íIç±äšÕº[©7~ÖvNüYrXxG¨¸ W>•¬â>‘·"·áêaÇw8)=4;:sW\A_¯<·m¦Û6¸"Hä=RQG…²¥øæÏô8µñ¾ºg N}|”'ey{€|^‹Ôª5R’émdzØ8lÑéˆ 9gÒ¬›#3D4]gÑ´‚'â¹Ç¤³¼'–W燢/›(øÉJÜ¥ûî&°ž1ÇÚlbYý„âЙƒl`}ñÌV:aE‰8v¿g•4ˆÄEÚúèûtýÉ—Ì‘(U—/‚0Ö5UmïN–=¥5âÓ“.»üò©¬ßŠY}R/¢en›}À|bÒëyÏ©‚¢n3îž ’ßö«ÊÕúÈŠ“ÿ¢ívßú i»ê Äe2¦Ù?è{´°w©Y%ÌÚœýE‚áÊcÑ»ŸhÙ¡›‘è;ta÷%f‘aT~¬Á,±f„ Œt£q# üÑ7íõÂH\ȹç‹ ³R9Ôâ« \åî³+iK«Óˆ˜è|ü¬9©uDlŒIf/ãdµœ¤bt²@·²hÒ›/Ú¿f!û t¯¾º’ñ6‘÷ÈY´ û±¿Pù@-”¯S%Ón._=yÙOtǃ93áâA>™$‡¥ÂÀ¯42Mñ¢&Ï];öêcÿ–½Uq ØÈÏr*>Jb¹Žô³œÃ™4-g+˜ëêF,®ªá÷j7, 4߸ºˇ/ÕŒz²ÂD±Úd‰SÑ ®@Jð½ÑŽq\_$žˆ]þ­:_áËÂ<ˆIüàš›·÷)9Âb;Úv¶@N@{ðØÑ[SbLŽ‚ªRMœ™çb¾®rap„ÓÄŸ]p캵IJ³y­8 •¤NÑ&¥É žì‚ÑËj˜õ'%åØÅˆdTDPP.4ijšN¦ÙRF——øÕç±_n›,tÇ$ÌÉŠ·_Ÿ ¡' ·&—xëèiö¬„잸’÷°bD``šz\äG×µñâ.°à¤.´É8&ZçµeRñœ‰hºZMÓt‹l^îPìUSKö£½Ð•×*‚ŠwôÇ+A LœOî.}˜n´^;®N)¹'ý—­ÌéDDX¶9áÖÃ1ÏÆV,ãm£»y…fVŒ¾ d" ‹-‘¯&9©ê‘±|y£NÂ=¿,WñÕÐ÷í1öáæ€¢w0p! Dç=›â¨T¸fz9JÝr¨ìçÑ‹U͹ÓÔ]»[xÞ…ÞYæ¼?»`~6¨XeJÐ×ÀhMIZIó±Ô¡Êë°ù¬oÊÎ~8 KúŠÔ€-Qs=&­NàHiÓº‰vй­h²qÕ©ty½ä«%½ž^>Ã0~ÌпtÖ=­êéБ]íLzðj+†o’UwD“ào»z¨«ÎK[]Ž í˜@Kˆñèà{}w'ð=™¦`‰Á×öÒ¹qùÅ"l5öóê°ëÁæ­ÚW0£³ õ­Ó†Ÿþ£c»0±üO”´Dð†ÅM¥ÙhË(Ž ÜÜåÕðÖÞ0¼oƒ¬eå*#'%é‚Þ,ÍüX®caΓÚ$@'@âk•RX_Ò7_¬ õÄS¡i= îרÞÄxX?@õBh&®hË8¬F œ„’ÝßßÂÇgر\ŸþØ“ú@ÇV‚¿Æ%¦+8Åiñ½õi¯v´~ÑŽ¢çÖZf>·ÕÛû¹ù)Ù¦€!aJJ½s›óGî•>í77Ø8µ]Ìþƒð'E|¥º÷–ÈæcéíÝü5ÐÍnï¢\4õlä 6HÂŒ,×z„>¾äÂÁ®ü|Uv#ü³àÓu¶Û'Ý auÈŬi1—õ¬Úws„E¦Tج"Þæ¼KÙ´¶_ä à™¢¨@{¯\?¦vz:X–gÆ8 éÅt* h•µÊw¨G¢/–ÃÙ„¥éËèUS— ¬…íëæ5Ö .î=ÚÞë%â&Ú«éÌz1<é™P 왯aüMÏ_+ü0l‡øKÚ*Ú¯ù§·¼Ÿ~»é€ç8"3§ziª<ðv©Z¶"“ñˆ=P¼íñ¥¿ø€{kÿ¤Rj3 ßȘK¡CVpf{QŒ IÒZ^"›³Ø=*l¸Ó%iggºm÷lÜC×}’ÌÈiV:‰Ð}½CÑ%Rš¶–Ã*jDPòà6Ñ› v*Lj'»³€à­w†Ùš·¨OµN𿦖SLøá¿%ÃL ö,ìÒ ]âðÊ9Å9[ ‰é/sì¹¶ÙÂ~W+Ö˜?>®?§ž8U¨‘œí]û.ï÷º+>Jà£òÞF1cãë».º×}$'I•1©Ø9,Åx¼l9ö©¶Ú“‘-Óµ@ùLž#Ýʼ½+ÚižßÐך“Þ†Í 9¯)£×ØBì`Å#[Òɦ¢Ã“Bwêl~k¼™3yÄU[†Ÿê=€Å}ÉœSš¹[Z[²Ø°3£Cò_ÈTœ®ôB’—*WMÃPnѦ2ì ß§óñ˜p( ëàÑ(Pù~^ en_*;z¯^qåÃD:‘Û:Â1î6u²À¶Õdwª"/²õ\Fª ÷Êæ.3ø¤åpı[rãËz—` ›þ-]Þ]í]:s¾qÖ.ú¶w†֪ï +’šÎ½è0ð^FŠtXwR~·Cõ°ìÿ2Ú~b¥Òû5vÚ„À—b‹öSiø½Tá~/d_(ý'ÆÍc» ’Àü Êl7¿4XþU~›­R~µ4¬ìç;ü"l1¡Þ$/½#‚fφi~é¸/'¦–ûÃz#˜†C|u0Æ>ýspÀ1É– Ÿ}#`/Â/ÑI†äl; /V{…µûÄ?>SJ€ï¾¢¡*ˆ|¼Š—z÷Å‹e¯ûƬ¡vÁ!|ó&{12LPpþõiŽN‚c$–›#²å•Xņ~•x¶o Àå’wMÁ=ÝÊYjDv›åáº9ˆö-×z^¢Y›%£KJe8îÌ;ËÆUòÀ¢if"˜ ¦TQÑzí—qöå²Yã’‚T]y%ðe®pGt jÓEXȉÓÜáëšå]V“wÍ—cRüò­°ˆ3ù7¬’ 7¶X*¢Tä™솪.X'¦ŸkÙö(^5¸RŸÝ#[øÈ©Z»ò­8¦cö^-ë›{ ’³AyÉꬢ«7Ç¡ÌrcÄÜ„˜\ÏÍwls$‹Œ=†œ-cñÔeeî^•¼Àô f »jÍ2¢©#HIÒõ¯˜˜îÒ³\%P–Kj DrGMs¡›¬Ô¡ÎÃb$NêÞë1èïå‹‘z˼Öb—mÌyr=9T*³ú¨,z08Lk!JbÓh0çŽzgá¡)8îm;®Ù²fÅ%; yÕôÓ ji;K³«ÔªÓo "ƒÄ%a´p´$¿©rlmjrlX­HŸ5ÍL ]ª<†RÜÙj–ÀºH¬Ãó+õÍìgœY"Í÷ñ™ãî¿êV—xñßQ¾‡žúêOT[!­4©-Ε¬ôæ0WÑAÐJ¬®¿Á„déÇ¥¸QÎóº<¸*ö0 ¥Þ ÐËÓ À‘þHÉ[ŠÆð¬M¦Nî÷°'ùR‹þªt+©8"Éöce#ü% ¢x½Hß\*²ú«ü ÿ!þöøpIV¥®š–«/ü¡Ëh_áàäpRq†¦„eU´¸l-+Ûê,ù†¥ˆ÷ U·@ÝMåœÛ©ª©CÊy¼©7/8¬ËËú+Õk¹kìR[Èú®bOCEçff·^ø@¦·H·" |Zuˆ AZL ûìvð•ÜÑD4»ÛÂ]7 iÜß6 ´žKV4(ô!r› dÔè\Ë7ýRD¢2ãXC:Äc#XxŽÊöi]ë„–Íëgà®\ož}¼­iž .š®§f#òXëýC7,ô“¾èw„NY˜nÚã½T,ûÌ¥Ù½!nª  îƒä×o©|»ï8l§x o\µÇçÍ=¸ë¿“Vo‰¶Þ‚–Çÿ†nûíBwŠcû#«£]ýfíˆÎÒ£†ATÍ"¼\ª9ÐŒöb»û¥j$Û¥òû’)xIцO›Êþ/ƒè¤Ib,e„„”¶¾^ù¶¡ðjºX™ë”D[Zì?õE¯D¡ª6³$ÌÞT­ÉJæöáÚ$ñª}b²gSÒŽx@ŽR%ÅÃÄ [hxL»Çq9!_c…~¹Ý¢öúb ÎrAê [´ÂPn5ÑsåŽb\'¤þÔËT¨¬C:À¹¯¶8E,Ò¡<ôåå\ôkõMÖÅȶ ,k §¡÷ó(޽™ñžÛžåqè¶Ç%;4Ls6 ¤>¯¦z#ý[ÌkL¦MŒÆÒ—èãv!âJ=H5‹Aý°jv˜a/ø_§?ì‹¿Éi½Vp¿b\÷ŸH’›>œÓtX=©°B>¸G] ÛFÕׂ>¿eÍ8,ŸT6¾0á ‰ ’̬š@óÚ‹%РD›jB ÔЈ-ðÊÙNjÇõ“æÑÕ~¿Ï·—‰ cìѶxgæÍhNêÎÔË|Á*qm*X™Ùtkê°Uâ.Ld显{=X,RªT¾mÉ• Ò=ŽyëG‰¬dŽ­*~r#ƒÏÇr»KÃn!N™‰G½*! _sùs`{Éïq!B`N–|_/å”´}ÿ T€]6«v¤`Ž1‘ñÑX3s¦áe¯­Õ÷ÏÀu=ª«âvZö“×”#¨ü¦Lû$ñ²Zæë™¨ñì¬é‘/$Ážy?ðä:™à*{ð£é ér Ôt‚äK:ÅêYëÌ~pÌJ%:š>EN»ÜsWèMU]Ϲù´ÎÖ%.pÃkôØù{ÑsæîÝÐ}}Ê×kïî'm,/ÅÖË®ùo®õÁ³(š’˜4‘¹©¥±áÅü¡ ‡>é;1âmð:uû©FÜ1ÎÒîK{‘”÷tÄË6çyïû4»ì51t[øÓÛI¢üSï¹$"φJÓ¼ì ¬†–‚ý³«œÈÕ^º:ñ«¶v¹£\)¬yT%˜Ò¦ƒYJO@f½e3âÑQ‡³¨ŒYÁsy`>5è|^ªpÝã÷çèTŽ»p(6-nï(O@×Z³¼‰!ùöJ³ëFKro©>Ù8IUï$¡ dK"à3·ÚxŒyÆ â¤ðï¤Èš ñR?2£êµZ jÕ/dJÆTŽO?𾸷±†ÞN{8«Õ@õ 2jMÚÇ2åj¿${-FTNÉ2z„hvÐ’ÿÞ‚¼º6l:Õ“/7+Ôñâ!Q‰âøFCÛ ÿ»C’NuÚ{1ʩńŸúaÞª8âeˆ°á9{Fõþ‘f†“¨ ÌÅ“Oíá ³N.#e³4:üƒÁiœ1òÜxä4õC¸ºQ±¹œØ±‹Âdç¸dßu'Y,WÑÊÏwnywÒ³nWòS¤‹ó˯ÈÃ"Ÿ†O$–£„·âކö‚¸Q/_¹®L³ªà~®×ÂzÊØçð*ÑâB\ðég:õ³ ü~­L&‡­Æ5Ú·¢ K;‘±}í«®£9‘ZŒFÙL1­Q&Û†b‰’ìJ{±z­Ž$’l¬ˆt¹Ù§‘­˜Ž%„D¨X¾ )ý°­¼@Ò£Ô'¢£æàŽÑV<£sOœ/ ÏĵUw8%¶¡ÞW’1„KV›¥ë×@Ϭ;…¡A9ëLq9}ŠnæÏfX ±D9tÁÜžÛÎ|‰néÚð:ÀØù!Ý΀û(G$“ŠcÂ}m†ÆRgl,×ãö³&££žŽü¸9…k“þ«t¡—$uQJvyâ‰Þq#ß»=[ÃÞçpRønY:¢ºmèZ6uB‹ Cz(Â]×ù†UÏŒyøÅÇâ0ú¬†nÐ÷ÁŸ#öo½ìNo¿Óä(–Íž9k Årõ½Ñ@œl¾Z6®Qåwª ’!]ŽÇR¾½³#ñm7ì'³8bݨ_L3b¼ª˜š÷y7&¾‹¤”ŒÎ4ŠG “4ÓEA ¥2ŠxMG¶#a7(ʃ·Íôy6 u#Ha¾Õ L_öÝÛFƒŒ{c±•¸¿ô‚yþÒ@ ª@äEÄp¦êSܹvê~z=²P 1YCž½ ÉáÖ{âb?1‹u¨ÂwëÉ¢>øª‚¿‚øÒ"{u¾«Ýf0æ£ ŸOúTðÈpgø)ºHÇË8eeoï~|§ëÔ¨á³ß7öªTãÅæ†okŽ—ûMî_¢{ØÃ»Ú½kP¡'³Z›ä;øe(~X‚?v.ž‰×…ë“óîæõq¥©êÀE[’@O6ôy$ýÜÈ•"ïX7´ÏàV%ãR<¯,`^›tùì+­¯®ó*_¤º’stq¹ß < {xdÛï9Cc_á;aSÃ¥I¼c»Œi$Fü–ôˆ¡e.È™ßT™K …¦ºš¸ãìË‚kY>{NSO‰k÷nŠŒkE¦>IÛxˆZ“SF~óH(91J†—ƒäÁô&sÉ^âfxl3–ÆÆÅÈØb’Ÿp™ùR¬æp슱hûBºUŸOæz#P£÷1ØÑëÛ˲ë}6½%ºEÅEo›žhHkØÎ`æEæ’JS+197ì쪃;;ÛØ¥RºŠ²ŽÝVAGœ‘½FˆŠd#&¼ŸÄUè‘‚‡„æ…,j!‡5!˜Xê˜]‰ê+{9tç­ÈÑf¦Ýµ-á…™”{„㉀Žcr*-šÇw{9²'„×7ÞT7ü‚Á*°méHÉHœÇfºAÉzuFºÔçy¹§N’´Ìh&º‰SâüXĨ”†[uÞÑ©µw7Üý“P43°H²lTK¡ì µ’üìeY ¹e™2p]@C±×»bßQ·ݶ+6_®0dp›'GÇgÉ™Á•éq³àNøI*ÓGö-ÖÎ)/µm™Y¿Ü"ci4ôCTgˆx*>þX$4[oõEH¶8c½E5!•y_ÁÄ_ÈLýãdúmö8[h7öûžÁjïMX–>\¿èXMÆ4†éÁ Wî <}ˆÉ8Fžªè{!f‘LRBQåäæëøÞ¤k_7:>ïá‡çÿ ÷&Õ/÷3˜¦Î€O…Ùå%±•ë·ªÉ>ÃV\ÔŸY®L”Õ ‰«þ’«>µa¯m=Ooù'nµÅÒ‚‚1¯º]n hi%¿T"H³ºþ%‰°BÔ¶•ŒÀ™ÔÁc·w ‡÷hȤí}V•ÜÕ}'ÆÓXî--%•hÂ!0tTEð>ñŒø‰!6Á(õþôë­p®iÕÊZÑxÆÌw¡×܃-Tnü®ÛU?#è°7”SZiËÍ}î‚8’êŒ:kMµ ý4˜­mS*î»§ˆÆô‹]é$™kÇ÷_su<;×FœäþhŸ-^}Š ôÑa|Ï!쩲 DÜÎò]¶bÅ£©"ÜNÂÿd·úMË’ÉÏ£åX{IŠD¾jÂ8´nò/âí«4ÉdE « Û^!Ó~Òs£E;® *›òÑ(¬³;ó‡>ß ÷±/–AœÌns_V‚FÃ"?ø¾ä(ÏÐ¥øÂ.9J”´ãê1S=.Rãa¥¢×â®pŒ2³óx –@k´5(—Ra$ƒ³ipþ|(èoÅDŒÄùy²Ã­8G×¾¸Tçi”òß騥 %Ëhûk<ÈDÀóYÒ7tDúGWƒB¨[áê´%ëé¬jö¬zªZÄ<¶Lb®“ó†À² ;½õ^2[É{.¦e¦*û\)z ôŠÓo0ç=~ŽZt,CD<îÔÛ¸äèϧí.z}úýaÖRˆj’®«)¹Ç£89Q™c&º÷$·zÝ'orq>°D·½?%„¦Ùƒ²2OpŒä‹ÐŠ˜#¤H4všú¥NK¯±3:žϧô”oý*ˆÛ/Ñå§:S’†tÅXÇì»9˜.ÝL¨HÅ µ05±ëDõxæXŸšÔдš4ùôp_$1ßpû»~NãoËh¡ÑýDÓ€/£9®Lw|`„x!–Z£=8#–ļ«Ï}'u©}º©ä˜k?y‹ƒð¾ÔÕ0ÈeñGÀn¿ó¬ŽG¤G@°' `NYt†ÓœÒõˆ3k㺸Œ-ñÖ¤%…ý5³Ew%ïc’KN¾&ã[¡M«8-˜@}Jr3Ó€Å^“ýPƒÌ@AsŒ¹ùrôd’ƒ;«nU3ý¾³¢w4HÂìÄZ’¨ù‚÷?y±ÙçïdI8‚’0‘*n2Ú<>Ìëq6¤´•ÙQš ¯EÎA¥¬»ÇèúËð[‡µô×Àj휘ƴ»¶¦ ãjº!µºEÏü8µ,“4;” µ Yú}ýö"ˆ±±´½ØìKõúÄ&+$ŠA5LßJ½¯[Zí„á‚ýŽ•{ˆ¢^Ôo†_ÅúËɰêÀ°6oÎY#Šž÷³Ê¡(ê©xP Ã.ñ$™¦æ—uÜ,ýw%ÀÖjŽ©«:uh–ö™²ÔD~ _-KîÎÙe‘u ÓA-ú®×FlA›@¶×Þ©î?ÇðòR¿ávX¸µ'jî_'„ì~ž^ù™¯5Í>ÀgDT˸È>`™ÆÇ»¢« Ÿùë¨ÓÑ€]¸q (¬N[HWÕ‡šÝ w‰%ÇCœvòß~2Êw"9ØåÅŸUpEêíTOçÐÿˆªËsn1‡#¨ú ´êÃ:3- 4ÆW÷ ©ö»Q×˰ÀÑ”vŽš+‡½ã Ùvð’.ö#»ñ»ðêÜ ,Å ÂþryMñ̼Œ{"‡grD*}ÐIOü|‡"¸—ó/U%ÕŒR”n/*\‰pôù?Ø~SÆÃ’•b>)ýô]⸫(ZŨjU.| &³²©XZ;Å&éä½Ê¬ JAÃŬ—k¹ûÝçPlD&¦oá1JµX÷UgKs†Ï|ª¶ÞÌî-99?’xãûŠGÄ”½Pá›^1…Ugl¥Ń·®º>«_÷jÌð³_ÙíBëèWèi"]çüpM,ŒpF7jã¹ùºOmIÕáz¨øczö;ì\Éü†ˆ÷n Ò‹¦‰¥xí#P¥×GÒ*¤™rô@ÀDväaéÐÀÇæ¹OYjmNºŽcÛÛbñMþÙ–|<á˜]´Š½?Žû HFèº6(4ZÕü³®½-½-.¢MïL$H¯_ç¾ÊÜçñœØS\ä¤ÈÀ*r‡¡¼óó«vê]àüâ´ï‘ _¤àE༙ÀÛ/{3;Übýó’ ú(‚A£ˆod8‚ÐãòQXz!>.ãˆ4¢ÏS:‘—6–ûŠ-iï ØÃ6r #{rVjñ:Ê‹ì`¥¬˜Œƒj#Ô‘À´ Ü­–T)½)¿Y*õM™¤´±&5y¢·£ÊDQø·29eCnh†þûÑÏ,-ËÅjŸ¥MÞîôí˜d)ñcÚ‡ÒŸì±k&ý‡-+X._ëqš‚£§€ˆMEôÄ‚ìÝpc½Øé»²qÉžê„S™ÓÌö5ž²L&>_Úé 0ʉÆÔ>ŸØÏgWî=ØŽ óUäüÄ×ôûü /±’ Éó/ÄQ¬­ú“Õî2áj<®`¯»° }a)²ŠÑ2I§R[ˆsýKý‘¯Jª“m¼I> ìïôÒ¦Á;»ÜFL|§ÈñE#N?èr~º0å£Ó…MgßâñûZκ%¨òÂð\.ý^û­8"l>ë2£èü67Æzã7ØãSéüub,«Ò…þÙg!ñ­>İV»„OIò6Ÿÿy&zO endstream endobj 174 0 obj << /Type /FontDescriptor /FontName /ACFCCW+CMR17 /Flags 4 /FontBBox [-33 -250 945 749] /Ascent 694 /CapHeight 683 /Descent -195 /ItalicAngle 0 /StemV 53 /XHeight 430 /CharSet (/A/J/a/c/colon/e/f/fi/h/hyphen/k/l/m/n/o/r/s/t/u/y) /FontFile 173 0 R >> endobj 175 0 obj << /Length1 1380 /Length2 6016 /Length3 0 /Length 6953 /Filter /FlateDecode >> stream xÚVT“ï¿§$F‡Ò2 i¶‘‚tw·Ôlƒ1r€„" *ˆ” )­ˆ"-ͤ%$””PR¤¹Ó_ÝßÿÞsî=ï9{Ÿç›Ïçù~>ï™ÀS q57´+\ŠC$À @ #s9 ,%K,XøV€€5ã@£þ›_‡b 6M(–f„Fõ|€) DV"§%Á`ù¿Ñ &4á4’ê£Qp€€Ú7ƒððĺüµ Á„yy9±ßé@5$ƒ€AQ@#(ÖŽ$t„A}€hŽ ùW !EO,ÖW ’€"ý%Ðea1`ë 4‡ûÃ1p7à/¸@c(þ˜@hé‰ðÿÃlvÇA1p Áàƒ€ÁQþ„„”$ôZèM|á¨?‚ ÿþy5@ˆäïrfÿ*„@ýN†Â`h¤/‚@yÝ>p ‰¶¡6+„¢Ü~B}üÑ„|h áu%ü>8¨­f„ðý‰Î†Aøbý%ü>¿‚~•!\²ÊMDÂQXÀ¯ói"0páÖC@¿ÇêB¡p¬Ý(7÷_Ü|AV(„_\OóÏ‚ ðÍŽÊ€Á`9y0î„Ãë\iÑlá˜C@q¼ÔÇ6"Gˆ‰E*9ÅDòµ—*=¤WV<~n´R×÷¡Ätâ*§Óž®œŠUܬô%‘YY=ïåöÜdØÂMp—3Õ¾âm=y*§qð:óâ¢l|¤>ß%¥=ÁG<;˜»Ó<ÊÓ<:»ìi•WbA´“¸#Ï Né]»°3}¡ŠÃs¸)ÍÔºA¾~Òy,ˆë„|hSuÔŒ±Å´¤jVšØ'•jõJ %}TZOp*mIZ·Õ³ ×·p<ùúßýYhng¹ÝÈîÞÈNq‰Ëü¾$˜Íe6¾ÎÒ¹ "ÞÿlÆ|ßðá;®hÚPƒI#näKž¢—EÙ;'“T¢N_ê'ÕªßÐZ}g:Á<å\›¶uzÁj$½?l^ç>¥è9WžÖè(o]—!‹y´»}%(ÔéK Í!ËdWÑdà#!ÒÝi1ñÂhxÇ·7£M…”* óø¥t•ûšÕ~p¿ö´Æ'÷*¸(«ÅóóJ)ƒµ6·€ü{3î]J*‘B¿Y¨Ìˆ¶ãD%ŽNk"ñÊCqq‚JyQuÝzúÇ\wÇþ;¼þ¾¨èª<ÉhNêHIëdÚ«rDzoÌÞø$€èÅžA„HPT£Êñk[|i¯óbÉäË9®ï^“©]~lBG-þÑ©À©½•=Ù-y”ÿèYUpR¶ƒ\ÑÚÉÀ‡”g0ÔúAÈÏʧ¼ZE×èuòWðŸ»êºZÔ㼚éVß$tZd¸$98Ñsœ?>-rÌá‡âmM5¼MëP¨ÁEòvüì®Ç嵇S3¶éès?¬sé®x|p?¡ïU*g Ù>Â.÷õg;¦H}9£Î´ Fç«&Rý¸A§óÉ1¸°GFþÕãÚp„o t—â8ï ‚÷]+pšÙ OÅèì˜3OÅX¦:Ç͸rq8î$Ë^m³çØÆ,Å¿L=Pþ\AÏ#}•R¯‚)r“Í*¥Ëì1†u³%ìÌPÅŒ©'ÁVgrò¤n·²Ò篼~¦Æ°.w «]¦˜ñ ÇùIÙ8©• >ù$tÊÌfWDÔã‰OØt™¯=°XP! `:$šî¢9%ÙH·ÇóTÕ¦Æ=@$£^/¿Sšj®ŸÎëÎ^OÁÕø¿PZC:DGE§¶0ú8éx÷ðL’«¯Ï q¥'ùÓ“5É^L™âzIæzdt'JIä+e­ iy1^vYåóò:ªU-¯—S•É#Ö” ‰ÃeiíÇmHL˜#¥Ù½çV„Xˆ‚˜³|¤ÀF‡ 夭¹3+ ZD ìÕÀùÉë9ÊÌ=ßÓÍìfÈ'*Ž9ô&½ò!€WruNQg±ßÖ^¸¡™Y!‘¶…ÑcÌ`ÓmÞ"wŒºçŽ?ZµþZ9žR1ë%g u†ö¶ýØãÇñmŽn²®”pŠG]ì+¬r¹š¤ÏÜø&̸¥ûü Řš-É´ÖzÓ£®ó’ŸV¹ŠÞ5~%D†ìÕê+ïD¼ž62zÒMè% Òð_hQV@JHÄ‚üÒÊ}}€ê‘ NZ÷/Ëú°ËéÍt¹Ë;=Ý vD’<’¡Ù\áÅl¤Õµ&^w¸¶-±µ|CGTG#Ra÷•¶(¯1`x”ãæúû ${ºVÕb(lc(9#ªTUnÝŬKn“g:ï2ZúvÛ½õÕ_Ú§as†Íš=QØš#òJù²T:§0~¬ÈÉ‹gXësQ·µz%˜gÍyð9n“ØøÕdoÛ×—&/5E>nïCŽæi>YÛá͉§\åÅ'Ú½ØÝã9Kxt3$uµ<Õq¸™Þä ˜c&H þЗÒúøÇqðE؉ž£½Û³ÕlpM ºeÅÍZŸ_µ2lûîåæXÖDj‘¯¥-Y!A;—Ni r釮|/§W®­Kú’¥KhW:sÛª¥åk‡ïß•±Qq"aO´Q• 5Iõ[!+)¹éWS˜ÈÉ›¼}†ÑëèýÈÃ_¢ì¿B1»¹WH~\e§ZzØØS*sT¶ÆP‡Ók¾?I¢ÌÜra5úzXãõ§5I¥6õC•­Â7í¼æqŒU€vç^±ˆÚãŸ~Za@º(ÝRö:BÅ6Áµ_:æÓn8ö'<§íŒ”dlú¼Îp±~5ÅÐÍ~ |W2ÖæG£ÄºtÉý‰­&'‘¢aîêK}šSaÛö*Õ›·änÝ·ì?§¡ÕT4]‚ôy9ÆÏS‡ê·0¤æ}"ÿúP™û‹&G®Š©óù6v?ðà !5É0AVž°WÇM´7Kõ‘kîNÞ]$‹¹2K»ø“ÄI¾°äû4×o.Þ0‡.OÜMuÙÔ¨ª¢kQž\;o$ÆðÖŸ´Eû‚¤˜?å¦6·¥çã®/>,/ò•þfÏûŠÏu‘>ˆÔ—#ŠÕŽ4~ND´àE)˜õ61Ï,a,Û°Ïu(ÉùÁr±%±Y¼ÕÚÇ™V̼Ã6—Tæ=$ô\û @-]É9á²#’:ä•ð Šø"e¡>ùìÊ@ú÷ÿÙko¨D—>ÅÒ¦¥"2ê§¾hÊ5ô^ÒHb.á 8ƒ®}š§XQ,`@’ãÃ9ÉÏ/‡ÇßU¼iÿºB÷l÷ ÕQ®6} µvû4u¥•N‰A6~q™Ïå9ÚÈ¥^oþóCv~^ïžy‡;#ñk½ÊbêeQ ; N {–ÛåüY„}ßýœ ÞÙ?×5aÕ4ÿàyËð˜$>ñÎ ãbY™ @[ìë¾êL]ÒãîNñE`:æ›ù€Õ·†$m–éyiqrмÀò{ÏY¼«Ò"ú`äþ¥úRؽìxè`cjçW[ÇÍÜáÎy1wRÊ ^œc&ëõ"€a+þJ mr1ö没ŸÖ׳À˜¾‰Óúk*‘ôªÃŠ_Ï‘*eÛ·/vÔŸŽ¶Úm¥³¶É;Yït3ri™²›êÝG“„?¦¢™1vŒ-=ûxLN§a±Sàë:Ñ7ÚÚsîÐ3„‹;ijIŠAæ -¯ê›ok\¥:iÞã«‚· ¦„õ‡_Ö?¾õeqTý„-+ÔdÐÎ2MÃq1Ö :zûõhÀîTS|njڣq‘K$¿N¼ð´Œ‰â–KÉÍëÕjO}?½ã%ítç%éð¯ëOuí¥¤›Ô(ˆFÑr‰jÏü 0ø¸YpþÁfšžnúˬýšÔ—CÁñ¸ù}–â¤U˧œš§ÀOÊÛ˜µ˜ý¬´Í„ÄëÚ×u&J¾ ž¶p+¼Â—º]ܸd{g¦÷fÏq ´0Ø´Ê¡¼sÒè(6æwõM‹|ï[§håºæëM.ÓÕ^ß9¬ìþHlÇúàEϰXI_~a×¥wÑ–łךz}SŸýSK@DQò]Jäj§dò”c‚®ö ùâ³xÔU~o|„yÖäÞjJìB°ðäeF_–Zèø‡Í6žaÏâ†Ýt é§‹hZ*ªû£²@WÎg ËXôð%q)Ü­ó´…²Z%|ûDоÄp¢?¾Ã|A<;.Ò6\5ûÉ]±OX:°Ä­”'i¶µ]›À¦ëí±ñmF Ô· I‹vÅñ_õwq¾¸V ºë9ãðéÒ6?+òª½§qÅuŠêZ¾×j:²ê*µ<ønÓ9Üé ËÕbÒ“]Ñx粡tº)µfâvÝâö-Ë›ôß ]ÚÕ.ߣS+}Ó¾Ìt—ïÉ×aÅ e°™’ŠÉ‡iãÏ ¦½‚–'—%§dV¨û± Èé Ÿ¾Õ«R–%¡S„ïS—ñ§æ’K|©›\ãD¿éÄ^b=•Q!âzÊ&Z%ºÕºHÓ“é!ßßVÑPÛq­¹Hl+÷Ë.EŽÊ›®æ_ðšj»hÞwŒ£Ϲ¸hÿ3ù•ð³×|£‹oÜ¡ úR? "TÁÛtãjE@B¯éÌã€-ñª¥ŒÒ^Œ†:ÊßcœsÿÖNö€ÇèÁêUY¹Vè´¢ë«Á (õЩ;‹œ¢L¯ÿqÎC‡žŒÍ€´¥S’Ö¶b•dŸ¡_–>cý~øtœ®’Û}lÀ9%Én½l«[& ]%j4£KŠ Úd'¶ß§ ?ô‰üÑ5ý¡^xê K–BáDKq®C?RÁ¥+¡±ô˜!Ÿ½Š—.10‘z6PYxQé÷u•=x¤gm6qr/ßSxí¦ñà`éÌ¥¥rejp ¶Øy‰VÄŤ„RAæ u¼ÑFÎã¥ðä°ƒe{ã&«îŸ÷ׯðÍÑš½o¦×¨JËÑk4D¬ 9RÃrÈù ̨î°`ùìÆ¸Íqù§ ßqPÓ¤× ¬¬ wFä9›øÊ‰»¼o)òZ’¸l(ƒÕ`›ÉW† ‰U·‚5º»‘<jú«¤©g†#J}F'˜%û6ÙÔx•7¹™t¶ò|&JX¶˜AÂË8;x;›ç¨‡” Äåò) °î½®a·ï¨ÌÑ,§Öì¸ÍÈUÛbH³ö^³›Jz>جG Û~ œiM±ôž~ŸmK¹Ž2Èž“¯7ŒjgN¬a©pi¿¡‰}IÚþ==k›­Ò ?Ü?£ûý‡ Ö!ñçÖÛáï:mú1î>ìË-ëj™ßÝwÝ•¡2š üe² ‹>I-§©µ"ÒÛ |æ ®%~£yΊâ3ä¢?EuJ)?8‘ ¾2á#…~<©Œ£âÜ ’Šsø’é`›³¤ÖÓšuS:Ë¥ßñÅfZXJ`ìRÌ´$¤UøuÎéí\·fY2 9íFoÐ<dR_Æ-k… ž­Óù2þˆ#Æ/º2­!’g(0Ú’s®m.Ǹ{h-LÕ¡Y€ô-E,\ÃyC¹“™ßvïLý{½ ;ަ(•kvù•½ñ[ •yõTnq¸ysd–B=”våK&«ópvâ‡Ç««âô£”Z…{Þ^+Cë‘(oÞ‡œdJ¼öA’‰Ï–\ï>ØÓª¼-ÿ#ޝ]; i7S¶f¬éû<Ý’ËRÖ^àÛñ°.Œáõ*ÿ*•›=íp(òˆ¡nä*’7羑õ¶@ªs4û"=5Q¾™Ld0{ò©ú&õ‚”ë¶€:‡*¹‘[íÿ5¡uÿ”»¦ïl`Åvç; ’©#ÆW¿û1’ |”ÎØKâÏ”ZÛVw¼Õ­%o`µF³ë`¨EUT”Éö~V^ôÇí\­«,S¥µ e¤ù|üŠïs0“®®¨¦@b }„É=kJ)¼©1µöíѨlùabŠ<À ^Þ¦ ò<;.}=£79v&eÈÃ!÷`Õ#ûIwuú›us23ƒk/yv¶¦S#ÝÁž{y/‘Š•ç×XòoÓ†ÄL¾ÈÇõ9¼1;ÜÐŒmpzÞ 1œ…ôßr¸ÍOÄP¥Ñ¢íºýÃÇÈŒ8ôžOcßbþŽÞÌ ¢ªkõî4âSƒó$Ó9E&Q£ê–ÖÉXuËfìXEÛ|õÃ-s½¯¾-úìR±¥½v·O¡þ4Ÿr;ÈjD,Ìì ÕMoDëÚ©3u™y¸¯]vZ¸"8KïoÜîŸ!}"# ñ]$æ!¨ë•³BÙƒß1Mv/ ÷ù:uµ¨fò +J/¹2ˆ]@Š„—û>ï¸mœŒkrßÍÓŠŒSu7Λ÷ Ë—àvqãÅ×Ä0±•>ÃP/.3Nrøc¥eØ-Ä;­XzXƒ“ÌŸ»ôkóÑÍ-·&á‰(ZÍ–ZùÃoŠð £_tŽÌ y»TE½¬CFV),Å€ñ|æp÷- HÉŠßaö©SaÚ™Šq¼GB3NŒýãjBäGÀž„…Q¦ƒI2üå6+’ý¨šãóæß÷÷3æyn•ùJÜø¼eõ’Ï+‚^d'¤@ê81>'Ãô1ž¯o«Ê/{ck+ôÏÙ8y8`ŸŸ³¦÷¾ñÕXòWNÎc=ªüð¯œoÉØj¾/ Ê)½ÐUJì#áË3þ4TŠê7Ü´éŽøbAq+ ³JÂ~t;£NḰ¤Éºažëví½ø|ʯ¦•¸ôxq§_ÿƒâièC[d‘ endstream endobj 176 0 obj << /Type /FontDescriptor /FontName /SCKCTK+CMR7 /Flags 4 /FontBBox [-27 -250 1122 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 79 /XHeight 431 /CharSet (/five) /FontFile 175 0 R >> endobj 177 0 obj << /Length1 1698 /Length2 10634 /Length3 0 /Length 11727 /Filter /FlateDecode >> stream xÚ´PœÙ-<¸‡Æwwwœkh܃Á‚‡à\Bp‡àîî\GfæÎ̽ÿ_õ^uÕ×gmßg¯}h)ÕµX%,!æ Yˆ£++P ¥¢)¹Ø€@NZZm°«=èO) ­.ê†8 þK/™¹>ˤÍ\ŸÍT ŽE7{€ƒWƒOpÿ1„@Òfî`K€ @ârA¡•‚8yAÁÖ6®ÏYþs0X08øXþpH8€ ` 3G€Š™« Èá9£…™=@ b¹zýWaWW'Avv636ÔZ”‘àvµh‚\@Pw%àw»U3б¡Ð´mÀ.е V®fPàY`¶9º<;¸9Z‚ €çÜ-e€šÈñOcå? X] €ƒãïpyÿvüÃÙÌÂâàdæèv´XíA5Ye6WOW€™£åoC3{ȳ¿™»ØÞÌüÙàÂͲ³çþþêÎÅ vruasÛÿîýw˜çK–q´”‚88€]]P~×' †‚,žoÝ‹ý±Ú9B<}þ<[-­~·`éæÄ®ãvv)Hÿeñ,BùGf rð@>NÈò´°aÿ\ÛË ô‡’ã·ø¹~?'ˆÀê¹Ø ôü‡âãbæ¸BÝ@~>ÿVü7BáàX‚-\æ k°#Ê?ÑŸÅ «?ñóä¡`O€!ð™xàïßß'£gnYBí½þ1ÿc¸ìŠZÊJªÚÌ4ü·JRâ ðaå°rò@.^ßóÁï¿£üÝÿzÿCªnþ«6à?­ ?[x¾»ÿ´áþ'þZFÀgP…<ó`ø‡öo€<@‹çÇÿ3ùÿpùÿãüï(ÿÚÿo=²nööh~«ÿ?Z3°½×_úg»¹>o„ äy/ÿ×Tôç«€,Ánÿ«Up5{Þ Gkû¿/ì" öYªƒ]-lþ$ÐfðÞìR‡¸€?3V ðtÏ»fa÷ü”¸2²úÌC[Ü~b %1Vd­B¯%’:±–6e®Ä(~ù6Ö"…KÐhº÷}0‰×ßnB™{Õ;šw(QÓC†Lʪ-¾ãûËÙW7Ю¦M‘ö“³?†úgÜ[n9Ïšž’Å¡°™m ^%Ô‡’ Öè7…S´9æ™Ó„Tˆ®¬d/™pN=1§®®'q²GŸ(ã™QüŽb¸ò} Ö8c尿—Ë´9]Ú‰hˆ Éà®p†Æé|$÷’ f}Šò—zç<…ó)²ÑYR–X±Øö8Ó+ÀšQŽ ]UîCó­[Ÿ’!ô$½¸[ UÅ x&P*5üŠ&“(\×*.;Ù^«•äróµn‡•m é‚ÀDÍ`š2¡ =+Âcxùµ`;WNvž¢Çá¼ãø J¯l×ï­ˆô~)±Ù¹K é™,óTÅZ/ê\¥è]«=ø/Q*QyöwõÍEŒCÝŽ§ò£Åd‡xï3 œ#^ˆÂåIçŽ[aÐ s¶Æ›Ço} Õú‚èý*^”½ÑnuǬec Uý •íYgà‡%B×5?CœjüC§ømLT¤ã³Ï¸âûúHÇóx×”÷.cØ#nþK³ðìïøU@RœÌ>ñ3ž„˜4LµG¾ù÷KavŒ™ •Ò?úи¤&"#u’[pI¥=ïN÷Øßw%G~(ËåƒsKÔâ|ºtoZ óe57 iIè!;|û4µÛgÕÄUîKrÅÞ¤"2(ãEÀoǦ½ô¦Í†Ÿ&VRU|H0í.Í›ð›Ñãýú¹û¡ÄËu,^ÕýètªH>Ӧ楷iU”\­“×âçLàÉn–GO…Å &5vªävÔW!û þ¡'Zô@lÎ̽uŽ$óg¿Ù…·M÷·øô½UÕšZÆŸò_MªÖ¥š…Ë^íW"1´úgVÖ^cPc4¶‡„,ã•-¶…”ÌI2Œ+Ò!‰wbgïloQøE°®ôÙö’xAóÕAð>(‚þ»_Ád!®­ñ›ƒ§îo¢›.¿vAÉýÖ=ëÞ”,KuËì‰n§ ¤¬0õn~òAñu ^£N“õ.4d±–»dý³ªìc“e¤Ù¦?:ÐMLCR„¸ÝÞ›YÂ{B¿P¶-¿T–D“jo~ïF…ŽM¨$}«ŽIo¶¸ó¶Ó¶o‹#ÊX7¢¼_N]mh\Ù|ì#™«±IÌ µ%å¨ HTpøIizo@—£“ƒ¯¥Ÿ¡1ao÷W#϶í¡å D¿ªÒÅØÎvrûª–½9FÉøm·:x*JKDNò'à§Y‹I–§¼É)x1ã3 á­—pè46+  ë„õ’LÅêiº>Cüq(·Ô{`F¥E‚/Fb0RÜ—ú¨v¶®6º;^5V rã«î¹Ô‹eb*k:iŸ7çÚÜ–’|·Ú>´¸41,Õ ‡m—#ßÃb™/…š5½d–*Qù5o,D·àèf­»V´œ{ 'â’ÍT‘Çû¦:àóLpE)â…Õýjjró§‡5Í7ŠîÈ£šNוgÛ þa?v‚¨9ïbt0Ì •Õ‚+ÃërRÌÖdæ™ñ€Ø_`$,,_?Âd–¦+ãZ™(]*ÕŸÌýŠUdƒ±‰ñ;éô¢Zp(o§4¡^(ô4Ÿ¸qâQ5|dÒôrII¤94g?®è§J|Wú ëcU4¿êÿ‘¯|’âùîåºhcG1ÃÌ!žFrD»1/Y£œäh=£¡UF¯}D»õW‘±ÜýÑ¿jºÊò¿¡ô9QãÊ| =Œ­ÿ— ¡ƒ“Z´ùI_vº³ÐÒùðÎQ)P©»‰êØ£M8¦ûýÈÚÏÞèÛ,É=@šu;x¹g‹³ä•…)ol”•þ^ì-U ¿DUWLltëŠÒ#ŽIm¥ÞÔ’óÎpçƒ^ñ8 æ+1w6‚KœÉJkf)UûÁ€9ËæøÒ«ÄÍ=ï´¬ÃíVÝ Në\ûº[¢E~“F¹"[ÛQO)Yí²î\=ªfwÒLº”]q?IþD½ÂÂÏß\?!X½´¶~@¼YÙDr™E^V"s ‹Cõó4¼ê£d3²^–Ⱦ[,£º‚»p%—f·´e!‚(s½k{ 2Æ› ˆ{EÞ-ó£]4"±Ñ¬1I8(š¥üT”‘NþpŒ1pQï˰—Â)ºFBÉHBOI»™£ˆF€1ÃG ;õÙIý\ŠÛÆÔ2ðUÕGy^¹R´ëWþ3\×pròÕWAØÁk$ÆC›óAáÂe×…9Ø|[4¬rV.¿Ô¤\Š%m<-7V#Bx¦SS–ºÝú±¦ÝO«, îµm]!”ÌS3F— ÇT¯ÃÁ´Á‰…ú}ª"Ò^\¦Ênˆ‘\ijƒ MW‘»s‚‰ñ ?î¤ú·(÷«ûhk•^͸‹\wtŒs›Yí=eÀ16ÿúdsä |[=àQÙ×¥#VÊÅ;8eÞ!ÿ¥‡–EuÇã0”ç32Ô¥º*hȦ=°Ò·ÎÆWo¹<{—l· }ÌÍî¤O¦<Ì Á•ΛJã ƒû-¯ìÚÑYYÕ¼¢¹2ˆ²UƒŒ!2 ˜÷ÅXÆ ž|W\A-bFœ!cÍé‚HæßóœË…æ³~Ù‡wµ¹÷Qè¾ ÜŠûU[´ŽŽŸ°;üƒÇorþ>ÖÂá±ÖZ Ü,l0ÀEëÞŸX7¿œ=˜Z±a)Z¥Ç3ƒ¹‡n´ÄRû-[N¼Mfo¬]ž71Ú²Gw#ó'”‘$ $bžT§¦ Qß U­F:Ýâ§_ÂäR0GlEŸÉÓÊšÓŽêuãî— Ê<& 傸¼¯4õ3Ðöåé¬#B>‹ÞÍs Éô*RºÄzSBzjú 8IÂ:“Nõ…¼&ƒ¬!¯îæ ¿UÝ7ÁÚFàw¿åÑ»×(ïô2iã%RúÄÑk"Ž/ïc긋çyQ‰bb]mý¦G¡Á5â„"½*6êC7m6ˆôÆxÜN ÏÀ¥ öö8‚Þ:Fpöûžœ¯zµsWø¸Vó“Eª ’»A¡}-‹0Ž1Â_}‰6›~(‰m{¤¤280‰vßÊ ìÕVžtX°™óÉ Ì‡Âú}iý‚§uÎ “7=¬è?&€¡iê‰ljîPÇtú®2©¹Aû,"ÉX÷ƒŸòƒVðÁTÁÈãª)M Ià®<¢ÐÆgW6ÆN@E™£üæð‹„AƒP.ž˜:[iÄõ…ú–EM±€ß×ý„*úÇèIãt_—Z5Äš¡»ÉsoCjÕú8± ‘ÛO„ŠI±o&~ø~CߎÞ@ /úsD·IrØ7riß»ŒñÒ6KDÈóGôc÷—Ëôï\˜ÛŒˆó”r®ÕMsVŠFD¡ /¯¾sú,1‚¡1üìÉ–ú=ýúÖÂ:w³‰C6û:~—›Ð¯õpƬ*vÌ‘#Ë/Ì7kœüíã=xØ0Úª̰´[^ƉÏ0æ•v‘ã|¢lÅ2±¤@ž®æ#4CÀ÷D-"(ñƒ?œòKÕ“hŸs£|°›Kùl=—PgßñûøƒYš;ª® ŽïEQ0©J0о£«a>}3Å‘H‰‚`{šüA¿œHKWcPŒ]þzYí:€$—ÒgcfaÎ ¾8„ñ¨Õ­7Jc£nhA8¤.;½}Á7¼†+=mÃÂBA “üu½l`öèµÈâ9¡x´EB4Eyèj·˜³èVåÑ6_:½”æ(Zµ`˜ù† ¨œn•ü÷:®áà LŽ$“àyœ[”ðé¶ÉË~s÷&W’wã]ÍÝ4¢^'"‡¬¾»‘eÒmKò’¥ß†ÈÙÙ;·–·ƒ¬ÇfîàÅ´º dïÔH°d:ù&{VŽtVc#u¬æ—?Ï6Ë``ŽyþúâßÔÕ¶0e’†P(§ivH:{»êHÔ1Â4-r »Qᾚ´ÊùëÃQßÞÚUÁ¬ëÙð.i'êeóêkß87ÛÀXÏÈG¦Ÿ„”3Wφ~Lsü™Ž {Ø:Ý™|eFÁ~ô™wõÅ+QJÆTOÌܕeºÍöG²7Ôâf…ÖïáhpxFhl‚G…f(Þêx3ú¦ölk8Y!3éË&Éãâ¶»`³£P0í¶öˆ°$Òp#xncØ…˜Û’º‹½SÔ–ñ®¾6±Ö¢ZÑ^n“iJ¶Z&¨ý¨Ÿ‚JªõêÄT +e¡&Ï) ÝééÖB¸ç{Ñœ˜ôxàÔ¥QÅÝuÚ6òvÛ«´'É>9±WÕüTµTE®2·Z„Œý8=’[ž‚³õƒP«½—QÒt)&$ è|WOéªÉÊôßh'M8îÛ´áÖËy༜d#¿žw‹®a¾Y¥—ò„óWVmbœèù¡»ƒ·’xUóƒ\ ¸Lu_™“v1I$x“ÔS|ŠÐßí‘ö8¼ïuå­JÅ•ŸÃl¦ÿCŠ Ù0¢X§Õƒ[®s6<™ad}=«f®‚ðŠÖRX¯\ëdŒÆó²q¾Çð$`mô@+ªX2»<½E„.„=á–,Q˜¥Ÿ3½ÃÀÓÄc¶ÜkgñHúÔ·¡[èð©6οùBbüqŠñøÖWaË+#? !Dœåóû' Ú˜4 £-èex½p,—4‰f I”™ÒéT‰£$x›ÚëÆ^‘îÐnÝmæÀ%àÑzNa™XÆB“ŒÀGhŠ1à§¶¬þjàHpЕ@ù’vÊÊ`ìQì Y¥=¯Ü(Ãí{ME:Âí‘poi†~ÞÕûý$™¯j€dÄãFsyUãƒ<…#—1œÎ*qYTï_9ݬÖà4ƒ‡â:•g=9PmC|<ÕÅ_^Íþ˜šx½l­ÅDz,ÿ:ùƼDYŒ Ÿac`¢V´§«Au (Ô]FT2Ã…åÌ;§ô:Pêøûòà V‘pÕÏû˜ê_-Ǻmv°ÃH[‚âàmLÅþq}ˆ"Ix*€h{1{ܪk!XÂkÔML=z±OÊÿÄMW!-Ø`©FÓ.+¬Áaân×SÓ+,ÞK·&µ¯bŠûXÊ ÜÞ®ˆ#²2½q¨C ½÷Ý•dÆ©`Fž½‰‰Fà1—¶7\ÑûŠÕ”a»/ª¸ívƧ¹T´6–ÒÞ¥r’!¬#[9v¼ZW<×ÄkáÚÍpÑ>HÞ^ƒ¨á°ïÇè`ƒÜ„[»û­\Ï][†qüKÁ˜¡‘õ# {®¶­½f¤õЃ=Ñç é"/þa­ ÿ—Ð(w¬õú¥ KÕØÎvafGjÇâ±¥† ÚN³Ý;²£P-æ`¯(˜•¡g¢>s$§ÒùxJ\p=¬¤Þ¸ôR¡ï߱ěS’cÈ[é+KŒûÿrÞ!/²Y¥År:^Y@X¢Ê­—y* Ôa_¯}÷C*€<+HƒÛÅK§nùè3©Úˆ›ê1NÞ£:‡ß«d0!6º]ÇgÊS;PóÐwGp$ðîí¨™ƒsÆœ}Z#e&çZíécœŸÏL§_~f ÔJCdî'§Ãl‰ŒÓ=nÔži®·šCùYu%ßi߬ëøÁ*®Ù>nÙ±iEF:­Ö iO *xVyA†½=u¤/’»õ"~oc(S¯Žî¿y¼ƒ”Î\ƒPƒ†ë#Éf¦ay¤Áj ¶moZ­¯>œ7EÿŽ”0¾htµýS:P4æ(,úBW¾¿C“7ü¦ Ia™¹Ç¯Ò‚·1Ã+äG°ªùb&0xOyÈÅ, äVû鼚çU}ˆ'½í´õÓê £3ƒaßy.ÿ(2ÚµþÉ_ ï„e)u,ä{ ,tïDUÊåq øZÕxô% °¯|ÕÎùc–›êÆ~4“Z¿O¿§ :ÎÂs]® @ýtiéêítN‘©0ðV¤}‰i¯ÿ®‘ÿñV ù.”ƒG8-¶mw1#ÀÙĺõè2Õ¨ËH6¾0fV†G!<½ãˆ½’ÄÖ$rþ›¦ÊѦ¬K‹;—l‹=Oùl¤Y…7rRÍ0 Î %»x>×¥>YL›Â nS½†é¯+ûõ¤1Z›øÈ¢á }ôÜn#G2’oùNŸîˆéx8ãPŒ!%¥ßtŠu?H¼LHxÈ5oÖ/NzÔÖdÔÅÛAù/|¨Œˆ-¶Ä ‰†£{ÇåϤÙqCYWv#W="¤8ŽiÛÀ:ë"ŸjçH¹ë‹\©T _S¥çÒl§by¾$ˆDº,R6šè†¾[©^‰ßÍÏûžþþªïÚI„üªLíJgŽ×îÇ\|°Ú‡È{LæÒyª¾EÏÕÀέ¬°ƒèÜû’ù NÑÔ_ú½Ðu¦jfzÿð>-NÊç@>±]SÌÿC7hL¦þJ:Á}¾ºe²ÇE×coÕM(›ˆûqVÊg·÷ŸrüŒÄ¢ü™R³—£«2è¿Û16__1Ñr"«ÂV8fò„{®¬}#t|L*ñ¬h2êOŒ·ÙEAüž€—¶H¶ìÙÀUÏÔöö %ý <…fïÃ=.¶ôÄ·™þQ2§Æï]’Ðí³€i` ³Ó@Íx3‚¯˜Å-([ókZh×Ì4åþX!z#Õ߯˜z‚K2C–=¼#ɵ¯ÉI“ <£½]k! 0$þõU’ËþNêRŒëþñ×#²ÍµªØž!1½0#"ŸrèÞàäß—±7]ŽÒ>ü´¹™™èî6e05|?¤Yh•°$f}WºŽ‰÷á€Èä›–»YD [À€rCç”…Z±ï½Õ~ÊM‹‹TT\¹Y&ÑòõÊ›ä~ƒÕøõœxP¢ Ïi¶Ý§>ÎÖy †z²ÉWu®Ï_§qßz8Y\ʵbÞé’­°ñsG/ï»ËgêW:`Ä(G_ßó )&Ð7ÊÅC”à+Ô£CC•KêÂEï6g’ʾ>¸¡Ú_߀¯¿u5ºàcé|¿³h<œiïÆÀA7r¯ ›!‰›í)ç‘lcò>j9Ó7ôå‰ÑÌdš;yY’|vÈŠrëÙ~Kå2³‰#>íü©e4üu2mÎmS׎ݔg’{â• †ïþpêËÓV,ójAZyõ~nVÝvâ2®ÕnñqץѻJ•—û·Óõ¥«á‰ÒmÚu<³E38 QõÊc°ßûÐ8$VÑ”ªh¢ÍU‡(\ ñÏàJ‰´PýÊG¿”B<¶µh]W4»R’_14:.Dá»éçføj€Çï+Ê8FpôªÕL¸Nî]±Î=Í)`2I±Ä›^LÖL¯Uäþ±vOØ€¿Da&› S[CTgT‘³¿œ.™C ¯Ó°F^¤ºw9?OÜ_¡hŒŒêAèÐ ”…Z5Ê6ê ‰À²¬@v¼È˜.¾DW÷Ä;ʹÄ\‘xøH5nXóùºh8Õoñk“B|UÛ§Ž(ÌÃZØÈàyU|¯ªKüéõœ•*X­ ý,ÑrSö‹£¬Ê3kúrºZV‘Í<â;8.ð¹èË™Ö;^^¥<…]é ’2f0žîÀñ ²¸ÚlgÕ-’ [>¼tRA˜Ûp~€äD®é†Ãá'kŽE’$¾QŒêÞPV÷±Î®ý~“ þ^šz,?¼¸XpqÑ;@óAXXånàÚ4ZNôÓ§ÒŽÊ­¦¸cꇤEì’‰À²ÜõÀ®×~":îÇeÒÄØ<;%Áý6‡FkÔÈÒcº 2waͱ¶k¹ºÎ§ëË*h—ÈO$¹®¼#À0—Ê {WÂÕ¨AWŠ¡÷ëõ ¨†n:;“qKå›9Êü|^î|Äw4ÞÁµÅ¢ Ô ”áàÛT| ‹hZ¥åÉóÎŽ-Ã׃%®åonµ£Û¾/< ãRÛûiGµ²Ãå´€°ø'ÕsígH؃72;žÂ(€z*­›9îfÉK&Ò&ËILª¦”9Ykª0»|-qºÑñKÜmGªdJP‡ÆÕŧfÃlÀÞ]Œ)6„ G7Ä¢³©íßVÝÞÕùЩ嘲ü5åº"DˆæÍhB•m5Î$¸8ïü  <¶¢Uò”Âl#ïýÀtîÞܲ¼”/!?XöSšæ$iMk¦¼Ü»x›Úþ‹hÜÙDÙùfµÔÙÇ›# ¦qÈ}Æ–å=ó17#b†&slÁ`û/¨—ÿ¯0„û“H<·c¿B9î¥[wAÿ)†–>¤ãä‚wg¤ægͶŌÇMj×>¾?…îü€YïiD‹® u%*üvþ°ê—›Ó-ð:¡t­Í ÆÉgZ‰ò2 Nß õ7«1*§Ùç_Ðwzµ.þ]i)¥ÞÂ-õS~+•7ß{£ëCd•G²+ù«·±Ä䮸Û8Z”e‚ÉPìÇuÅvÃóõ"îuâ››ãb»ëòˆšê+RÀ×\fˆŒÚ‰>ˆhÞLYu½ØŽš£žPR°¯v®Ù±Öªsëz5[p?Íâ­3þÇ O<ë#Ư'ÂtËZÂn‰7 ú†¼[½x;ޝHÂÑVöŒëI…gìH5f% ! oÊTõ‚AZ»®Ê0¤íº…Ìæ6&Ú!Û~Mw<Ög&&’®øŽšðÙï nüLÕveH¿××å_d'ç_3‰úr6½uûi$ãæ6UÉü56sB'6ïZu@5iC‚fˆQÐå‡=D¥KûÒ~7à~aô‡Ðˆ¼l Å8ì—ÞòoN$õƹÁˆÀòÎ.©•˜R›xêßÜíÃ= ¤IÑÜ>[³ßÝ®è݉‘VÍpK‡RŒk†àíÉvÙH}ª¹-¯Â|: ¸|ánä¢Õ»Çr‡Í»¸”ªŒ]†}Çðh4QrÞŠVþ…ªOÕX€ÍHSò1ð˜ù`W9 kÌö+Ø9¢î7œ uSv J)W áR1xHâU–¹ð9Ë—ÃîÉãdßvPäF<¡1ͱNo_Ô0½Dª»Ê…¯bdÝ"&Úh¹³‘î}…Ê÷O¿ð+UÌ649Ì¡SR{á&Óm¨¦ø=ThŸîtz$ÜÄG¤˜É8Œ$)-¨±LŽ^Áà{é7*ÞØ í$ž½H^Ópv%ò—Ó9wÔpçÄâ·1ÞÉå¢ú`ò°Ÿ…™$DȼÁÜ?bÍL^*E¥_Šè<”h“~Šåù*…K¯¹?š’ôVVª,}û&«ƒùøL^Q-ñ[y«ÊLa†¤ê8M²C Õ—àËpOGRÀþ¬F¡ 'nü×N®Žàõ˜Ô¨gí¢žà]ãÞž2º$Zó“>ä81-ΧN¤dŒñÒp¯ÒAäå¤nÛÌ(áÆéqU¥wUÿæe46hCfösàìþ¹=~¤mÛOºr…w†`ýý•þË©|”1+D'JYõ/²ß_X%¯™˜2íÙÖKFp Fw3`#ßk"§'ðd•]áÑí`¢\($ÄoR´Ö‹œÏê*^.œs¯ ø&ÿªz+8àKdöERÚèGκhâ`ì|1xâh˜}q¾kh ©3hr°oq7¾ÈàV`ˆúÅÆûUðó@QƒÐ¬¼ZÃ=úÍ06rïW¶\=¯†§¬ùõÁwHï3›rfNÞ&NÌe–F "‰J°ºÕ»3Ó…ÍKŒN´.,¦ËÔõ #Â|^<[³•Þ´>?·ù1ɶ¶SÂÈ>¨=’R tW¬N|)µ»‚Ú{é_bAÕ4y„åg‰×­S¶*ŽXuZàÑ’t¾ZmóÆ*½aÇ¥«ë F}€ˆ¤ `‘7¬~:î­ø'£—yä|\6zj5{›.p‹c}TDù4£’¦À­_4Âuª7å8Ríù=õQÐüÉ˼Lü¢¡a¹$Z†wL‰Áv“Ýbfpcšs~¹ °[#OH­‘åF£¬Ûq%á¨fàÍ÷±­Ìy {‡í.¶Ù3é¸b¢jò¡ô~­“c¿'D#ή¬¸›ÌðITgx5¸÷^ÛemϪâΙ×)<­°ØeË‘°SAltcZ<øQ¯×âC™´Óîy2KvQf…+QE8Ïf”½É’¸âˆµB‡iγØ¸&6H-¬+jj§..·¤–iÏÏ#šWÒky?}ëPdi‡¬4YØyLóz«>Fî–Œ„“ ©"ß;.‚\íᎮfSš²†vÙ¯3wœïÔ˜‡#ãó~ÁdL“Ö>ŸŸäˆúð&‘ÞåÇš 㻜ï[Pò«M|Îo~#. 뙞%C³Œ¢ž°G¡d¬-rÂ7Ÿíw+ƒñ«§«ɮƤÊꦯ5š)òðú$,%µ‡/K}K¾5D"\ƒç.!¤Ms|yš (:¾÷ø1³Ó‚—üQôÎÿ¨Îˆ3<ÞÒ¹›©“jc·^£’Áè÷ÚÖhÅ¥¸Øa #Ýë+Þň à³åR”!~Ïl«‘€Å=ÜT)“C(Ëå~©$>¯Š§‹c²Æ"®Ï¢—³¥ÐG}kÈm`ŸPk }-ÑÛ…‰¨E"„2„L—f×Þˆ(Ök'_ñ”4ºÃÁ\ Ø§ÍÆç-(#õQ6·V ­„ßW<#YÓhK<Ò³ƒ”ʼjYøDs[=ðMâX±~ L´ÒžO¡K¸P«|DÉ©]Âf”að@<úmªF.ÿ!ÓËãG9_d0#îF‹Ù»ÌbüƒlÏF2FÓa&ý°³š¥#"gYLæÂ&žG]4âä¥Í5Êϲ­ÅXG‘±Ze+`mJ= }L“Èc›>4‚[ùWgå4æ@g¾Ç®u÷ýî¡À‡ä}kú¨zà»·"zü™óFå o1zòNU­[3.S…ÄÊ=ýn^´·#¶¬|àrÖÀj±y‹=˜$ _&E–§ØP2~TB+Í9(ôƒBvÜá±0#È‹Q‘õ´ÂfywháË\gÌ-u q_§üm()ÁÁšàCR|æëühÏV endstream endobj 178 0 obj << /Type /FontDescriptor /FontName /JSLKNT+CMR9 /Flags 4 /FontBBox [-39 -250 1036 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 74 /XHeight 431 /CharSet (/A/D/N/V/a/c/e/f/four/hyphen/i/m/n/o/one/period/q/r/s/t/u/w) /FontFile 177 0 R >> endobj 179 0 obj << /Length1 1938 /Length2 13625 /Length3 0 /Length 14822 /Filter /FlateDecode >> stream xÚöT\ÛÒ ãî Ðw‡àîÁàÐ@c»»K€àî<¸»·@pw÷ð8rï9÷ûÿ1Þ=F÷žUµªj®5kí¦$SRe1%Á¶NŒ¬L,¼1yÕO¬,v&6$JJ5“5ð?v$J  ƒ#lËû¯1 ‘Ó›MÜÈé-Pl u¶°²X¹xY¹yYXl,,<ÿ ;ðÄ\@¦y&€,ØèˆD)¶sw™[8½ÕùÏ#€Æ„ÀÊÃÃÍðçr€ˆ Ðdbd 7r²Ú¼U41²¨‚M@@'÷ÿIAÃoáädÇËÌìêêÊddãÈv0¤e¸‚œ,*@G ƒ Ððe€‚‘ ðojLH”5 ã_U°™“«‘ðf°™mß–8ÛšoÕª2ŸŠv@Û¿‚?ýÀø{s¬L¬ÿM÷÷ê?lÿ\ldb¶±3²uÙšÌ@Ö@€¢ä'&'7'€‘­éFÖŽà·õF.F k#ã·€?[7HŠ(ŒÞþÍÏÑÄdçäÈä²þƒ#óiÞ¶YÂÖT lc´urDú£?qÐämßÝ™ÿ>\+[°«­çÈÖÔì¦ÎvÌê¶ {g Œøß1o&¤læ@'' 7ÏGÐt3±`þ£€š»ðO'ëæ7Þžv`;€Ù  7È øöƒäéhä898½=ÿíø_„ÄÊ 0™8Œæ [¤²¿™fá·ów¹>³¼ÉÀòÇç¿Ozo 3ÛZ»ÿþç3ËhË«+*ÓÿMù¿NQQ°À“‘‹ ÀÈÆÉ`eecp¿=xÿožÿîÀØÿiU2ýÝÝ¿2ÊØš<‘xÛ½ÿqù[4 -à+(€ßô Ðü#]N“·/ÖÿÏCðç’ÿÚÿ#Ëÿ«üÿoG’ÎÖÖúiþ øÿñÙ€¬ÝÿŽxÓ³³ÓÛlȃß&Äöÿ†jÿhy )ÈÙæÿzeœŒÞfDÄÖüM猘ÅÿA<f‰ÿ"n6³ô?ˆýM¨ÿ ·,òÿ ·, ÿ ·,ŠÿEYÌJÿ ·œ*ÿ ·œªÿ ³Ú?èƒúÏ[=£ÿ¢?ö”Ùô_À ü/ä|«avvø—ÿ­Žù¿à[jпà[¿6ÿÀ·d¶ý'Ù[aÛ·Cû—ÿ­ø_ð­šÝá›@˜íÞÆü¯îÞ^6Ìöÿ‚o4ÿÕë[3Žÿ”û]€ÿjà-ÜñíJùgÁ[ §ÜoÝ8Y8ÿEÿ­'×wøFÁùÈö¶ÂýOø?š3qvpx»•ÿ¼Þùüç+tš -̓Mø‚,kƒÚî«EÞ¹2îL°q \F\#hnKºì)ˆñ?\±çG.ŠtÍîF>¬c±•¼6Ziá±Xé¯y¥Fòâ-Õ·Ášo1xMb <9~rfÛ•ëìÔ1d·55Ç;kRr½ž¡Åg°¿Ø™Ë8â§jª¼ûfqOÝpÌ„5 Oðñ#; TP»HF{¥hÈÌl‡ …ã¥ðÄI±äÁCjÿ(çæÀr$h#õÝá!ªÜuÆ¡`Ê~‘œá$`†r»G‚à)Ž&àº-ÈŸÆØqLUˆœ/Sf{òRúò4S«ãu*6ôár=µ¾í|«–¢Nû¶|¼¼UäÙî 4G³Šá ‚â­ºvK”ð*¯åAØ•“^#´û0òYKŸ¾Žz`+µf@ÃôÏ ¥‰é ùo% äæyf"hÔàbÖÅ mþoÃ¥ºGͶƒà¸Ê[w@{ ÅÇsb=â×nëpEL_TPQ1jj±BCR*&;…I”äÀµ­t0Y÷¨ƒÚgàÜ {C^' ãZ¶9pJ·´¾…îC˜*V߀Ok€Aã”Ã|¢3ØÞšy@¤Tk\Ý™·þÓRåµý°dk¨I¯Ë[ïªíìÓsK¨Òhîã|ºB;Z¼5z¥1k~É5Û DíÉÈU¼+ëø(¿÷‰;"ME‰À¿Åšý(R¹ÜØ—CxºÅ•ÓŸÛ®ÐÔŸ—CÕÊú»ãt–·//ÿ‹ƒÈô­ Ùè}l´ð7«Ú´4Œ@¤Á¼ ˜_!dYíÏ‚P+7 R¦QøFfRÞj7‚;uûdðûìas#+?¡ì©É^²:¹¤{~Û맃¿"ŽæñX=ùöJòbZçYåÞ7#õ¬ë ”žq 4Xr»ŠGßà×Áý¼JÛÃPE™‹œÎ<“¼ó¢bq¸×QªÐ¡ 7v;MŒq ;=®Û×26ì-‚´ú»‡¸QÃ{þº"زúŽç)¶Ä•†¤ é‡$n òÚ†'ÛA´íŸµ£òjãCé!‰ãŠ,ü}ðU)Í Ady·­T–(2T@„q#\€í™CŸ ]ÛË8KAv@I-LŸëE5çcŽ4^¬Zdù$R° £]¢fcÂÑdÜÇ«¬@Œ3G¼ˆÛ¡Aü¨> ½XW…ËÇFæÏbÍ0s¯ÁÈHÛ…¶UÐb¦_ÜÌê*‡aÌÄ‹Š2hfÀ”#g#aßÈ>†§b~ZÕIAѧ:Ì©e.šÎ% ¦Jfž*A…•Hþ<µmÈ"Ðÿ2Ým¤,}ж9†€ò‹ó7ćðTÒžÆÎ­Ù¨À礪Àå ¢Pí%rp·LèixÚnp8Ÿ(Ø­ÆdE‚UšÝ!ò1 o—Y³Õ’\Œ_‘võ4´ÌÓÚ~T:ÍJŽ GÙˆ^•#;k8s›ôéPÊÌ!¸ý”>þˆ8¿õýLö…I%v÷s ›ˆ†+0@%¬„[®µë;]Å⨔¯% Áì¦ä¬Ë`‹š—¬^}[æ 'VÂw·1îï:[nu°E<ïš)½•û1¹ä\ëⓟ¢Ä ŸŸÏ奢DÜhÀpgðÖ-)juóíPû*ßü°5ú¤_ø;Óam×QÓ”q™..^lXc`´c uH¯h¹ðz–l ¦ht¼0ROùÖ&xðLZq¤=Mé>M²kç”#“M¢ÊB h¢½89î#Üý¤‹kÓÿð`/xþêZçdUdÊPeš7iç”Ãu)Ã⢒Ñ0cqêÔCóÄ ò³Ž’Õè$Iã ÿ+´O Ty4©QX¢åDa´„kÑáFð+Úr…q µÉÝCâ©«˜[œÖù-ÃÌE¿'?ÜBÙÔ´Pœ´Ëî}F'ŠÒh@}¾J)fù‘t¢ 4Ý-_h푽¨È›œgH}ݜȼß&…Nï$ÛÛ7v’PW>ì™ËEc´5Uˆò' Â?’WÊ<ü¢#´ç?(8,S»þÂfðd|ŠÙ"ÁmÂÂ2¢â 5£[ŠêÈé 8ê É}¿±¶§À…JÄy·ÈߢXo÷#N=u.-Üx«øáÀqö÷Ïô¯¬ð|^H2çÖjƒLhâq6= ˆ+z‰ãžýâ儺ôÑaìöÊçQéÖ­;C´1)ä8áÅ0^=,nG¤‹cÈàÕJºñæ5š~B VT>\¶ß§Úr3 M™;tµC,J=KsE.;Ì—JÈz¨D­Âjï£CÜ`06¥ý7ç¿ÚmcNØÞî¹)-Üì¹E>t¯ù.5ª&P‰y¶X}Ã:Šlº¤½©ŽâD)ôòQ&2¯^‰’¨Ö#«‰/õ¿æãÕ=8$iØG“„h7•!;»ö¿\æïñô)èiâ:€8 ʉ˜l-ÊšôáYi'ûÅÍeÐUôó÷u4q {5Ó ­{Zs’ô~ÊïÖõ=?T´ªÆ\ªf笥-wMÌ_¤™46œõ(7l÷Ãá˜'³B0š5ÒøiZ‚„½xó§ÖRÂ(!9t¡e´:ä GHÄmyL¦çq*w›Ûµûè ýèlJ¦¸šäA©Z²˜™k¦l~OîRÓÉ= Žwr|›u¬ÄEoÙV»H¶ ^:òòuüþ§Vdjã}Œö€ïN ¬R.À–f¬ˆ”ª¦­-ëR£¤kå|h&­~ÝK©×öj½;˜øy%#‚Íƒ‡-w›¿ã1wÈUX¬n³wÇ¿ÜTß"%©Ïô£õO\蔇˷¿ä?ñŸ'ôÍŠy«¦Oª‚Òºì׌GLžƒŠW‚ðÙÞåwº—ì¿ Öx®SZòq¹*X÷&,'ìüاÄ+ì‰YWp½:øR>ê¡Ü¶âT"–Œé¶Êîü¥lk󲑞#Ô ø6ãøÂ¨”ô¨£<•_èc\ Ü=O:‰ŒXмÀÓö’uF‘ÃA±w'ˆÜvölÓ†?¶\B4¸I~$:§µ2w4?¨AÊDݧ$6bû}”ü…,úâJ‚‡›á“4Qþ޵aœÂÒûS¸<Ñ/n‘Q zº…ןsæînŸDä"˜±9EMaRò/ìÂzºNÑ•šL'ûLYŒk˜ßÿâH@½ùu§ÖacÌwzº'§¡õ³!x¬›œ§‘3Üö™g¡xc P‡·u¸‡ßÌnv<ѯ¨6ÁÔŽÚ{Ðñu…hTµIá¹Íb†Ëˆ?ÓƒÀÍ ªS¨úÝ1¼™ºd@ª…¾”D.'a!£xi–ÚzªÒUmW@eº0âøë¢¶©ý¡5É€÷ü“°_…rLp'1m6‚©P ªL¤Y£& Tªè4ßҰ͘=Ý\Ýt¾rëj™cá‡& iÃPþü,? 0y‡;›’ñ EÏèTfaÖ}ÕFÿþ‹ŸÖ,!3b)yîz …ËË®WqqlJSmÎ dßAü¾§µ¶e•3q¸–YŒÇÌW<˜`s¾Æ3Ò”C°¥Qç5­ùJ¶Né^ãÍ,ýßO&jw6úM:øQ[Öã(qúC7‰ÐO¾=vG.‘%çASˆ/‡œÊIU^^K³ñÎ {l_ÚN/ÓæJ|µ–ýáüN»/ÿÞ=;¹Ø¤‚¨ÔÙBÉa”ÄRª1ÑÕÊUQCŒóŽn½2 Á÷¢‘#R™A6HŒØâœp= 7”.ãk¥üÑc1ð㺨œáǽ²Üœ¦PÙ¯Ò3Æãx éâôÓwû‹t"Øt:äžs`)EOØ t©éªÍè(ã9U©Ù™!FŸÈ~V*¥F3F/¨1­WÑ>¸’qÑ<ùI´|šÝÁŽ £H|‚¨U÷{óKrP£þþÕÐíœ=ÙÍ@Ã2&:Ò܋ʤ¤ñ_{á²(Q¥i^=ÆÌŒRóœ¯zg3'pÇÝ®ˆÊÚIÏ}(©íwiCÚ6%>õ…î…O]ÅzœG‘"mátê³r œj1UÓ‘4ÈP÷Îdæ5þ©è‹,ß™QlÙ¦Ârz…4+c —b-kíI­D§ ÌØ\š‚žã‚òP¾D¼œŒ&âŽò øêM½ë]±–Ñ~Ï`UÉñêÎ";úÕ,d”ùéô…1ãQïr&ÿ]}ÜÖɉ 9þœÀôuÔŠÀetÕ°UîàÑTUD^‘NlÙ¶èK-/Ï\Ù¥G/â«ÃÑëäHJ1‡—#îEüwøÉ™Ö XßQbz)¾<Ø2kÆpð®÷W›×äëDöpM¾/|²C9.—Õ/· ×ªŸíëîÆòç î¸[(?F{3®m9Ñ2eô!Ã^0‚4’KðÜpt“ªD–i§M¿XЙ3ü´é±Ã!ÍÄÝÔ£wéµ2<Ð$~Ø…+lÐÌ&±i³­dËEñ‘!«\btì Åš¨'HëkÛK˜“‹ñ*Ôc•Q…ë6² +`¦Ÿñæò|vúŠ*p/ç2Îèá*¨NïÑ wL üŽšyg`ãT×¾">ku.Z(6:1:¬%ØÌxª=hFo[£ÖK8åš~} DÐðbÁŠÁ·gæj0WôÑò,ÛG&Æ®6¾Ÿæ×#óœ¾7¿û-ŸSï“à—÷ÈŽû2„IkÖ)V9$Ÿ/Ðþ´¬À’¿ä@9²®vñòû轄ƒ:”U|Ì^gæÉhS6™KëOy.­¥¸­tÞîfÛ ¤¹ ¹´ý³fŒuDå_Ò ®ïe>1ݧFrÈëƒcæª,~‚L°oï7§äf‚,ÇÉx¯)Áž6æÔ~§ÜÂñƺòŸfµ‹uï¨á¨G `ÝW°;e5¢ šLÙZ5w†—áŽÃ)ŒMÐ~žŒé6XÑìÏ1@°¼?¥Á{(›šhå´’U9;Ev~Ò}Au>qÁŸÊеÎOHÕkXŸ…9®…3Ûë¢_ýkÖƒ‚7ì…j†½³—Q Ikr¯Å[pQîW=>â)å¨~$™ò ˜)?Î¥¡5a{Ê{ þd¥”»JFîÉ1ò%jf÷rÙœ‡ä:pœ ߯±Î;ÚSˆáJÄ øºSÜ6åUÖ¯)¢)é»`sÅ‚©A‘¶ÚbE·g^ìo‡3ݹO™•ù:&"a¨² Üvy™G-zÂdèÆÚs>nt¦Äpø5a18̽\JœÆ»/bSDY™¨B¦1ç)÷T—ZxÕŹ$m0x&994û6O-ŒjÌnËALŠÎŒei†’4Ò _õM_A¦ªŒ>óÛ&ê¯Âá œ€ø©ò“Du¢f0_ܯEª“/,Ãy°-Óî_“nû3Ÿv–+¾ÊgÏ<ï·G\¨º c†”ìö#®¨m!ÊBvÕÞ„6Éó2ÑÔ¹>a4ErZÞ ´ì3nr®N¦ @ÀhˆtÏËCØð\'·èÈñµ[öx¼J¦@—_ÿÒ€âêá55w0qÉp æš GÐãù…o|¢Ç¦yï ×S´[ï·ÏŒ©Góáhöç+£Œ~1\n¾›€ª«õíbÔ//Ä×bù\àÁwׄOÁO¡(âìv}Cx_ É@Iü^‡jê«ÒW1Í>kž lýp–·Mã'éAeÁ-šïñu4*-XPÃJ–ŸOYÙù_”v2Am—nS °þHÕÖ…§P-&£K×ÔÀI…4%6«Ýöð™1öùX2NK$ycR)&1ϰUƒw=`lðk³‚bÎ]:®Píd Ù—ßß0è%ïóØqoÓõ}“Ü (i$yóeÕ“ó™Š-XŠÕÓB '6êvãÝ¡íôw0„ öþ<)QOPE0pŽjIV²AnœøÓ&ö;ŒÄG†¬îÓ (£ÃÒ)‡µò´Y¶ìŠž/…ÈsƒóMvJ±*êÅ„]l½’}¸žžwùfFeŒ «€!|´ï"ǂ˷6?®ülÆß)€Àù#)zm·mkžÕâ’3~& †ÏÛ­Eqnl!¥Ó-Û†¾ßÌäQJÀ´ø’¨ÏµÎ"¿áBă–¯±ôÊS4~8 ¹j7Ô‹U‘ÀÀdÞIwSD(™SÎùáºFþ ~æ/S8¤†çü£ˆ>†2TÿéDDpŸöÞ›Œ6pêôÊf û]vãâXëêeNOâá.dpÑoNfé ŠB:@5|NqÒŒTåÕ9ÓkáÃp ±˜‹hÉÀsåâ¹ù1`N¿sÌŠf³’)»¥¦§vØë0o‡MÄv?rHkŸ°²ÂÛÞùÓLJߦÜ:Ü:/ĉÀf*«m¿õ»~õGâ›î¢´á ¢ÝÞ„ð˜pVKÝar­!üˆv£TÖ;Ò@R§¥ACãVD’O> Ü3.¦õ¬ „]04`¥ÛýKeVv/cÍ=ìÓÙLn7*DFb-y~Üúº—T±€ÄYWžË8DßýºÃêMè}"P†çèòFz k¤c–õ[æç. —½ŽX!ã;¤¸gëfìÍÕgÛ›õTüšüЙ>¼; !4¬ü¾¢˜š…ݧÏ{g–Š•+#W“‘ô™K¼ évÀ¢ Ø?¼{¾ §K:¯¸áÿH¦yMoXTJáÛ‰ãÚ/ÒÄ ·8Ž“X›3VB®XUƬ‚ŒhRæ|c@ˈޖQ±%Ͻ©J©äµ±#&I8dÐÌ4‰+fx†ù`¢]uƒQÃ0a|+2ž-ü¢1©’ÝT`àöpº¯€,òÈÜýchQJ›áà&Ì:3ùá6÷rfX¸¹D1ÆŽYËõ3&ûÅ;)q*f 4¬Ä˜„`#º˜•·"(¡Xcì}c:6òûý›!ü_$íÒx‡¢[m‡Õ•_Æà×OUÞÙ+1 âÇ’1PÚ•¦ÊÞé‡Î6Ö®ï]­"|¤9oy6‘éƒøÌ8ú,&FØÖ0įã½ZL+u/äåEò %4ïz/ÛàgnG¿4nðrº81†.ù:•Lzvæ`”û`ŠË,ÉÏ½·w3|ÏÄÔ »ξ:׬!÷ÅØª7ûx9éWˆ tÝUŒº­÷™æË¯„Ý£ c;ñrc±üa‚M/oŽYª<–Ó„2¦ï?¿,SŽoCýˆNìâ×и-ÜÀÆü~ߣªpßçQ¢âo˜ÛLÑבP )–/iÌù«ómcJFó/$oÆD1œ âÒâ{¡«"½ZX¼ÏÖ i)uà ü‘1–zÃïà:ÎhH¤XzlO6éT¹é;…»œ% aºKI§ë~1¬GX|Sü)7m|¬#Ñ¡Hðð<”ÜOd¨Ü…fâæôqs8¤v¥ÇÁ¾­€[d¦£|/T-狌ü¥Ñ6*×½RU—©¸ªG>ù øL?»°D‚ÃRd=z£¹i oxkð ìÃGP¼×‡–柋¹[1PÂuÛÏŽ@q¤´f¤t`ãðó¢íæóÙ<Ķſ€Ûx1[³¹½òªTAgùVk¼báõÜú.Q);äû`Ü|œ3,£ÏØçÖ3•Kj”¬º…ƒLèµb‡⢳²•°þÊšWž!ÜŠUIµ¶˜»2>iÊbƒ’Â"vÚÛ£•·<¦j3Þ ŒmÂCåwóΠ'öÜ…ÊJv|w¦ÝÎé Š{-ÒÃÖÏU7ëRûU¾îò pعô K#¥gZY`´oÒÁ˯ìÚã-—· ež¿ZîrsSAùzÛçÐWàñ“®ó†*’c~uKÚôî¾8=òÃõyö«Øh°®húý³e .vC(뜊ï7¨ÿç=óÐAÑœ§á&6|LM©v`Â,×} »;m­ðNãÓû9³ãæÖQd¼DiçW¦ú¸„ÂÁD²°nGŠ¯ì† çc Ò-0\Ÿä£ï˜ü¥I`cmë‹õ`]½öš›H[±½ŸlîØ¼x—…˜½ß5Ú`5 øÈR%l£*hž…;óϳ!­)&à¹ëAª^Ï¢ˆ¨~f2jjΆo¤78!^®ßö¼}{^î :@µ ró¬WeÇœ–'•]zÊ€ñ>Ñ}}W„¸^íïô)©¼….{µ)ÐE„³mí~?…Û~ vôîÇÒßcO ÀšÊ¨¦UöSéê6WqJîÙÂQ­DÔÛâ´¢”SBñn‘ê[×O¢8ÆÃxUcVÀ#ø‡CX‚’/G<ôûðFƒ¥€5x¾ ÝþH-ŽÝm ýKwF(Ϩ¥ìL°iM@¨ššQp1œyææqØö÷O3Ô…Žp’‚f³Øs¶N”n-²¹–O^t(úhìÙU ”ÃÒhrSùùði¼‚°ŠÂú‘àsÞÝù~i_ßÍ@()ÿq©óm©uÛ‰~ì5-†wk~8ËÑ­Ç3vtv”B˜¤½„[¿Ü(GÛEÏZl@6´–qàÜ÷Ûnß÷¬ÆAŠ;üУ;N¥Qø~u¨8Õæ‡5FÏ»%Ò%#É+ß=g_{4s.?«m‚ºæ ŠÊ½ka†Ä×ÊQM‰¹{?ÕµJf¯ç¾Ô¿;ˆx Ù¹í4iÞ:¦Lƒ~•=PñÚ»ô£8)ñ6®ëÊDÇDÓ芃®×´8¥û ‡y_ý¯ ô²¬ÚwìéŠ#1ýÜŽtz;Gòuë&¹¸ìÁfå«5evÀmԃŚÌ]ºmÜk¯?=‰ÐáЬ!­ã9ÚXã9Û‡Èû¹Ü3öçÏ„Œ«ÊÕ™á1÷žkQ/Ý7”" ±²tdòºæâ)0/Y²•ÕQ.âa_î‹5 ¼‡©rÊ?;lçs’¬mŸXí×'V&ô?›åGüj 5¯sæ©éÿ~¸ª«âÝw·¢÷ÞÂ^€ÆA×dÌ—Ñ?P-n‹­™·“o`¬$1;«6±×·Ž”:¬¹×OÔM¥lëßdÖP¨ÉeÎÿf‡…–¨îµ [ó°—§+,µªx¨ N©PWQüʺh8-:ÇYCÛ²“ƒ¼ ßwÙuéu·L!B?0GR 1竺ßÛ–¼U‚5›æwÊBóŠì'ј˾ÍÔ!@™—J_¡¡â“¥ ÍV$8 :ÁÀ³?ñáo7 ´ìçC`ý|Oxù@dE®ã²Äµ)ÅÊb½ÁÔwS3 A(Ž&Cß96¿–üš®Uºñ3ZMÐéäMŠ´M[£`ïÉ*?õºÓ”>* …ã+DÞý<‚C·±CÈ´~2É áìÊ¥¯˜®IÖ? Z}©¦Ê‰ãŠd-gÅ=‚†å*ínâð’1ÁóÙ³*_£(J¤EÁú$–€šº­¡pÚ‘œÈƈc°JTVÚ Göô‰ö‹Óegc€)नäzŸ¥ãG×l˜,/3ùO²x½6so­/4£X͹هqžÄ|[yUö»ÐRt ’<‘ŒûÅ”ÔÂãõøòD¦wœ[ßmHóëØ­›mzCBv—²Aʳªú±³•RrH¾Ã‹wÎÞlnå¿ ÁÆOhuó´ÂqÁ‘õVÜ«Ó §äЧ$ýÊ‘z¯¶er@þкïŠã-‡òuåP w¢Pïv´®‚ÁM\Nr»kûT*ˆ/Uôø9‹C/ÿ6Ú‘¾_M7‰EÞ>;—3ßKQáRÂ*Y¦÷ižÞ, È…°_™2##†bóýKY•Ïf ™dÌá˜À×>+RÄîJ8¼¼—ý?l>oœ¶  csC¿Høhѳ¦Ú´<16¸nŠñéiÍÌ–îòfâG{»Ò׈i².ï¨þ˜õ¿uðEê±J¹Îć1‡Ò¡cÁž«õtž]™ÆÊÿ\fAÒùn‘â/FÞ<ôå÷IßÇ'®Ï›¸0±ós_ì˲º!Ù 3Bá€pþ¢¸ý²A 5ðÀÿÃËKÞ´¸M·X[–7Gó sxJ¿ B¨ULße§ÎÍ nä¬e 'êJÞ^³Ò&Í—á COW) &9^¡¨Bq 5që994Îj8½KÓ€[½6Œêt*²~`ªfÄAÔÍšV=z²*‰Ê-pry~ôoœQ¥þéÿ%ÃLäÍຶ Š`vJW×™q6grxåÊÏR sî—˜(ãTçëÃiŸÜÔýbéÐ#§åÓ íöHɢŭtØŒ; ö¬>óð[„¡eØlä÷?‹—V}. á.U@#XURÏ L7à®=‰‰ôòÈ„˜ôyðôv6Ýð?”ôÑÜЛ ö„¨VëòØüLT½]qiMðpÑp&®VÞÁ”b²Z¢@¡ÚÀO:ç<„þqxöó¼ñx31ʧ;–Íz~~êº]ƒ«—MV?>ÐwFñÝ[ÄҮ˽°”‹ˆý±ÖŒªWŸsÍऴ(ä0e2Œ‚ªè1„ªCñÇÅeòrxt,Lyk$Ñ]œÅ|q$w¿“ðø8 wjÑ¿N}Ÿ• ©ß(­_f6E½_Œ«¶D¯l* ùBÜ{÷¨òºrÜäTuuw¹s½ËÉÿYæqx8­ƒÍ28+=άHoPß,¶Ž‘Ê¡]Dôª|aè‚ÜtXûÄ]™ð¥ÃåÕL#ÎvEq!iEmždºÁ?†¿#Äqå…ÒãUrµ™¬ðBøo{ˆ¶ÚX¸¦Ó‹Êg($Fˆxµÿ&˜û!W%r À"¤(¼¼¨OÍösG;._ ´;ˆí$šŽ™çã¶I`ò¾'&³…eùå|_èŒö>Eœ‡Ô¡&!Å✧Nꃋy-¶ˆeúi;avyÍÇ;SÊܰe{íD;¤ô¡«Ôq§»[|½nߥTâ÷¾xW¸Y[gVSí•»K¦ «pKqM-MÃÓöËM_Æ£Þþ„u#}ù]Û´f[dI3™¥$ÊL¬ÍN¯Ÿ¨¨o–™=[XhOnkµ½¥ˆÃN 0ɵ…dŸÒæüeG“Õ2°iÄ;7“\ëqÑÀãÀ&í:nÔFspãÊh‘ãõæBä"„`}-ÔÔøÒ¿{aH(¡À¦&$ìßSšCóBor™cbQ®£ÏmGÄ œðTǬ÷è©Æ‘O ŠÖ×HªõkárØ­ûeƒ,1º'4½XÛ ˜;Íçv6†Mû¡1ò1ûwf Øk}£ÒÀ0r!»pÌÖhFyôã\¯܉ ¼…žÊeh™‘Ï+}T‘í4yç¶Ù>RMÿ8郷Âpš6½¹k裲ü{—¼•),¤ÔÙµ€éá£v ÛQÂQgÈWÅNØUŸTÜÁÔÕùq4Íâ±Å =KP×ïd£Ô:¥O›¿ÀïÓ‰éýZâ´wð¶ÂÑÂМƿÍ&UøZ<ŽMhû\giÛÝ+††hy_ Lʨ ªîÖ&SOõD½ŒA†p²ÀÉ xÄz¦Ük%) ¶¾Pã.a&C»Qp.Yß3É$²2‘Ù7íiqgåsqÙÑ2:†•Uj#¯ë—(§ËƒK(ƒjLŽ`¬óÁÁXZN¡çÈ©v>¿'—)ÄH½ûKøj]oè? U™)ñ„Kͬ¶Ñ‰ì£~dß4÷RöäUd_<¸¼U&N Q õ\S¤ •Ê.vµáããÊèçuÍ"#?!,4xÅ9ÄÂ-e{v0©‹[ 6öÏÌçTel3`õ׫ؤ–iªSH÷÷€—亟 Ç¨2ý»ç}öQôˮĂoˆX¤ûÑEV–ø¡¿…Me5‡²,…úý©Äç§O±äÕÁ—÷ 23m(“LòfÞAEl¹î=Ž¢Z³ û]¦6Òúö/g]dÊ ÍèýyTæjMâ~£Å¸ÖDßÜ„¼2gå â“­Ç+8çó0(»«ï«“"-Ü5ê+No–ЧƄ |œ ŠX¶rÒ¦=ƒ[ç7ƒ£‘zŸÆ2¿/d àñ©ùMŒ^ÿèD^guØGˆWÍžFŒÆÕ°®ÀÕ­ï J›«EØ*Ï4Énf…[p.·a_6ÝáöŠv©Õ®Y|†ãfHœÉºæÍGñæ Î$ªÏÙcù`ج~禨^À ÿÁ“8Йwjó¼w€éÃÎM£CŠ-äanä’¼H7QÚŽI­ä·½ nA›ñkŸ/4&î$Q-‚<“«Dª”¹ Š%q’0œH?jM¡]O­½úøM©·ž¸É®ÏiªCXªáž¦ÊB;6°*Þ9¬RPnöR¸y‘NÛJÙ0̪˜Ê嵘äÒï‰C᱘Öä°†·Õzx×% Q [gûÊ~ŸGócK fÀsˆxAûU€É‚(¬ó½² qòÝY¶°q\J˜·]Ti«Ö„tŠ¡(ºïEÐŒaMGl+¾,…£ËÌõ¾ÌøeþÏŠ™ß`úŒ®r»HïãÞ”+ö Ó^¿æ½Jgô7öÍMâjYŠ1ZÍ83)%Ü€W¹jC½ÑR1Z§BùË›—-åÕTѰ¨’ü&€«{ 2•N>7gÖÁ`–‰áÖvÊiϯ¨]©&^N".Vo¤_™~›o‡èÄùíqVG5 Xnåà—â´Ñ¸¦È]›Ã\³­ª5…m†lb’2ÀÇÏ[Ž~ÓEƒ¬à¤ë)DȲVÙýǘt,Ùòd®²²&赆ãk#\6ÊXrÕŠ¥ùèCFA¿“;Ç/›Å&YˆÅO© ¯Yoº8Q9hX0Rßù`L¯ É(jl—Ïך`Õ‡UÀ„,JPÃ;@ÊRÑ|ü‰êÙ”&/Ì.†€¤E3guROÞO#=2ßh¶ÏЧùï´c£ºnÚØ’d+l4’ B$õ ¦R"[7]êYÅÁ$!¥ ñž·ï ÛÁFiXŸXöUòfiL†¯d|ÆRTYÀ€2¢ýÊYœ·~ysR¬£hÈ–ãÍ»ézóž×EÌr¿… ¡X Zâå§`OI?b8ÙðJÐÞE57ŒØkíÉ!$ àEb|ýäøëûòR —+[ZÖÄš£ªP ½±–…²iK|´—Îû-ññÚŒ,)Œ\ ýê‘ûC¡2¾1ƺ¤îÀVBxê1×êY¾Ë¹èBKƒÞ™ŒêûVØ’ e-Ñn¥OÊ)©¤¥ßìÜðN‚T©WÜö­iàqÎèò¼}äÓÈããòæÁ›qO Ç(û6w?æ”'9íc—I=òx)÷S‹tú3 yfsìžD'„r [£bUn#âGrCRM$Ò±³nºÜ°ïêÃïçªxk[äãÆ[@|íuO·0púj¾Ù…8»/_sÒ¤ôr(ÍŸE±d ”ý»šÃŒU—Â[¥ç&a\«ŸbKW6š G´díÒvÅ£kaÌ»#Á1¤ØhÂöΑ±€¸h í÷æ~àlRtÓ8Èú9Sš£ÞxöFò« UAÂìþ™ëõ9‹z’lí²z5*¦‹nI÷íhÃ"âêó1ÉY-oÁE\ѵP[r‘Sk¥v¿ÔG­iÞ|wŒ; ­µâ³;çÔ€82·08žÏ¢zà1SÄ| ˆÊÓÍos(¢ûöž Z;|ØÓ"†Ëñ®˜n‚}6φþî¡0¯Ó4y•W`ÀëT•SýØZüt¦^™óàÀ¼‰ ¡¾•j¢Zîw4ÃÖßFh&q´·^Ù´±ËŠâáñÄ9'7¶ T ü»GØZ-®i½RM^cºÚóê°<“!v½á­ßi™˜Öî”À³†£–©& %7$¥õ(ZËz.äÏíìOg„ÖÂ0ÂV½X-%k°Å±4ûN§BƒŒ´FÎ(ÖO;*xPÌëůØ'Ž]£gÒ‹^D˜eÄ/^ùZOЭ¿’x7vj—mSPÍ-D~ÊEÑìZü?RÖó‹ endstream endobj 180 0 obj << /Type /FontDescriptor /FontName /IYMUOQ+CMSL10 /Flags 4 /FontBBox [-62 -250 1123 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -9 /StemV 79 /XHeight 431 /CharSet (/A/B/C/D/E/H/I/M/N/O/P/R/S/T/U/a/d/e/four/g/i/m/n/nine/o/p/period/q/r/s/seven/six/t/three/two/u/y) /FontFile 179 0 R >> endobj 181 0 obj << /Length1 1469 /Length2 6425 /Length3 0 /Length 7423 /Filter /FlateDecode >> stream xÚxT“ÛÒ6Ò¤Wéé5ô&½÷" !„Hè½HéA:Ò¤wéÒ¥*(éM@ù¢Çsï=÷ÿ×ú¾•µ’wÏ<3³Ÿ=Ïìd…•Iﯼܬ‡!yø€’EíG¦@(Ä â±²BPðßv¤7’`³û´"à¨xOÔÆø½u€Š¼>ÀÅð?ÈâŠDð! Ð_ù¥A³2ÌNîâ†!x¿ö§qƒPçîÃÿ§¹Î0¸Ìïï•=fgÿ‹†‡+¿ âæVWúƒA™ðþms#"@ QQØ ö9òÿ*`èã þíümFqðs…»ìQ4À{0êÏaã  Ý=À~ÿéøç O@`!¶` ïßÙQf°ý_kTÿÝ!Þs J~à¯×¿ž,Q ³ƒÃ >ÿ†ÿn1¿–Ž‘¢Þcî?”ÿåTP€{üx%¼¢@€€€€(@LLðÏ<ÿ:¿Ùÿ¶êÙ@þìî?2ªÃìቿH Nïo"ž”Áñgl8ÿ¬ Gé àø·ü-€"@êMàÿ<¿CþÚÿ•å•ÿïHÅ ýíçø ðÿøm\ PŸ?”ž=¨ÙІ£&ößÐÇà¿Zlñpùo¯:Ò5#ò0”Îy„ù€ÂÙ!ˆ7ØN‚9þ¥¥¿›ª…ÀÀzpä×½ƒŠÿˇ=3ênA ZöÛFMÖ?ë*Ã@p»_#((" °qw·ñÁC)µø  fÕìý[â~>‰  8ìáîx¿+à·A 8CΨ>8þrþ¶ ˆømQg‡‡™PXă~µ÷ß €ßó@ü6ücw wwÔÿ–jë¯ß`°7„·0 I…;½ o¿¬‘§õâÝÅú¼Ò`Ú%‚d›{é稅¥:å¦ðÄ®òþHºÞ|YÄä¬?-×Á嘷EwNÈršZM¹Máˆ7èûi·˜ÁNã0.–½Fr˜¨OOôÄÓœ=ùñìõS±¡­ªÍ›NÄ–™Ä.ÀP|NÌ”F‹|.ŸÛ¹‹þÌ”‰e9ljAGênžáa¨n4~ƒþ w¡ÐKýÝgÍ<.sxié]Î@ºÐIfoµhe5¹¯SîHÒ 5EbŽFMAä\±,5™ºÈ%‚mã‰Øòé‚¶ÄA!Å{ºï=êà"³Ò¹=Ë'tÖëÙ†ßù î7'E;òÔ¤³(°VÛ¡gV Aóz1)Xuoµ§á%¥¦Z英ØaBV›÷/Ÿ<ÏJ´L•†Š~y¥ ªep±¼xý0@FÃJ¦§Ž¡Ãä´â1ò€‡ïÛ«~H… c2ìl»ù]ûpOäœå€žb*$Á¤#k·o'±I]äü‰1—²(²VsÞeÍŸ?d—‹©×Ö©*e&'1?Áo,D”oH2g¨µ…–¡ƒk*ùT>xš˜Ìù Œ¾jñµèû—Ò¡ÍÒ©âÁÀÀGw”ô÷â‰k×îé÷|¿k•`ë~Ä/ˆc¥™×iæø¤D‡])œiÜM¸ÞV0 9›]ÎSøidMVh‘gÿüGÜ·­³†Ã<ùº(3htJ×TКõ«÷ôfqto'öz;ØS·¼Õ®Î1Èl‡U%™Ã‹ ñ"­ŠKÑFæ6ZígÍ8î=ïíϾ㠘_H ¯‡¸Zm7èºþ(wSP±Ï?•Z«Ôf“ðÃÄ2R"ø&NJ`3Ñ*8 ãCs´oÄ[‡Êj.R욳˫5ÖƒUÓUr– ñäZ˜{õæͨkag]iªýŸr³F€¤ÒOPž%=¸ò³eªMgô™\„b8næ‹LX{WMcóÛÓð¶P«9–&¶ØÓKqhjüz¢…-<¼›?auÕŠ3‹Ép£/؆à}åõÁÂDÝ eHÇ#æ|©øíÔk+´GÑxò"'™¢ Ò$ ®ÕO™ñ+'Ð) E;tdE|/ÿz” @k™[Ñ)¤ ]ßxm¼¸>6ÖeS–ey¶-;þb‹Ì‡&g8‹&ÞêFyöX—`|}_'‘ð`…¡·Ï¤ïzÛ@{Ñâ.zÑÞ-UTg–¶Ý5°î9Ï áŒïCGÙ –äã*E£44·Hv¢ÞÈ™<2·|½”m뫪(ËÌê^*òbÚ®M}>Rd ·Í²ÙÔ"yÛñs¨#NùÁüv‘ûëÞ.ZÞ–Füw‚hü´ýÖ㸀ȅ.ÚØùOTø.#O«Í®iú ´ÅÇßž-<œ6ŒÃÉÐ_Çdk©}hÕütvژ˙ñ Û-—{î#ÈÔ'µ´­(/û™µöûØ›'¼ruØ@Rc¬Zö³œñÚ‰ó2ä£Ò¡B";Ù¥Z L2Ž0Ó°§}Î:Lßî«Ì?ÜV¨Kûê\÷±û³Á>Çâ̸•à<+1]þúfÏ%¼ -vŒè+Ôß% >ýn¯L˜Z£•¢2<ßç™rü¢'#é!w`BaC_Šr(îÛŒ$íÝ9þÊszÊ]äüSŒk5pVÄ‚žbýWOƒ-fUÑüâ=‚ì¼\Ë|yª„·±)Üþ[5ë-Æ3ÇŸcTK_CÅB5íi“û.»çYïKÿPeöc/‰0ÑstÝïM­8¤öåÿT׸à;¥Õkîß­t‡a@˜—èû Pyßµ1†ÆìÑUó©üàJäkœ¨ºw+ÔóÍòë)-ÝHhgí˜ÚM¾9šaˆ7bL»€þ©^4WýK0¸,¾Ø¾¸ÍËy1ò>Ã¥š§Ni<„ùùDïa( ~þgH}E¯±,¤‹”4Ú÷tK| ß¿«HÆîÖÉÇ0ëyHoƒ±Ëàfú µ[É{ÅaêÄÓÄÃù·­Yw$|ï¶mF).ñ÷![û3"î–Àé¹öÓ%bÜÇgÔŸåêö5Ïɼò[ùpy°F/¹mjfßã÷ªgC•´õÍ0„B.õxað³ö“ö‡¦Ÿ±À¼{ü—„±yb!±\Ê"Òí" áqi~–Šå2,?1Tp}˜&¢¸^Á[Ѧï:Å|àÕù²?Z4Z ?ï×ôÒwXzîšÃ%`EFÊ7õb¬g·_Ë8:ðìÝíõ¥ 9ÔfŒÀ’•|¹øIB[™u•~„.ˆfÝõíyÃ066" ]ćÏ$,ƒnj´Šóx“®À0­øÜN@3¯À¹¢â}ŒÓRPE- èKU®ZE¿ÂèÝ¿kSöXÿ+«oøô}7-ó&…4=BHu`_ç+>ÌéÑýæÉ éÔ(Mru­Váª(ýV»œáyè®;m7ƒÝ+$™Â°—㪦Ý3‘üÖ¹%3Øž%É5º¬Eo>úœ¢W"‰Í&ÉIŠ›Þ¢ ‰Ë9±(ŸäÐ[£Éµb¢ÙƒþѸ‘ÝwÁìô½<ý"'.ìà|ü^ÝŒa{ IofÂG­±Ï„»‡'_­” ¥7æÅG’ˆ‡/>5 ö0“/E^ùg£¥=Àú.b¾k?i³ã¦pq=å/}›…ú=Ó#¢ë¯×‹µÈ’8.aˆ XßHæÂ£çvp•æ©áé–öwª!Q Ëþ6ƒŸt˜VÝ>OGÄ÷•_¥”–v¨eX†4ÈYiAçc¦óã;ÒPw꿯Ϻ¸žhDÂëåjjWÓBn­vä§‚„JVõ)¾v)0Ÿ²I(´R&8Iã=³”Tl¿ðóº[mM$"tQ¤rà0ÝU'üB!s{={O¾´‚t¥ÃíÍøÑãç·Ë“ Ø1 ‘… Uzö÷?à¾>å™}ÔŸ'z¶Ö~—î¥{a‰yâR·ç“/øí µ?žSuy_¨²ÜæÑ†íŒóä·ŒÝ{ŸÒTJõi¼Se43TS›•*}¿²Ûž‰ê#×HG9ÿ–V_´x+‡Ü³,_Ps‡\¯›ºKzîÒ+¦w.©àãa¹1(%áã[æ)cEµíË✩fï>ô¹ÌÑñ °IÁÞ)*íèç+8DGêÔõEAß7;Ë«[FrRi_5>*ؼ5M[€5Є>ÇÂÊŒŸa+岊£Ld¿É¡­Þ¿fkòøy¬¿0ý¢“a’f¿†ôvg¡œ;DXÜø0?ЇÝeñ0Óèkˆ„+“u'z‰~ûâ·uöblÕúÕ»2„èý¥£o,ëIa§B&2ù¾² JûÁÒ:—OïtØÂèŸû¹QÙšrÈ0/ˆsm?ëu.õº„¯Æ\¢}ŸF«­õÄ+y­¶\ZãwÐ&PìÚ½ôSN¢.ê}æ²@½’IÂÇBa¼²åHƒÌ9÷ufqvf±Þ­¦À<Ù7ç_U·)b>N“;9ý!ôâ<Ý•ª_ý2Y33Óv¥”‚ßõôNÃéK:Ãd·N•IqLëŸ3ò$I]°]2ýØ·.šq~l¾Rgºr±B\NÖÌ!bïÇ)ëws^³sQÞ¸™Þ ÒÎÄ:ŸðãÈ– ºPs掌۟µTï§®¬\ú<àX«~ºèWNK\ÂÔ®ÏÃdC|ön9³ßR¨à~=ãþìPùó¡9rrÑAW“î¹þ+–+–7Òä4_Bçrdwìä„@œÄ–Bå4i„;3t3h¬\Újt½4™_‹r¥í^­dÜrwí ® wºÉS!¡!îŠ=EÐ#S÷UÙ/V-ÒZ]91+9ϱ~æX3f‘pÖÎp´\e5ÜÓÖnÅk¨ 'pðdk¬¾Pü¼!¤ƒÖ¨e†¨ó2ÔóðK¤D´·Ž×\êå>ãæ}QY–oô,½Vå›Ñ¥s›æXDwEû”i'XŒLXÁ‘zޱ£¥ÍÒª—rpÆ–è&å0UçMˆ…>©úv õd†bkS~GM²¾ê助½­@rÃj›Ú _³WØ •éd5!ÞK•ÒijJ 'Æ4²®'Ø>“é-äzˬ*Òm¡=ƒ ‘Xç çùªšózŽu:õæÍ˜êÃÖ;QÁŠ8G†”¾ËSö¸[¸§ÓRb¯Cî<F}++ Ìj°·ß¬,±< 0ÀÅ" Å^ ²( &YÕt¶/°9…{hˆ ½"Þ©?ñ\Ùé: ÒüøØ/G{zYHv.þy™ö‰åwÉÇÔRä$žŒ O‰3JÝ W`LÂ.1!‹çÓ[Q—’Íc2,ŒðÝkBPîaœY®W…%IOšÄü¼w“$Rÿ6&Ø=X)ã#]Áµb«ˆÑhEÐì§•w¯Í‡²7^ö§^ŸÞ±8»˜Ï¢Ó Aß Ë×KfC"‰ÐÏ=T}¥4„O'Ÿ3H5yp2­“ºúô(5­Ç³cäèú›b`l—FX’ ³¨_ Pf ýŒû“¦þt8šyxºbRz7äñuy?Ì®a¹2WÎôÞëZTw‰/àYn0rw$H„ä¨Àxu¤¬Žû5IQÓëÊ·×ôb1uFˆÐ¬ªÙ²Ÿ­á¾dlüXE‘kUw‡U#¬>b‘÷,ñ‘é±lþ5ñ ]18©Kªåëóâ¹é;ùÕXÚžŸ9œ¨%akŸÇã°ãýlË1Ë~}ô÷ï?ÕO¤‰r!ä‹}Wy„k`ÞI5‘×yèô`ç'{èV_»@%Ù<á[©F¢£§ÚA/@³’óàøZÙó§kdf™Â šQ‘˜eýÛ…=e[Ddr±9†¯S3ì6ç̬šþOô5¾¼[;ñPŠÈIŽ& 8e ¾é—à»™-iÛ²¥ñTq)wqËâ‰G±A%ÎLZôd&`g¸ê*[’²=È”ù¬GFºc B'AEó¢/ºb2!ίœ‹ Ê:ÐGLªÙÃÞÐSæQô<4*y3§óQ\ nçô1G(D)ƒŸù€–æ8mÉn’jG!Á­,V{¤³Ž…“i+î×oyëÒò‚?’úÞÀ1qnÛ\E‘'õ3Sô,Ó´óŸŒ^pW²³¯™L™Ê}z/ÄTdá÷Çûœôˆ$VO*™³»’b^ÄŽõ/èÄI)XéÇë–% }ïâR¸'TækÃ`iú¬>@¸s›g­‹þùäcËÛÏOBx%(ôùûŠ6´ëÀÁ¹²ó݃C;S5 wˆ÷×1,cŠmºpo¾¶íTXï>œ¼MàÆ$ÞCÒõ”טçÔFQkäÿ,Ó•+dÕNT]þJ€,n˜÷Ä ‹˜± iá·]›ì=Ñ6V¡ŠÜŽq;«o>–±O (kO\ö5ž !#+n[óÊ#Š{ý™Kê7Ïfñò‡Ì)¦µbóÐãLI)ê8çá"bΟ&?` ÂVK²@ãyí=憨Fxï©å>TÑ$Y[œ¿;ºïXr¯ÅLtâþS4žåIÇG¼ÍHã 1Æ4î³7Õ\ K—®òÒÙxQg-—Œf¹Ôù¬·îÕk=­ ŒaÒ\Šža¶Ú˜üîàöSXk¯<À!åÊ,ýsØ4Ç—í¬ŠØŸQÙ Y‹ÁÕý~¼û„t§Ä5)ïùs©º(•bšæ"¿WÍ rìŠOÃ>°Téÿ`˜TÔ:+8Ml¦ôÎðÂýÒYLÿT¥y9û.A søºr²Ìh„£ÔL¢~|Ϭ—Œ‹Õ†æû Y,ËÃP0z ³jºÓóÏXá>1GHOïI;ýDJ3kò7†vÌÉå¯l¹·ºu#,ç¡ÕÞ_ØE½NÖDMÞ(w)i2èbSwGÚgs8ÈyYÚgŽô˜ïîÆ ¨|ÿÊ`E$/äùwpU7Ûsªš®QðŽ'>žïÕ†aóòÕpa‰ÜöÁyöól_Ÿñ¤L°ÀëÎ3"évò{O8úŸÊù%Hßõy,Óuµ.s•X½å#·ÙÛb´r…óû/…^5©A_ÚÑC[±2(›w|ëÑ]¹²È‡©8¼vù˜;<Öw,ÐzFÑ7™3‚.Ø=†ý)˜d> ýÖ?§ême5S•rŸs&“ׯI7¾¥FwöJØ ´§žÈûÝö.c”~?Ι—‚ÃDâjûÍ£›¶Ülæ¹rh¶íѹ¯TKm†ºÏŒ…òÜÝî‘hW÷Rgmü&9,¹0ÛÛ—B©ÐÞáh䣋Í>Vú}Îm~WƒÁËå…·åÌ÷<ð2”ÁI"—Ü} 5ˆ³vòÚ–’o_¶l£ôßМÕ<‚’æ9õŸ¨i|±=©Ñˆ—ƒWYùÈ4}-tÈóc·®×.(•w°yÖÀÆ‚S$ÒÚTp2NrÞ Рñ—BÉ)£ÁÉf™!¨¹wÉÌD]ú[_†éÞ|›LæÒõýÑÊj>u¥T˜²]þ4??N¿·#½+Fšbz?³þüòÝѼlXý³JL*Žìõû˜ÌK_½ÿ-INª¿Ø|"TçêµÃ®ÿšŠž8CÚ‚j !§—íÎ)}g!«—~zœù½œI—ãšiÌï{›e$=ÉÜðÅF}©+Æy7úì¾sA”ʇã~¬ÂÑØ÷¬U¯ÇrdŸ6_˜iyÊô仳‰ÝŸ~ûæSú7B MÂW6|óÄ=üÔh1‹>¤¡ü"ÕÄã°…[·àU¯A·¶w@ì”âƒËüùñ«f>ü§/£Ùr—…ÎVeÉq@3+ZÏH¢ÍÞnåÜc¢SßÛŠ¯S¥¢¹÷-ÂbI ´iŠÎ"=Çëë$4ñ|iɲc¨š¨öƒàصû.Þ4†g4Ô>’Ó¢1¦DÒøÍ{}“‚nxJÖE@x†ñùIŒñi0W7±ˆ‘»££Ïõ>Þ¾:•ÑÁ¡%Îe¶Aœð˜ró÷Е—Ž‡*Gž{ª¯3€†UÖ¯[õånPá`¶zAýƼ-ã=šÈ ¿‹M÷})Jl`È’Jñ¶ oîK€þ-ö¨7…·„Q5ãåN_árçý{™ÝÍä¼®x[Œ5ÇÖb?i€ÁF‹îcQT‡"¸º„f}£ŸØÆìÓÙ"Ä¡38ìT•Éä«Uf/o€Ÿ¯_{W\x·»aav3rF©’rLµJ‹¼Ô ‘“ûâ3&3o¼û]ƒ0Ž{E¯¨³y£úPƒ7ePö^͉·U>;>ï‡âè7Y"R˜<øbhô7îI¾©"eoÍÚUìÁÑž?Ós»ô÷À|Év­ab­uIÿÔʨ$nAt£BJóø·ß·Mäš"UE“æH3÷s’$÷ªY“µæŠòÉóqM",œò½ÅÍ`XíUŠ‹ 7,1Â\¼[¥ç d@ŸJhÖ^ïÃwv1½—êšêÜaÛP™à°ÆÀ ÄJøínµ’¬Ë­G†BÏÍÝw*,A @yŒz%•DÂRVg—o0æJk«‹ì@¯¨,‹Åh—àªÛ:ÿkŒò+fýµÞ‰ï¤È+jeªÂœ¤¢Óx—ÌVÉÆ1Ñ ßÈsϰý¤7Eë®w A<Zž}ztY…TN*´É¹‚6©7¾|qž×Ÿe £ŸãZÏFÖÜåv„Ͳàý_ Xè endstream endobj 182 0 obj << /Type /FontDescriptor /FontName /LNUCPW+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 40 /XHeight 431 /CharSet (/asteriskmath/bullet/circlecopyrt/minus) /FontFile 181 0 R >> endobj 183 0 obj << /Length1 1982 /Length2 14647 /Length3 0 /Length 15864 /Filter /FlateDecode >> stream xÚõP\ÛÖ #Á%¸KãNãÁÝ%—àÐ@ãÒ¸{€ÁBpwwî!Ü%¸»;<ŽÜ{Îýþ¿ê½êªÝ{Ls͹6 Å513{´½„…• ¡¤.ÇÎ`cãdecã@¦¡QCl@ÿ‘#Óh‚œœÁövüÿ²pC^e’ÆWC%{;€¼‹ €ÀÎÃÏþŽŸ ÀÁÆÆ÷C{'~€¤±+Ø  Ä ··9#ÓHØ;x8-,!¯yþó  7e°óñ½cþÓ f r›Û”Œ!– Û׌¦Æ65{S0âñ?!è-!~ ÐÍÍÕØÖ™ÕÞÉB˜à†XTAÎ 'WàÊ€÷ƶ ¿©±"ÓÔ-ÁÎ)ÔìÍ!nÆN À«Àl ²s~uq±39^³ÔäÊ »¿Œÿ2`üÝ;+ûÃýíýG °ÝŸÎƦ¦ö¶Æv`; €9ØP–Vd…¸C˜ÆvfÛ8Û¿ú»ƒmŒM^ þ,Ý -¦0~eø7?gS'°Ä™ÕlóGàa^Û,eg&aok ²ƒ8#ÿQŸ$Ø dúÚwà߇kmgïfçõd¶33ÿƒ†™‹PÃìè’“üÛæU„üÌp³±±ñrð@Ž»©%ðê ?•ìˆ_9øx9Ø;Ì_i€|Àæ ×?d/gcWâäòñú·â2;;À l ˜€,ÀvÈÿDƒÌÿ¯çïv|d{?vÛ¿ÿ¾é¿N˜™½Ç?æ1PKYAEWƒéoÊÿUŠ‹Û»¼X8¹,Ülvv.À»×Ÿÿóßü‡ýŸÒÆà¿«ûWD9;s{ß_$^»÷"®OýßkÃøß ïí_ç ÿgüõظÙL_ìÿŸ—àO—ÿ³ÿG”ÿ×ñÿ¿I»ØØü©§ÿËàÿGol ¶ñøÛâuž] ¯»¡dÿº!vÿ×T ô×B+ÌÀ.¶ÿW+1~Ý1;‹×9gaçbeãúKv–»ƒÌ>€!¦–ÍÒã5‡ ØôÁÞüǽóêÅÆöt¯«gjýz·8¿ÙŸ*Ðëfýo^);S{³?Vƒ›`ìädìü:¯ˆàÅþº«f ÷?Gdµ³‡¼º^9úÌíÿ8Øwl ô¢¿(ÿ_Ä˪üƒx@Íÿ"¾w ñ?ˆ4ùñ€¦ÿEܯ:S{›W‚ÿ‘pqý!±µýÇÿæ@³Á×Ì AÐüøÿŸóèú9÷z{§ù¿šXü ¾æ·üäÁÿ‚¯<­þ_‰Zÿ ¾²±ù|¥jû|]Jà?<¹_]í^Oñ_úW^öÿôáÕÙþÔ¯•;ü£~-ÄáuQìÿÕ˜×ÏÐñ_ð•É¿x²¿2qþ| ù§š×Ú nöÿR¿–çò/øZÛ¿šüjîþ/øZ¹Ç¿àk¥žÿTúÚOÓ_±ÿg™œÏ<”ŠÝðAíÂk–}Üi(2È)Ì,ÞFºá§•…`5kc¸8 ©ÖÈkíy+‹BCñ6âìì€*P3Ä›gôxX†œ›4ül¥6ÿÀŠ@Uô˜ÝgÙϰ_ô÷j EÊ|êAîϨ6FuU¤t0†U»ÿÊRTHc±Óæ9oYõ"¤M,Ó™¼J7 —Cò^ÌqÆ›O>5o …é¿× Â|"ð|¬>¿¤~µI?ÕJz !Õ¨6@)õÍvŒ20e-KôúT;ÄÓí{²"!¯ÖQSÒ[ëzEP{ ®¥¤>«QþŒœ“Bž©9¯+rµ¼‹Èu^ZÆÉSâ’]44bäƒUãâ›[Ó µNV¾‘û•ïªc«§šê—’P‚9« ÖùäÒ "¿4²IÔÆƒâÃÍ€ì)Jò\b¬…ûÌ’d€±\²ÞûZÆöÝS•¬Å#FX^."x ,B6]zꑽimW"F­ÏÎQÞ<ÏÛU Yj?kå³ö“¿Ó˜à†ñòEPJöÜ‘íGéP_{›xeU(âßû@º–o€<­hY^Qð ÁóÁ #làжï0‹}h¸}«zuzøÞCàϧ´¶1¶³+aŽ¡âNi*ø9~aÅ÷½ey Û‰ÑB˜dùÖ*SX´ãñÙ‚ª@,ðìZ»>«(M ê;ª›®Y˜ó¤[32y›’‰šž{Ý›5Aõæ8ÚhNæc)®û艟3mÃÀ;GDF¡Ù†Kšø§Ì·ˆžq¹òœÒb4¢_¬³¢'ÈW/&Ì€þ0¥ú½Cׂzá4+ñv£ZôA8Ü.rx+´¿Íråò̵ªZ!¥úIwúpíûœäW0&ç{Åpšè0õãj¾þÊWÅõh»´ FO{–«ÚÎ2b”µ4;ocû%QŽ[·¾ÔGk¾{‡UaI••HEœŒ >:‘ A}£(Mf‘>õ]Uõ‰3gÑGÉÔǨûüklÞS@²Lq¥ÐrÜÎIƽ– :Œoå;ÖG}—¹Ù‹‚6ÐqmV<¦¹¦_ÑPœ«S$|ÊXø9Žk$fÈ҈߂XÅ"%oÇò~õë>Êfª|hIÆ3ê’Ö4¬u½l@Ÿ2Tž†—å—t1·KàÙx8‹ˆy&é{J.T7´ˆš?†Gãtf4Ó…þQ{ßOW¼²ÐšÏ+s½]ÏšBú¨èø¼¾Ã#›kQ8€Åó[®0J8îÒ ¼Žf«¹ ù g¦Û¹fûtŠÈ’B8VAlÄñýÌ—)‹÷6šügûÁ²(K÷ôy8÷äãVÔ¬_îb±%ñ…'nÍœ61;u²=»9~IP’Ó?,—xÄ‹”T.Þ;—B…:K@*¸È¸IHno§Mós 5ó¿5øüèý°8$G÷¬*e¹ô}öŒ¤ÅÚŽÂá8×ÜÒñÙÆQ–./N8†ãþ ýkbÍ‚˜ò¨M|0G) 2*þõc ñPŠs'¹}*Ô÷IÈùÞñ¦©ÿˆ_¿Ï¿6|›W…©a]¤Å1#C»±.`²Ô¤.6T·(T<˜kpyzsiêÉ'rbP7éñXM/P–ÍQ½t´9Ì2wëû®¿Oã*à×¾Sy!­Jâ,ÛÇöÔq1%ý óiím‘w}²Hpómòö©†ðýI@ÎÍϦ'úñNu‘X ä_¬8hÆìŠoXë܆ÁÆ¡!¿eËKŸ÷n¨$¢XŒ,„ˆð*Ì—Õãk¤dBýÂðA©r.R8Aö"ÒÄ(“ÜÉ]Î|%±1uèþ—c2:N=Ô3ÙÛ€“Ì ÅÍξ[œ6ÞxKþ+R0Ršä–)I¯5 ëí±ÍQe÷[ooLÌXÔâZ`éíRŠ]2=Ç}A¤5»›Éê©[d½^‰Ç9ÿUþÜĵÏitÞ,“Î!¸3ÜР!ÉÂræƒTøè¯Î…$ôü‚’ÄÛ^¶îD;òïÅþ®åÂ1Œf4xèG‡&˜aßՓѧAyæ”ñO«òõûú¬ìwˆPt œÏtl;;PzEûXJm~’˜‹Î•þþ]i&ÛÀ}§Î¼šbFD[ØEV‘< nã p¨(¿O|Š zëMôð[Œô^ËpÍæsÇÇr¾ŸM¿ïÞ«;· Ò°)­ž °n´Fšðöªç$KxE0Àu9âCyCC‰ÜÞŸÊŽõ«wî;æ¥A ‚¦Ü¢gsQæü¦ùÝZóT]q²4ØM†–ã§I>¡¤ vÌÛ«1Ù‘›XשÉÀsaí$®Ðsâ¾)Ú5Jˆ¾k»çù cvs÷õªnœ Çßi³­¬U8»ãSK©á<ïecÞÃüAßOCÃÖ5Ö®¹ìï vÂ0IÖ…„¶0q£.’ó]S§bÃ.¢0.JWñÞjpl6œDßGégØ»Á Ùþ\»ÿÈÿòÔÄ>…aÒƒ&YÀ÷„ï3$m;ÓQÎvcºÓ¸i—£ºÔ)wýɡά&2ìÉíНU3s<]‚#^ÐTÒå5y¢×ò’…í!Ü´gg9x­ºZ£ÔÏJ*üF[‡;õŽ;GÜ ®[€®¢VMB#/«†Š‰¢¡ù7%n=ï'šàƒ}¤—Ì´›cF»ElŸŒÐ|7V*2íÉò;擜™˜ù)0ᦦr8þ.57ÇT ŒÆè2‚{C‰l·‹£øvÖJ絃‚XfÀ¨…“`\S”Ÿö)ܾáì!b=1á­Í1!C-û7ˆi®.ä¦Ýâ97õÊÓKð~;EEš?yˆc­[K8d6M!GwúrsE 7“Å,Hõİ®óÙóÛ]ŸgäXGÂvA% ;EbÔ@VCUm¨¥ƒËè# ÁöÒXÕ‰½heÃéñ± [T"ŒÅ ½ Ò°ö¢jÀVùK‚uâ5ÝñÖB¼örz¥ðæDÒü–buEÈ;2®Xevƒÿñ,ž¾écDo‘ f”³+™•_òÏxëÒ($ÀS‚Z!ø™·×_ õ5 È²º=÷ÉãQÕO˜©5‹Çù0­~/ê®Ô_Ƽ`¾øas¯·¯4B‚§‡T‡+Žæ“'d¬MG®×޽òÒ‘¼ U¿ßÁ<)Bc ìâ÷ëã¸JˆYîR÷¿¥çÎöàæ=ãåµßË>t›‡^Uò#<<[í§òT1W‘Ȥ„¬•–i˜æXMkg!W“ߣ¹Ð0¼ƒÞ5?zôÚ i¼N'Šj…ii=IäpÓ®ªÐµî5ÛÔîÁbQ'š¹LËP“qÔ?$}âP[¯d®wÓABæŠÞoûLG «ö‘éRF×%{Kr®qX›ÄÇïNüÍ1Zk™œ[²%=³8œÏúàŠžö¹˜ºöüÚÛ÷ø…ÅìüîÕ3óM´Ú/ÑSƒùËÙ‹êÑÌ¢êA!n¥(Ï7ÅS„™ÇU%ž?Z' WñF÷=AÓ7ˆ°ËÖq¦Bž§WÆ›w²FÓFÔø_¯¹z1ïß"F®bÉÎË¤é ˆZ/ZOã?wF\H¸Mú`ø߯ÂFÕÑNUú,4R¥3".!ϼ»Ú zß×Käks¤ùO iáuR¸‰%[ÿ¤SWU Žªh³þÀkNXÚ,,Rº{Q2 ØR‡âðWÖ¯ít(tè¡ ¯FQ'MÍFÌÎU+ª½Gãî–úÍÞOA5Ë òœû?eQoø¾bF¦ ûj‰Ÿ(»(½.-~QOCì±#ÎLPÔÿgÝrÅ)òšf°€RÖïnOÈ3Œ’íÉ×zpÿs›ü§Ù¹jý7°m×nâPaöõšiRãx–µpœ¬\9¶Ð™Ä°²Úða_ç ˜‡³${J#;Šh¯ïgˆ…J²=Ãý…‰Ojl‹C½a¸éǶDÝi´róÇÐÚiìŠÉ[´ó (‹;¡0ÁSÑÕZE®~ƒØöéB;ƒ(ÞUÎÎÓÒoëׂîf[êaÙôîOÎN€÷VM{fkÑ·t˦ð³ÞaÓoµ3f[“탔»f¿¶ ‰Ho¬R¤Î½CV}·2ð]½F8n}©¨(¾;8Ážo98,Beëå¿›i¿•í9|ð£Ù;lâ‚|æ2ÅìÑ– \«rµ?Lî±aœÌé:Pµß '㽋ª|”ÃßqÔu/œ­Ô„L†óøJÇ©ïPäÀ‹u9ʾ©\Ød¶»!ŽnÍÍ>",ñÞÙì_ǽÒê‘ÃÓÆ˜|7ªáÛV~eاzB÷ÃèfIªÌE¶?GöD±Ôìn Þgê±ÿ~|îtá÷݈iÏ^×¾›JƇӓºgt!6²:EJýþ÷{Ï‚dƒ_?Dàt>YP /9!`ŠÜЇxª5Bƒ÷—’B<®‚à4”‘t{³dDÒmaÇËŽ_vfÏàm>ØV`6ÀŸ,–8ˆÚ1{øu“pÍàýr.„þÉßçþ>µ>/HAÛ˜ƒê1ÖâFßð8H~Ö‡]S·1œ¿;»Ž.ÜÒ¿Š}Ë,ýÛîÂCß\ÖðÉ@à=º‡¬Fp™Š’lúÒÂZ<ä_ÜI1š v wÏH $õòÛGõ¸\F•0ñŽk'(GÁhlI¨ÞH|‡mÝŸ·™þ¢p Æ~ÞömSÞ˜¯ÞsY«Ó9w(aÔL² Q[ö+MÏl1=ΪÝÓ}‰Æî‰ÎÕŽë§ \x_i«Š£·,ÇíÆUöå³ÕYäÞLd"ïæ{ZošmŒg¬«}cÍ+Šþ^9ˆr]ÅŒîøUl°;~ Fò ¼yë½x‰ âyç†ä혧¾CYóÂÊü诬"ÝÃqã•SÀ%›¥6Ë´i;8DX᪾1Znâ¹—q7vúý¼LrÜn:ú²®ØK5m”ßÈ/ƒV?¿'$èZ‚Ãj>å:O ]f\†ï½òÒM?Ôà‰±gR¤ùµ,ôTu È m©u Âtñ)ut® ì,bVY¯’®Qm—±5Nƒë¸]¯meˆx z<˜¹™kà+~‰ÑÂT¹É}ª±ÄÂSZÜ›oþÎ$‡WÛŸ9¥Ð2'të?n´{?Ü꯸v¹Ñ û¤;­3®¸¨|Vwã!_¦Ï@Òù–ŠZP{ Õ’NI™¬êÍ!zÚ1ùK-ž˜ÝGøñPþÎØ˜w€“<ëD l»m;G²ƒ$¸O¥È–â<'µVÍ{ $îŸ'…MDkäÊâ”C¸ìQ_®+ËÞä]×>ïD9%MMJ†ó‡ð’Y7?sˆ„¨'¿9f¾W)ÐÙA’k~Ø ®—Úƒ“o§ujÕ5AÂûY¥¬Ö/0åë(Ígúƒê¶ ÔÔ4‰ðûLr»™â@ž [ÿסÌȔߖ}º³§5ªA8ò…aÆ)™é˜y / :œ©¶-“9m.Œ'g&™v=GÊ6éÂŽðM«ªÌÆË/±PPMI0Ô@_ÞG²©7²‚@R5Bñ8 MÖýKÝÅnNô*ŠÒ/±«ä)Ê›¹t“— N´ö ÇbÌ'g좥7×àë⯿#ÓØqUûæ®ô£}_û+Hbb›vÉ-¸ÈÇk¸l€]}Úª°LcÞræ&Á^Ù–#¨RÙŸõ¹ƒ>Ú1§zóê“UJd1ã·ŠOCkR2¾Ì×jL²H¨üÍhT'ò¸ø!=ÿCh„ŠDpKÆùƒâ´”äF÷ÒÄ ‘šÚ”=DÙ$©D/A]8ÿpùàïüc¼ïª¯“<òºR*"QPûÁ\¿ð:ei‰Õøè+½ÅÜ ´¤I×"Ép*¼T±;ѼÍQÓ¸ÎQ_÷‰‚ÖSûyjÔï¯;Ù@kˆh{+Ÿ÷ù›` …ÅT ÖÏû99ЇªÒEÃ0fØ´¨·§œŠ†A¶ëB ŒÿDÂV6™°¡žS²¥,‡¸Û6þ}”þnJÒ«w¡š0€À`j3ÃS]vr_ºÝ´wá½$®Äéï0ùžsüøéFpC"AÍ'˜ÑJ],^1ž„]%K⯶R72ÚSY×Y†-D›.¤ø@ˆ!mJkM…ÞF`RVºpÚK;Ajü³y‰±‰¾°·ÑË#IÊð ´óŽÌMƒäÂTº×¦çX^« CÌ41ÿ©7þ¸½©‘Ãç6ò¥Èëõz\«÷¨WF&ë¤/oú­"‚Î8µ¶;Uñß<_>Ke¡›„˜£ê1xµÔ«›ãB÷-û]ÐÛ¼É@É ‡‰ã‹ÔîˆwLfç# è7%ʱëþð]Ã{›KÈSWñKDoä õV6WÔ@S™ëà†&ñÊm,ï\PòHŽÅEZTÑ—¸²5yä›pžÉbwúC:oRhÖIýž\ÀAœþ3{ì7ÌýN­f̨G¡‘“–2{ÏÛIª¯;´¹P§#¢n“x¥mÿ d?I_ÖÆ³*Çáæ8(ÕúQ®Z¹Ÿ1Ã’Þhõ.80ËE¬Òúøw’bSÌ„©Æ¯JýÌ'ÿÞ[Õ¤A¶þ7ÆûÚYY£=­ü$W«´}<>×ò´x9¦C÷A§Ü¡ƒˆë9qE¥l™ø»tw9IŽÍ™ÀòªyÉTRR™±§µ·£mdÞÖ»CËØgÓY0‚^bXQ²:;•?³MïìNêW¾Bzd,O¡ý°Î¾»U„d•ãL3G,Ÿ¦ „f˜\:ÛÞgÆþ!¶¼‹BhoŽÿ}ï‚¿ouÅ?>~Ú–™·©ÃyW?û$£™K&ó á‰ÊOos9æ·“JUÑ+Á¬DWHU!Åuê_ËWÛ–$¡r}ìÈ}f ­èäFw#Nè¶xÚäLûò½°*¥’R³VãLgîߺ§ØØ5iÅõÅ8I‘h¦âR¿?]”üYóvç¦J›£ Ø7þxM9ôÈBrBƒÇ÷Î*”/ϤãÄûW‚¹Íón.3mTÿ³['Þ†ƒÓÅîIÊcˆþ鵪¸:ÌdQl&ß­všYD#B”QÒŠÞq?¬uÒ÷!¥z\2ÂG ÑÈl[aÞ!š±–fLÇ䇉wÜ_Âݨ\ßyrÛZa Ó'rÝQæoµçT­6Ú8ÏÚÓ‹øÐZ–±{wfLko—„îˆq¡c„\:ذ™=²S?Ö>[«…Ç ¦¡‡¼Cß|ÞîᙈP™ !]Pç¨úÞœÿ:VõçšCÒx*Tâp¿ªá—l'è¿Vå/boÄÎÍoüÒ²¤Àrìý9îÂzO ÔáÇ´FÙ)Úð J„ ÔEó÷KÙ\ äð«)áóœÁíÚƒè‰Ñ3­W¾Õ÷g[3Þ-Ø¡ôÞØï\$‡Šìkëtâ®Á»ìá¶Ca™ë.q‘Š EÍ.Ü,±ÏWç͹ÞEû×ð cÞ[tdGñv1òºNYä)ñ‚G\~qSÏ™Iaþm¦ÎšÿÜgƒç©ÒQ~|ŒÌÌOÅŒ^†N}}dAm_C݇xo”ÖƒljcÚÜ4„qËdЍžyå_ü|Œ„&]Ä6$‡¾Ÿó¿9Kü¢þ&Aßwtúî êØ¢°]xÃܹc•_Õ¨rªñû¦(U;_×ïó—Ošþr…FÊî¡—ö}[Mª•B¨3›;\&fëИŸH§žC4“Pû —7:gJ´=Em(3ï#<”-0™ÛÙA-J{<Ãü gÙ}3³™éµ5ŸhºX¦oåh…Šjz¢eÄ(¨q6„•áädÈPmžqÄÜ Ðá™Nc,ëEÌÔ¿&›ÍdôØ“e'mÙ» b‚ É¿z’Žu5 ?,€9 i°ÒD¡Ý‰l’¢(Œ³”Ù•' p*{,ÐNt΃õcáF´õ±¹Ó}:ŽEÁxñ¢T>¥äE¡ÓìeÛì{|»º¼—Sñ²ÍvºÂŸÕãwŸåM g¡Š³ؽ ŠØëȘd¼JPæ±Ç_øª­$±[SFr‘ЙSÝ;¾Þ¸6"kÓ´Áºýá|H:^—?#Tp¿xVÐ^èÍànƱ±_µ £óÈen)èoC¿«i¢  iiýö}FÊðSAõSîbËŠK?=¢uæãbü\’.0ÜOíó$[úä¦÷Ù½äIÏfR@Ïál;˜­ A<zYÂÞÙŠ¡ œPê åi îíûÌiˆ §BÌS¢«WvGq·z61ŸÛ!mVròȇû{&'‰rÝÖåÑ©è†kµ~÷p85˜2¦Ž‘°>›ÔpŸôy\î´±s*—+Ü22ñ9[]MDëíê†(,µhŽjË Ï(³Oè˜>†Ä›ãk ¸¤™Hqr·;£™F¤>Q¿`1Q¢Õ&¿·"’ŽÊøúXl+‚ëÞ ‘—bˆB‚¯I3¡ÝÔ™c ¶ÔÁLkêêóÕ’ }Á'TU-+ÉH£p@þyîÜàÁ•áîümÂ"~Ÿz Yžæñ–ÙCÅS·Nɶ*|oCÆ—3ª î²wy+™u‰ßÃMceå6 á¤n…]<ºlÎ`<ñÅÅ MÑzA;27þIŠ_Õq¤pó“U§*4ðËȧ[¼^¢EÔʬQ‚“Z«ÅKæpž³£ Ìï‘Y’LIht»¸f*Ñæ­K/˜ˆ(—Ô¡Ü`{WÇ^Az¢|®ÇâêóÞ9ÂùüIǵøô¦‚ºR®„l­æM&;ÿvHì®l!-î–‹+4_kìÌâ[<¶WïÀ ðúB¯p®¡üY¥3Ý‹²Î"ÜkN© õƒ‰ê!]½Å§†^,’%MS*XyÝâï¦"’THγ˜p%Lëœý(£ÚãùxŽ™ÜIË;pÌÃá[+w‰Hß,zBÓƒç(iè€ññ9©:B‘‡y¾ÃõÁø:¹º†TíVA¸…³ìô¾ •ÀˆÑÍÿŒcÚÙÎ-âôÕ›+›¯I;€\â³ ²ÉižTQÎñ„ý°Ø|§¸ñ $^!ïéÓ¶æM â×}­ª¿O»[ÐõÁ?dwÒù‰ ‘CÆ[ËÔ~í/ŒÓ¦wÀÑ~õª5´ð^MçÕ§«Ý¼lÏ,÷˜[¯»á×1é'¥e§nŒ^ÔøóKÇŸnîq¾i" ÒÑ©†Yâšê†èâM‰Ü„ yZñ 2æñŽ8™ì“’û,­òíDEê¬Ò#í¿;[Oÿóå<Ý#5™ÓAû6QŽ;:‚WŒƒË:XÛêØ&Ø É$iìãÀôHìè³wÉ~Ï|™ûš®ÔBœîPyÛð:"bĺà1¡vÀ+êWY оŽ,l9Å«Oã^Ì^¸ß; Y©\ ”Õað™ŽB—:užX?ZÓæÜäWÈ/¤EË^ò9lŒÇgëÜê ûêõ3NÊc‰‘C·¯] "dá E0$Ÿ4M•¥)¡Ï~ØYå–"´ÛþÐã²—ØŠC¼ù¹Ò²Ý(Šª;D`Ëoe³TkiÞï=÷ò¨1uã-—âÕv¯õèóÞkÛ³ç¡ö>EÉPv0"±L€’÷7'»Œh£|Â<ÂôÒ\iþµ;LÈ Ý‡ßg®g­ƒýcwÍµÞ _­å°ÞoÞà‘ûcé,äÕó×–<¬E[^gE‚?}²$f÷c‹ŠcزDŒUȈ]ˆ2רîž+[gDiw/&¾{Â…-¨ˆ´–w™ùríéÕÃÍñ[eKÝ£ÖOpÝÕÿˆšseײ36G¬Èü:t„l£üµtA© ©J^‹ä²Lê ä&)žŽÑ+™bŠœâG ¾jÓìF‰¾fj*±`têßLó8ÙNŒS0Ø`Ïþ’ü.‘ÏáDz.>¦%‘ó3H~§mþò¥9Ü\,-õDõAù²jëû¢æ"åVµ|ú“Ò¯ä²ÇÙZ-+ÙO$l7¼ò±Ç©’iBs•Í) ñ¼4æÚeÂ]òÔ22h¤ÚkáÖF÷‰!ŒyqpS™ò§ñg»ÞDt±Ðõëm×%ÎŒ‘×·Š×ˆ"rÀÂïeI²[£X±þ KÞ^ØÀ_ ’‰ýßtä,3üÕÒóRJâ\ÞþZƒÓ ðCùh¦ «yËvÌ™ÏÜ¡žF…è¿åáybLæ•}ÌjŒújGc«[§ }¡šÍ˹ÚÃAªmæž¶‰h4NÒÏÛÒEýÄdðÂ\ïÜuñ¸J§ï›âKqèFï“1ÙÑŽË„âÅPûô]åólÇխƨ-„…€œŽòN^޹…µWÓéégVº`)¼jLÖA¯@ud4NáIì„ÝÜd¹5ÅÖ\ƒF2éôÒÆ©7ñм<Ÿ©ËúnÜ`0^3úæ‰p§AKºfÕþ-a"BòÖÏ»ôìÆâ0|~P*ú|±ñ}ÞoTé`â2ó$Œc;¨#°Mˆ«ñe£¯¶ÆóJ™ñ¨!(@A%EŽ4ë2`á·ìNö÷bJø+0nlÞ•¥#B#Â3Â;?EŒôG^œ¾¼ED¯ebý-4iÚÅ-T¾Z&ç\ l áðæPJdÜSž U Ëb!MCù²I{œÌYÄÑc÷´ Ó Úûž4> Í [Õ4V 9Õ Ræ ®“¶ âpÓï5z^Úê±ÞÃņÓ*'7ÙGÇðD²%®0€üš)úFvÛ¬ñÉö[‚Œ(­tt™@ÈÑQÞ×ïA±…jtpd…N2äô?ÎB¹biIhѾ`·Ø}ªÐÄý' ·˜R0DÄ$ùm—tâK ÿ–ÿ'b"ŒÞÉ2Þ¬Mo|šÈ|ƒôM̰—±Ñ(¥³ˆß¿p¯ã£˜¹O\„ º“G'w¹O VÏ8Èd;»ÔÕv$ž–Ï1Y5ž²wnŠažß[`žÖ}(È’<m¢qÜRiN42¢á¸*²©±é¦“¬)Ø|¹B¿Œ( ûÔ&ÛmW²NŒ9•s1HU^ä&¸×^—0Ån+ø™ N«3ç$Cµ•—ëCÖ—*Ñó…AìaýñÆÝõöudõ#Z™r%,A¢ÏÊ êÓÖγ*åH©óÊ]Æ‹ìa)C±éŸpV´CÌ«—k‹`HŽ\³iQç“Ñ}8jˉ/NÝÛ# Q”RÒ¤Ë}66ïË7°š»¾zÃ`¨T5’Ì’•»žª¤R‡+øO°Þõ`ˆ½ÂÀ÷õ:°&~ê£ÑÁx ies #ÖÀèq¥éÇcÆ›õE˜¥*.c«F\‡Ø%¤tÛ¨Y!b²÷‘Úµh¼k±„Á€8vÞûy-ÝÛ~;5x†yŠ·çú^3WIý”?}.(/êÅÌ[P¾c¯-ó°`QgbM «ÁDNÜ2OwîTx®ÁXÕ Ihç+¼ivêý”{¤cðø¸ˆñ¢‰W¡k"ÉRwAFKQÝy¨ëYõäÅþŒš^´%wmƒ^Ç•¸'úÞúÃiRiºý|ã„C‘‰ŠKŠÞEÛµ?BpÔw`¥ô¿·¤ÄEgo…ÊŠJjz벺B{i¯ Ð]—¾ß;¡°k_7ϰŽÄûá<\ö™ŒLÞâfcزî‰öÛŒ® süFZcàájаj;[íTr¯è®M„m€' Õt?ݨGz~¦[)ˆ,îÈŽ»€¥ïŸ”„cö­ ¼½ »D^+ ÓK3ëÆáuÅrÒó•®é!‚‡uП!k}ùÁ>òN?壘“_ñ ›Î(ÂÿhÆÔ¤¨ ŸkEE¼îLˆÉ˜HG˜®¸upÕýÁBHYû•ÆÂ¡]夠wô"Ö¢žV*ï“öW×®PØ£Õ^ÿ{ò]ô*=J‘5L‹Ë¬°˜ŠrØLé;´zû¼€iïÕæwù¿tÓt÷ûîûçƒðг~4®wÂn’ë—ÍTâB™_дÖ<4¯T°…I„Ù¥öƒ“0·hDúC·9¾7‘Ç ‰g…ÆóK7 ,žeÉ@ë¿­7¨5×UT=>‡Ra×ÜN¯ ™*3YhPD—’45 ãú¾âŸ%vÂfö¤#;ævÞÞ10…UˆK—GÔœ–à!i<ðL¾ œßÊÄuݼD”N—7C ^#¹ú¦×ä'­*%ÝGEfÅÀèoz’ÍdŽ7{Ûÿ½â$ƒpìõ`W×ä:Ç“Ðnûô“ á»´z4çjï09a.Jؽ—Þbe8gvw¦¦Vä—çÂûüHâ{°Lë ©# ÖÑÄѳ-™ìïÇ„ÖÜ*ÎÏìW(zNò|1T{þ]äåãþ`Û¦µ¬ÇP}ü|•ÍfJ{*ÿó ~yÌ­P× Ÿ{Â;Ž Ž¹ßq!ïÐ/!mŠ—0ü ÎÔ¾ß7:Ãyx’kO(³C±»â‚~¦èb?ênýb6u3EÚ´¤B“A++!¾Éñ»+J©í™apVž¾nÞäpâS[)˜ìåOh/7i)o$Ü[ÚøP9,T$BÓOfêÙ¨OüAºå“¸j ³lº¡4`öWè ©{;/1ú Bè鎳í¶Oßž£òv½ý¡ @Ù¿A阂þ©IºíOš'<ÁcU)j§ðüÛÀ+ê1‰%ºì#ZÁͨÙ2Ȇ?ZÔuÓhiȸNûçæbHƒ1zÅImZ‰½ÆzE¤û/Ѽ¥lí/¸±2ä .Ÿ=5æ'«Aœ6)×ôáì‹Ø8¿E I¡!­÷Z“ήS óÑtƒ88 ã ¨æ’Ù”z¾ x§R¾^”’·iÇRÚŽz('7µ8Q¿ ñBD—ô±*Ú¿©ÿ>ÊHSLâ,|vÔù_¾ÂÝaÒµ.žc;€‚=À¤¯bM†ÕN ³õ¡f~Íôw­ð³?¶Ñ´È»h›ŒËE¢Îz÷ŽÙ·Ú‹±ÊMQDò®)—oå¼ÔGžWXéüµäáTBœÛüî–ìt6×éÌ °°,>™0¤ Rl2' Gý†ë=-\«!pVsÚ¤ ƒ†Ó¶\ó2ÓÕ’f$É…x÷øs PÊ·™ÉhÏÅ—Á-~Ì rް?3„2$¸y|îÔôà;ÄwÄ¡üVc"½müM ‘ QKFUB¤«žuœüκæ!u˜ /Jm~«+.™ú˜B€sç}áùrq?òg“°Ä¨L#ûGH‹Ù¡ ºÛØýõ­6A Ý: j©€X0ÑÊè…]Öxä…“¡_¹Ô?׽؜d‘›VøAºÍT0 ž¸ e’ýÍÓ‹Íw…Ò“#¸.y\lï¤!5ÉuźÊõ³7Ù£ÏK¶œM£Á‘Ž\x^÷﹦X%©L•ìI«žÜ͹š‡Ð*ò7…)o~ËIF¹õQÛrÊýh¼m8R¤^·¨1àð ºÖøãW4×]ôÅû­ïT ¹¦þ>øŽðÌ@¬^„/ÈQÞÌUàŸN{_ûã…f.‡¡Žúå–/{$ÅF« gE+Ÿ¾•o¼!HIæÂ¦…ú:šÏ³¶™BÛ|Ãò>!:X|yÒ¦}†›[›,¾\=Ôù š Á'gדςM{(°Ý1¢\†+òQ&py¤X,4”q[ÎrF ãK!A Kf¶4 Κ9‚ñd6ÏwįžŽQ¿û}4it ¶ëGuk¸ÃÖOsÓ–MT·Jïé¬6ãL9'I­˜J>¢oJfWªr$1\´».iÍ}רííû1­Y»&Fû¼õÁ_fëqÒ賤>$Þmt…A¼\¶¶_ždN*KÒ”SSöy—5ßxñ•އMö.ºŸš°¿;ÞÒÏó6»zŒ³jToãh× G÷hÁ'<³ßä:шú÷Gê°—ÔÇ*C(Ú¨NF¼+HK¡¹,&íÇéÏCÅþ»ôõ_Å,Œ<ùÓ´#øï`ª–.mˆÞn“™fKsVžŠÍ¶|‡•~g„Þ _€zÖÆUV—–’ØVdøY£? P*ˆ)?p•¼±e°EC7kÚ%~ãZw&Ð[Fâ‰Ñ½¾Éã‹26¢| %§W+=qJ)êM´9ÿ˜ÖéÈÆ<µÆÅãÏ<Ù0¾„ŸœƒF*K~?}â2âC/8ü9ÛvÆ3 %€ÈCMFIúÍ4¾ßiú¹PÇæ0È:)ý›ý±ò’oÞ»$æéA lÇcôš›'æ4 Oïô Õ…RêݵXŠÒ§Ø¢ ¤¨+†GÝp|.nUð%¶+,Å7ü‚GRE”ª\Õýsö“kk¥5—×t‚×W¹U{ÒîáüÆVdúào]tõ3Õ<+›L8šuÎ0$ñ*ô¹tqé‰áJ°1¼°9âûX¬§€µælþúšÛ8'¬ßV“û^«l58ç…\-€kE $Y²&_O/I© —òƒ¸§/-Tý®‰/"¸ôI™ÐŒz–޲ò=ãÀåQyCJa}£4º¤w“íôº0ÕŒs\@ñôA/n~âM©åB• }‘ø5œÃcùYØ °ÈðëåR'5}øÉ¬Ô–Baàò§§<+Å5àËûtÆ©qiŸ…Áz=4»<Ð÷=_K­¬^ˆwh‘© 7±´Ë“°¿Ý E‡x°=Q²î ±Áw»c#&Ÿå½¼—‚0S„¨ûµéTWˆgÀ ›¾õX°Ý(êûB¨4søšqž„¹ˆ%n=’:×BëžóæÄlTÖ)Ì’˜VV Áú¤}.®Ð¥Ù¸Ôdå@êbh¾6¡Öù\0¼XîÝ3ÓBëd[ÚÁw5» °] ÓÊx1Z‘GµÞ2ñO6G%#‹(xx½P@âM£Ð6£rOFÆ&iò÷ìšûVÃT{¨x9éloÐBC#3þ‹÷ÈM:~)g 4ÿ´~¸HÒ ¡™ö,·8j5ºB»éYqÜ/ñ”\ûTŸÂÜ/|j9ü·Y>vÇr·D¼ô”¹ÇòÂ@ÚéàÍ/¶Ü‰2ëÙh:©Æ«Ö<•·–˜ Ê>Ìa‚oétLJFÐ'üÞm0Cçö_—/h=½?^@-™ÊE˜.˜lŸg›-güúÁ±?LN1ª‰+ÎÍåt»[ó>k Ï@ØïÄöÛÕ¼bê¼ò敘Ú!Ûú¾¯Œ~eó‡%O”Ûâ=˜Ÿ Ë3Uµ6=¦ƒ~ÆWå N]z÷2ÿt§Êk>ÂÞòL„/oPJÂV¤6îÔÞÐ$Ec±qW¾BרլðÃØ¿Ò¼¢\31†õ™Ô£œçxeYŸEo3 Í#PA%˜´ Gô)“4”Û€úšXTÐbzížYf|Ô‡Ô9™G•HI7‚8‡"û‘ùÆ?ŸbëïéeòñX³_ròù à …L„ŽÍ ³d`‚í¾“SÁ_â§0aàò¡urE<$"Óü0ÊÜ»LåâØ|Yíp·Ìƒ!.¤ÊN’Šð6 {qöBNñèEï=¢¢Úý›q0Pá¡rvk…c¾2"¹R¾û}­ÆFfβ­®Þîÿ2ªž®~WŠTæ1ï ½ð9Þ‹_ ÙCì2}áÍ{&š5"¢¼YMôb¸>×ߤgžóß&pYÙ“d»JÞ«õÉž»Þs™„ ØŸ$pœææí¶~ð[ª¹aøt—¼;vœ°ñ øÙwt >;~sÏ©¸oÇÔh"{²Ë¥á¢{8wF³p)à‚¢XªÔâ@FØŸO:g\Û(uy~¼zï?Âx‰Ö./>>ô€ŸðÛQÌ×fÿ^1ml¢?‚¯Ý2  y'xyìØtOf„VÖ¦¹lZ'ÔùØ’C¢Ü՛¦'îÅ«8ˆ¦v«Õytø#¼æ§c®\>­ØvÏ}?ŠB” ý &1NCã•ý‚r>ÀÃ_ûÍ¿ *¥B… £r±(L¥‹ön¸‰:w©ûÊXSEÀ w[Òá¨ì8“3$Ü4=ô\™!­œwK±©•t«ÖÍW$ßFCi3¶ïÓýݲ)RåâÏHAOéÚeîÞqª;T»ej¤?V˜ÁœäÜìb•Áòs;üQó øPíàÙ\ø!ÛJî£B/wÓ§ÀÚw®ÐÛ3áÚ{qNꌾqünίw޼e1¾mÕôÄ/*6CkéцzCLçõ: œÜ¨R¡§Pþ,pˆÅÑ#r®òKÆ^†ÐÛ•N/O|?„‰&C?‡àï‡ïê?̸=×Ñ‚I¼Sr{ ƒP0ÑÆò=È¡êºz<úÏ+´˜¼ürŸC`•ëH~7ï6\E£ÛÈGÆ*…ôÉÜôåá5gú˜Ã¡Hã) ¼Q||©Zæ„Dü’Z°=^œ0>!úŠó´) ]RÉUPÈ2ÊV"õœg&fu`ÆU2“MSèÊ·Z´D›¥aó˜cO©¤ÃaÐâK]ê 3§üqißûq–ù—CÆ1°Ù‰FÞÊLö½™(À…ovÔ·Í]æP\âW×3¥tmÅþÞfy endstream endobj 184 0 obj << /Type /FontDescriptor /FontName /WOKQZU+CMTI10 /Flags 4 /FontBBox [-35 -250 1124 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 68 /XHeight 431 /CharSet (/F/J/Q/V/a/b/c/colon/comma/d/e/f/fi/five/four/g/h/i/j/k/l/m/n/nine/o/one/p/period/q/r/s/t/two/u/w/x/y/z/zero) /FontFile 183 0 R >> endobj 185 0 obj << /Length1 1480 /Length2 7122 /Length3 0 /Length 8120 /Filter /FlateDecode >> stream xÚ¶TZ6,Ò¥HHËÐ Ô 1tw§ ¥ 0Ä 0Cwˆ4JH ÒÒ)%tK ‚ Ý)È7ê½ï}ïûÿk}ßšµfÎÞûÙûœçìgŸ5¬ŒÚzÜ2V ¨"Žâòð‰ä4ôUD||ü<|| VV}Êú—›€õ1Ô CÀEÿ ç… Ð>y Ó@Àª® ?($ ‹òñ@||".¢yˆÌ  ÁPEÀ¡HV9„“§ ÌÆ…Þæï%€Ã’sýNÈ8B]`–8@‚²…:¢w´„8ô–0(Êó_%8ÄmQ('Q^^wwwˆ#’áb#ÉÉp‡¡lºP$ÔÅ jøE  q„þaÆCÀ з…!ÿøõÖ(wˆ €v8À,¡p$:Ãnu 7詨´œ ð?`õ?.À_wòÿSî¯ì_…`ðßÉKK„£î ƒÛ¬aP€–¢:ÊÅ€À­~!H:â9@,Ѐß'‡et4Á¿è!-]`N($æð‹"ï¯2è[V€[É!¡p’à×ùäa.PKôµ{òþé¬=á÷þ˰†Á­¬‘°ruâ5€Ãœ]¡*òAÐ.‚|6P@O@PK[Þ_åõ= ¿ƒÀ_n4_o'„ÀMê ³†¢¼‘7(åâ õõþïÀ¿- `³D, 608Á?ÕÑn¨õÝ|˜À„­= €ï×ç?+3´¼¬pÏà¿ûË«&#'£­ôèãÿÄdeon~A7H Àè…ï¿Ëüçþ&ÿÛ« ýu8¾*ªÀ­‘?З÷7·¿dÁñ×Èpþ½ƒ&­e(€ãé›ò òY¢¿€ÿÏð;åÿO÷¿ªüߤÿ¿Rtupøæøÿÿ„!Ž0Ï¿h)»¢Ðc¡@ü¡†Ð?£¬µ‚¹:þoTA‡ Ü-qn ŸÀ? ©ó€ZiÃP–¶„ôw+Ð{8ÀàPmöëÅAgññýO =u–öèW‰nØï=TÿÞWn‰°ú5} A!ÄÅâI€î?ÚxÑcjõø­o/B§Ð}Ö‚_m xU¹~[@´úx¡ÿ˜ ¯5ì¿¢h°í™Â^‡L  €ù_¹èRž¿ÍØÒÕÅ=οu…fó·ýûí€B= –3SK±»Ê¦órZwîoC âîÈc<ÃUj·u 9ñ‹#þœÈi™k‘K¤[ ‚›:{£û|öæ_|R"EïÏT7a[[¬pùŒJ\n!Õ]Akj­­ÆÏøáV6÷÷êu{Ý¥Ç9)¹œ¾M¦o(‰³Õ—ž½·ÝÃe¯Ýæ!º=‰K%,ÌOt;¤Y&½¹T¶Bf|¢E…y(=´O¯¸q‘ÒÕüÚ=[Ä…[N¡ÝÜ$vR;Nß”LþÞ.D£öl0κڮ@õã%GÐqSH ‡r@OŠY,CeuäPùp5ZE׊¨7$œ‚ý°Á ¸"YnúY§ø&ìE37= ´ÛO)Š9í^ Ž•ÈÖ7 ž&ó =Zj£ *Ïc\³ §Û½o¾õeÃﵜ*Ž”X Áƒ/[O¸zF'JÒÝCø›~,‡ÉƒYŒv– -–\*är|ªÛ‰XãÎ?9¹±ÚOW0µË ôÖ슒ÔJ lhËï̪î\‘º+¶4¿ªžh%±«óoÁé£dmXs­´V»ßP_¿#”Œ¡j§#wÃñ^+ß(ÇꚥªÃÅÚÝzÁ*0K§’¬rNËTÜÜ8FëmTHÑ·§Ñwò°*H`þÒx¨,÷®–n†*QùàµÖ£s¦ë¥Ðä±WoÛÜ´6¥)ù7éw;­TKKçv2<®0€…© æ=¾¥ Ÿ?ÉôªÝVš13+Zpçù¹&ÍõSev:Cx`2ÅÜg&š L™Êx +ko 9¦9 r"šÌ+žáЧ6L/=˜Úˆ¹_^-„ßÀÂ?<Ôæä\Û¯ªrf/îŠk¿·¶Uü`Ox‚U0N+ð{ña¨=ÅM´™ÆŠ¡o5°“Ì é¢rH×ååqÊ<°ey§ ‡ßtn™,° Œj0'¦{dzÓµ¿UxUBy°Ç¯nfòúËþFQñ])MÖˆ–,2OÛURù¡ÜE!lÕÅŸŸM„œI?–Ùåó’žãÖ(5¶Q¼ˆN!S¦¹mFÏãËVµE˰?{¢^=ß IŠÝ&^îÙÆO1å­™äpú€}Mí}‡ÑvÓdá¢otWê¸^tÅÓ-® 4VÙ„†:ñY¡:€äï+›¾‘ïM«Ïp«OÜ–—åaxoÚ¢«‘ªzïÁê×™‡4™ª¤Güâ…céÍKòÙæ9‰ÛrLO«YÌêýyT/úF9õbŠ9Qt.ã÷*ßÚ}Ñ ˜J·• ,‰é ›¸:"2ê-GZÉÖƒ£ÊRL¯´#×WbLG@XýWoOÏý;ô¼½}¿AC<,ÎÆôyžtkôgÕi½ôÊBŸ¤µð‡›C[ö´BYè F UÓÚ%Šýk׋ ‚ÞžWmgïņ؈+ߎ}0ðÒ™÷úi¨mm[}¢~8ÀiŠðÜÞÛeDâX‡ ”GÁ¤ÈØ==ûX9-.Áœ7ÒiàG³$$}f°ÍûOšxS=Εkp m‹öb!kuE 6æuWûò í"ëAvQ\3pQ‘÷"4’W}Ù®Lhx4Vƒ@.íeO#A ‰ ×6⤑ê™Z°0ÍʧŒ>¨}}Ñ÷•XðFJ»… „R•ÃîUwD"}Ë£èãFØW œóŸ-ňèZ·¦%5}H²¯S‰4‰ðNY^9Z»Nì`W+cYTf»9:+á£(N›òi‡É„õ E–Qqmcü¾µ=Ù÷ðûµ£tÝ Fiîjc R$6I݃ Oóªü”Ôc²K2RÔí³†Š€Yxƒt!»ÑWû$)Óí¥k½üÅw±¢3p6»…×j€.Š=tóoöêï|ó—bR ÑvÊ÷ aè«xÚû8ˆù;4â<".›éÚ¡Š#Ò‡ WO´æ†$Z±ˆÉ»›Úí½^r¨R^&íO75ªÝ¯ù*›G„ë6 òRåK¤íÛÒOì‡V˜û‰Zq;O´âú†}›’ víe#/{W”„4‹×6”A5Ê`„ÅKU®¾?U=Õ´E-'Cá~̼ÄKjÝ?k¢?³K‡?S¤M‹äÒ®Qìµâ5m{ho*@I¬à.ùÞï²W…Ci­“5´Á]2'íÀ–A¥xcÜÙ£ •|OË‹MÛÚ¿¯h²NãâY™ÝÏzQóí/Öq@KþÝ\ñ¶i“$¬öˆj^¸æ2±è¼ÒR<Ç©ÍìÂÒÞ>h­Ðäæ–c“,XÑ0¢ \Ï`˜¯æUVÊc$ú$w¼y+=Àúí ßM@£É°W?«ÎÊ1ÑìüÂyÃ.îÝÃæb}‹’÷&^š «ŒÚ#bŒh·?Q…•º0‚foX¼äVRo7´§HÂ|h†C¾î¹°x¿Û1ÁV§k?`öjئþìo^KrXɳës½Ø Á™¹6Á8®¶À3n)Ò®#Ú°+@úpYÝ·ÿbáë·YÞøŒôFdºZl1‰"ò™e+×®Þd˜~ÄLªÁr’Õ]Ý |CÓ%Ì¡T­ó<‹Â§#QõÈ”pì½Ç×w¸…»VIÅ\­*Ý^2é à§4]ÍêE5lÑ1Ñöòà‹7íùüòKÁ¹/ç—=§}<ó%¼ïÙGØS3÷9ö=¬½ ÷üFS¿³<`–¸¨:\{)@ˆ¦þhÏRXÖt#.C¡ÌíÅN}6°Îîàñ&3'&cøÕ`’gK@þ>7˜ë¸&w*<ðç£<óܑن»AåÝŸ/½×µY$SÛõQ¾~`»±‘½s»}”Ž/« B¤÷UœFo” "Ÿû/¢a¾¾&™^X%4ûŠžJVx¯[œ\EJ 2Þõ4M=ø°3ï£bJy|m•]e¨Yïq òt¨Î2÷¸õê-ѳtр曥£ûn ŸÁÐè̱ÐìaB<“ˆ'žZnæv.¢,ÜA¤ ³„šÁ*‚a7Qx¦ Øü¸r4­æÖ/em&bïß`õR±ES¾"%<Ü=ΗӪt×MQÅ¡\+—'»¾‘—¥mÓÕ™ÞòÓ‹c ^ÑÌm§D%nr 3×WS³)çp³Õ%¹«MNHîq¸Ö<•?ˆž•j\w=Æ0WMÂKÁŠª0mŒIóSþHf2U(•yGñL¡QçƒØ©5!ät}¥»"?J1¹ðÜÇ_ÿ&ÍœsÞU°°·_<ìFtàyà6OäT:戱ï(ä”BÚ“¸X§K,á·6 þQ2¥F àRÜ\æp´ù¡¾j¸ªcÊ¿¬5˜&fœJ¿êÓä—ü³=y1ƘƒG2áù½VùV]Ÿúöå ÌP­sKÑX¦cëEß7“Tœõ>¶.gv U§Ÿ‘¡‡25¸h‹·³*wTši„ 𭥨Qëxn¾3p·¢Ì[Ñé´4óÞ!|Õ8oÈåÎ©Éø>‚ÑcW’ ,ÃÅãçßM1”u cSÔ0òJ:ãõ›À´²rw7`çx`‚;ˆÊĸôsÀÌY“ÅülÙ$\ ;~ϸU,ÑÃb’gðú>NÃX¦§v:±–˜@'éˆG1…eÀã€-äÁÇéÊŽÊŠ:Œ³×ë™AŠrßsW÷tõ£=t³I¨ý\¯“¤©‚` 7vâþ²1·ÙCu/Œ„õðQ«ÅÝ©ÞS™ÞÁ<ç>·˜$ˆÛŸc”ÛË·iSžâÇä8Ž=”$°oÌ·{‘\’w¤Ë‚ú¹í,IìluiŒ-sã’ø‘&`í±VèUѵʃG¤IêaºÌCÙzÒÈç«WH=ùu™,,‹õº\Ƥl—œád´ûȿĕ‰hH ÅÔ_yé“Õ [Å;Ü”i±àÚyÌ„jž—ë9Ñž‰=ŒUÌ¢Ÿr–´ÉP®]‹Â·‡ÂÊšŸ†Itîy5•}{ÜS‹”ÛKßžï®÷/ØÊŒ»Ð5ì6¢`ˆy’šÑ\uŸ"܈¥2|! r*¬}JÚX=Ã^;}í¨Ëò~t\ó’füXЦuLqM¦ë9¡ûÔÑå«HTá(]N$^OŽäípG³Û#®³ ’Ëoå>]ÊïºÚ­kÂUæ¨æA‘¾FõåßRÃM¤¹.°.Š[“b1Lĵ Üí ô""'X=eV¥Ó÷‡ÇÞ×,g‘)XÞêòp[ØfýòHã®ìÎaÖÓB;OógFëwú:½qÒ L–pvŸj<x™[¨*Ϭ¤Gy“l%÷­ÃËf³ôž8=Aqø+…ЦÍíþ`_¸×²Û·vPγx×I¿Å6Èé\Ë~öÕãëEÙž²“@ª•§„‰ˆÀ‰±9ç"¢·ÕdÃì+¿™Tó|1ž¯‡ÁZ#1”ñf®‚UŒ7ù‹g¦…˜xîd 1Nßwµiƒª<ö‚xhàЦç“tr_5‚,º8‹ß¨æ/ó—«M~••0ÕG"¹º—Êzö´Cä”IFØøËû“fZXólrDzݕZüÔÌœãÐ{¹i4V}€s•Õ…7x“ Je'{âDØò'jUŠ?ò’ÑáÐuAýîý¨À;`ÉZw¦ÓyÈežÙ/ŸeE]ªÜïI{MÀÒ7­ô­8Ñ|VÜDÙD–î*:¹+À]ÕUðNÅ)·µ þ™’gbnÞá8RÁ"(,O VUjÀvߥâÀñI‚ù4bñdв}&tÀãŽpX*Ru!ZÙzh&Ãë8bÖ¶t#®¿S?P+ ` Æ~Ay¬ø0S$ =z¹Åýj‰`K Ÿõs‰ÎݤÏÒÝ-E(`¶úÐ0UËaMId&.”R§wº]y*p™úäÇ~q8’@7x2òci¢ùÁö²¢?‰µØkŒóøªu‘Oòg6…¬à¢ç¬”^íAÞeÏT€¯æý?YÒ-Ñ:Ê(WO2ØÚ«jÊ®X\4#ðÄHFNs‚×h;žR|âR¦Ku.ÎR¸d %‡Ù$›sZ`û]7ÓUZ ¨À†±2‚Ct+5Á¨?u¬¢¾mN—Ñ”î1ˆc0 yc·W‘–1»Þ›¥~ñ¡6”O<`R¨÷»5m;H¹¥K‡>™ò‰ÕG ‚ÃõX|Qn5+•%½ß;'ÏZŸ4œüÆêtI˜œQÛ-ª™æÚF˜l »¢ß¹ ¥½M$ºòzð{®éۅйEE2^̪ XÅ­•CPÅøgwxªFl~ô‘dð':÷}‹¼U¡n TÂl¨´¯&Æòååð}Ï”¦'¼ËëÔxRü"wŠ)xa„'W›‹ô€'5¦®õ;dµ 7^ôRjÇæÔEW^Ñ—PxÿQ”µTáMä˜äŠ$N¿ mˆS:ÝÞ¸¡ÓìSÿЬ%;÷IL\iAZÖ4g»Ü_û¼m*¸dòcˆ¥ë F7±i5ó—ŠêxžMK?uß\¿x¥øúYÒ½‡Ì… v`2—ºÙþ’#å¡Q®Cßâ‘E*Î2%ïú8Îß\1–žòa‹êqJD:KÅKzÝ)ï>›gp7¡ø¨Å»×Ô^»nk+s©;LX_Üé–߸ñBÆnÌä[äò£w|›q‘öjP¾7<;'‘$u6_CÅŒ*q¾4³ÚNYÊà{|nM ¸ îÖý7ŽÂzðççЪ§Ù‹ze‡ŒšÞ¼Ñýýœ©=÷ÐF QLGKEó<Ò[};º‡ENlŒ1ý\‹Ü©'váJŒ½Ñ’Øíc©™•U@‡ó,U`hüðküûR6¢˜5¶ëÌÙÊ ^KR}Ås6T½g2Œq°‹Ü¶‚ªMùc©Åcqë[^­ùKCv. Øcøº£¿ÜN”LŠçKÑ)Ra¨Óãü2íÀ<p7‘‰6ýÁ¥À×vLŸ³WƲºêÑM£r ªå@ØŠÕ.W¥À:wóú䞦u¢êWÖôH“ÇS‡ 6úÒ Ëß?½ÙL>x¼Ë²4Æ«YdV“«'öU;Fé:‚©ûÝ=¥qT¹ÃK†Ü Þ¨3‡<œÅŽë+ô<|P:¢GÄöQŠöJ…]®¥›6ööÃ…¨ÜÁ£€Ùà>Àñá­F®V.Ïô¡ÎWO”r˜ý8W Û#´tržÚk0àÔìI³6®˜q•µ´r÷ïètñ@x,W£Äê;` 1ø"xžCÍΗOkÇ Öºý 6âóô›Ø¯}˜‡2ƒ1|”Àö\5¥ïÖX\8ó_Fˆ#Á%­Süp¥mÁ£^Ƕ>Š}å»lÜ\xÉäkšÏ±µM#|"­‰³±]3gLüϰEµX[¦ÁъܬÕbk9YSvæËôg[ öœñpž§o©|PÝq“Îi!Iˆ¡ Ø'²<ÌöØS«óÂÑàÎ$9ÑÍ;‹K—T¦ø­Z±ãçf¢½Œa…ו¥0|Áwµ9ºÖ…¬+J%(–U9w”95Øp¤é'ùÁÔÕhÈ*Te~lÓº8¾³ÃÜ| ÞD ÆÖ­Rª‘mkrøa†Z£±Ï¥¾)žIUM„SÏ}³÷˜­9Ç8_Ù Ñ%³£WãÆÈƒ¥>©1¯Œ£‚²tõ‘WU§¦…Ž‘¤>žÏn]|¬ ™U»#j|'õšaäüeM!yYx¡Hp2›j‚Ñ ¾y`›ÓMÖ‹¸BlÏê—ÖܼÔuäû>K‹d·“U×·“‡0#î;¬{aåcÓ3/ÝLnM©c=Áà• S|ŽÛƒÚ Ï}to¼5ó™Yë¶Äœr>Äü*e:Q îz‘ª&ãŘWãν_tŸ@.øu ·ŒnF·XkTì‹õ>é­†hÝf'çÚ—IŠy}.•OLkŒ¾ÍÔëp]–Ì¿qx’ƒRÄBü]-R[mªŸÔW|Œjˆ-kk³Ô0&SÔ⇑<͸h­G¸H¼ñŠë*–Æã\;ðÑÉ­4äî‹ïc{ß èv{ÿÄ™…´\{vct™4ÿÅéý°¤×dÏËõTÌgì™ÌoMÌ&F±n@j¥ÄÉ;KÅ8ÜAy¡|Ìr.¾Ú_êG;.èmÖgÞ~xúÜLÞ^47%Ó#„Ð õ~²lo3ÀZœ¨p~“€?ÍÄGñà(×·d°eÇlEp0Ësoáê°;»×®gEJìCXå5¾@üüàË‘«¨‘FCº±Çjñéé ˆœ•tùgnʳtlà-vŽƒ/ªB=ΖY‹XÎ)…ËÝY¼­ÓcÚÏ8I6¯ïå"’¾5 ­_X"Õ"D.s‚Þ| Vw¬ '¹çYgq“•æèÉãÿ!ð<­+B¢;sµR—¬Ggò=‚v<‰fŸB*ƒò|[eø†C›&7Ûž[ô³úÄçÇ&˜N8;ðãoÛ$½À¬L³Oä^ú¡Íý¯±öå½ôcD`þâ>å š™¨ƒ¤ [füerµMM—<ëžAÊç%¨Dfwè'²‡në wö¹]t ­´Jœ9úO±=êDÌÁÜL«Œº[9°ù`؉3Þ’þ”H-Ý|M»ÿ@®ÍóƒH»ï4Æ’1?éÔfæêÌ,ÿÙÿmŒ‡+˜â€D:ü<ª¬ó’‘D?5¸ù“¡Rb6ápX3ÕsF=ì‰mÜ[óÇØÚX#VZçŸo9J§)Íhned{R%ÜleS´é»0Öäsü€Yò6ƒL¾Ï¾iúÌŽ8Sq¥©±O#z  6¨sºRB¾¡‚(bËÞ"‘k?YÏ ¼·QyŒuó­^=°ËÎG¾$‡+qÉopkÔ•K.#+fZAþœèöÉÛ,M?…8ÂùÉI‹ão»G¹ß‹3+UY.bÇœ<„}P4XØþò{ü¸é­Úo|\R5Ò¯„;ünÙ9_§ÙïV°¾âÆ;Y'Ï&ѵÊàL[­qxŽ43P ½#¹©ùò çnŠÄiB±CsÍñ½*¬ƒ¼Ì$¥àÈ*Ÿh)ö¨·Ó„1V¯§6m ×U—„Ù-HDB¡nj!‰õû$›îÕ”RòñüçÐY¡¡¹¢M¼V±Ý\ßòða‰\Ò–WêSN×wtl1.¾—dÐW‹ÑC ‰Fïá0Û¾y¬"éóÎ=º— &ŠGXa,}UŠ3ˆ?ñ†Èn# œ5áÒãØ‡ÙŸqÖ÷qg½C2‘ANôpW²@€Rsîa¡r©Oý=Üù"¾|ê¬,›BÈáJ±éËÓå¹aŽI–!Ó{Rl?œüs©;nÇê3(6 ’“vª%O™Æð “}Ù‚…qôœàŽ endstream endobj 186 0 obj << /Type /FontDescriptor /FontName /KACAPG+CMTI9 /Flags 4 /FontBBox [-35 -250 1148 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 70 /XHeight 431 /CharSet (/J/e/fi/h/l/s/y) /FontFile 185 0 R >> endobj 187 0 obj << /Length1 1911 /Length2 12079 /Length3 0 /Length 13273 /Filter /FlateDecode >> stream xÚ´TØ-Š“@pÖ¸»KpwK° 4Nãîîî’àî®ÁÝàî ¸>fîÜ;sïÿk½·z­îÞUuvÕ®Su(H”T„¬ @Ö`Ff^€¨¼š 3€™™‘™™‚BÍÌÁôo;Ž™5˜÷¢v  Ã›M èð(o È8ZXØ,œ¼,\¼ÌÌVffžZÛñÄ€NfFyF€Œ5d@!jmãjgfbêð–çßÔ†4.ú?„­@vf†@0@è` ²zËh´¨Zš\ÿ‹‚šßÔÁÁ†—‰ÉÙÙ™heÏhmg"@Cp6s0¨€ìAvN #À’ @+Ð_Ò(j¦föÿr¨Z;8í@€7ƒ¥™!lÿvÄl²¼e¨JËm@àËý+€ðWs,Œ,ÿ¡ûëôDfà? ­­l€`W3° ÀØÌP”ctpq ÁF-í­ß΀f–@ƒ·€?K$„•À7…é³7´3³q°g´7³üC#Ó4om‰Z[YÀöÔ'ff2|ë»+Ó_—k¶v»ÿ›ŒÿaähÃôlfë’û+æÍ„ð·Íäà`ffæfc€l CS¦?¨¹Ú€þt²üa~Óàéncm0~“ò43½ý ¸Û@;G§û?ÿXXFf†‰áoö73Èø_øíþíÌ\ÚÌoãÇ`þãóŸ:ofd ¶tý;üÏ+fR‘Ö ûKòœ""Ö.wv+€ƒ ÀÉà ðüo–ÿèÿ·ö?­J@³¿jûŸ4ØØÀó/ o½û· §¿æ‚ú¯¥¡üwë·i¨ÿþ¯Ì̆o_,ÿÏ+ðç‘ÿ¿Éÿƒåÿ:üÿ[‘„£¥åŸ~êüü@+3K׿"Þ¦ÙÑám3ä­ßöü¿¡ê ­³<ÈÈÌÑê½ÒÀ· ›Xþ§‘föf. #%3CÓ?'æß×ðÆni)YÛ›ýñÞX˜™ÿÇ÷¶r†ooŠýÛeýé½mÔgZý±z¬œ Ðùm¾X98î,o;jrùs´LŒ`k‡·#€7užck;„?®”‡ ÀüÃô'bg}CöoâÍì-þcäd3:üò¼Å -ì-ö¦[yL†ÿAÜoÈÚòMÔ¿-hc2úd0þßHÿÙL&ÿ€oüŠã ¹Ú˜‚þÉþf3ûä0™ÿ¾‰´ø|«Îòð­t«¿áÛB1ýƒùm…™¬ÿÎýûöÈÿÃýV¸Íßî·¼6oݳþ‡R–·âíþß*µÿûÀ[eÿÝH–7Ž¿»ý¶2L¦v ¿S¾M“ƒ³õ?¼q8þ}oü¾ìö†Övÿ,ô­rç¿!ë¯ëße¼uÄ d÷/Òÿš/CG;»·§÷Ï'àmøþÿ|çA !Ââ¼µ!_€yM@Û]•0¾3Ãîø§Š]õ÷E»ŽÈð‰4•~ëv7‰Cݨ+ÛâÔ×BKÄÏîÇÍuðÁ-ñÊ­Oz±*S»­?'±û'òŽ…kûß0¨ íy<Ûz|ñµ€n†ì¡È²uäFVÊÁ¸sî•t©í+Y šßUÞ«ä”E|*™fˆüñÕ·p–"ÛàÛ.)œá;Zôs”Ùë›ổWb™X:Ï“H¶|w­ Ö¨û9·Õ25VûN¼ÏØUÕ·¡­±9F^À¥3vv–ÌQl*èÕÝ ~bGg$ï ¯àê¾·¹s­y|-{|Z3¡í6¬m¼õa k¥QdUì9ØÖSŽàj»Ó#Ï<½˜¼Ú½Ç|âÄfÆeÏEõG©ø™#2|^b* *F^ZÅPìu5û×÷•<­ï¿vÑhá-I|^f´½Ø{a?ÍÕJá–}tsv&¨wµL˜(æ0@o$67Œ=ÕÂ*ƒBN £çÊÌ›*‘­æ½#’Y6ªšj•8“Þ¿íÒ+É~4B#3¡«y8þÔx p3«õ-èÝÔ˜¬N¦p&šɴ´Í¯UÓŸw—܉/>–¯=2N™)ØÍ~0w{ƒ±—„‚kjcaÜ¢ ]žA-ò44|Y)Ñ-h¢’*[\«:ï:£ä×ÔùŠ]–ÿéºdK{” '~Q§ŠÌ+eTk¦Kë§ë°Ë`eDMpõ€¯:¥˜vìÌ!D:%zýnË)Ak ’ç½g{ìzGÏðzÞœQïy<2kiDЏ~¼©{t×ï=4#ß8CëbÕ4‡½§Y‘Œ9*p²‚Äh·‹QccìÎ,ÖéÁ)TºŸyøO爩²ÝÔcb’ñ®PEfm¨JvÚ*ÃòFw…R}Å'|uÀ¨1çüÙJ¢÷ãê¯RÂouÉøKs©Cl1²^ÒØAù\BØj\Â+òŠJÈaŒ|Q«1RÃtfAÕßù~^™”8¬¾ifIpŸð›n\ÍBšÊñÁaÁëÉ­‘ÐULbø–øí²»À;^7ƒä1Š–ÅÄùvŸµ3›© +³‰­C¨tëk—Û2ÐíhŠ…à&´‘q#õü·o¸¸‹Ÿ&UË`ÉíGˆ„¡÷'°y;ëÖ9¸yC̃g–‘Ow£l>™Ò:Áa]®M5¼Q£;HÆóÙÅ+Gáñ»GEÆ&'6ÙüfÄŠDÔTîÅÑs5#ÈÎ¥/ª{ª t*n±×‹‘)ü­ZÖ‰ñÎ=O¢[‰r‘¹"ë™È–ØS ]ÿ®ä3­‚L8ÄãÅWªÄ˜ò dHE÷)‰”Ðàfºú ïãÝÇjFž’•ðì ]Ö—…a·ÕáܸtClâ`\}6]5d„L%'ÊUUÛ]Ge±:·**é%¢ù¢0º•ϧ‹­Iå³|pí-ÍhkšÒ{«‰Ÿyùhé,)r]T¨øl3V¨_^~µ•&ÏS ·£‡)c2màL²•üa´Í¾×wXm:¢\¬ÚÀoˆWÝ–DÇÛ¬?Û¹5^ÿõ ¯>‚j·[ÃT®ûƒšZ´t)X*d¹Óƒöc,î2ê¶'K}õf~Û7Åçfa@UDd²ŽLý ¦T“¥yï¦44ësÇTYӉ⬅>å {5®l/£è‰Ù˜,ON‡‹T†Ó–øÓ,»‹QÈntÖbËSXZ/ýÕ÷B£-K*ƒƒU[ú$©F€b|Õwßæ{ð­V¯ä%,¼­ãQã@õ¼|TûU—Éãá¬4#¼õ©mï$ôÍ–v”á¦ÍÝH=ËY§5Š,Ä uÒ/wá“öòÛ„ú‚´ßëG<ñP=Ð/3Ð!Ћt§— ©—X:œ2å!5ž~ ›Ç|ùíoÁñ騟2]3ûÄŒhÑùwЈNî· 'ÑÊp%Û¶LõZ䡾„ÿ– ¼"Igé‹[ö@O®8# w®p†ƒ>]ò¸õÑâQ»Šr$7Lý=ïr mŘÑþgÄxFiSÛØ…—"Zfè,Û3Ÿ–jŸJý¬ÏïûØú‰£7¸Pz}x´Ù<"Ï9옡7Ûôÿ|yüÉ ¿ž¨žB`+&×÷£-Ê}åT¿3~ÐÈ9ßc!IRæÕ©1ã@Šª]‹< t"õ§üxwdÞFTt¿êhHdÞ;~®u÷J9›5´žÛ/4è›Ã+lþ'©jÖyO¢`OvF­W»Á*÷V;œ®ÏZ¯<â%™ó³’›Ž±ìŸzõ4À—BP5Baƒ›P&SÇY"Òö Ô×úK_à‹_¿¬|(NQp„£ãy]BaçB w•D¡žê~Y_G*òEêî #-wÞB¶VìÖKð(3Ôz!pÉÛójÔò&^m¿ßæ‚\’vñ cöHDZ!_‡à5;eÌㄪ˜ˆÔYÂ`,Fò|~–8’©$E×¶ÑéF\‚¶7øÙ•5ÞWtôŠÛgb.Þ-{­].H°Öç*牗H6œ¯âú![ý•bT#!à†üg0/ŽÁÍv„®QšÈ8ѼŒ 5$§6ƒí);IF䔫&„>•|ý354bù»ÊÓayŒR%a²~ãX5Rc‚RAÐmò‹F!eœJ{¯øÀ1¢N«œÏQP/'̇ ASnÊQ,& ª±ÿMR< N sHý¹j£<_8´3¤Û–urNr¬FÏG_uþuó]³-.ÎýgòvöjdU]-`¿Xn—Þi<[ÍQùÀº™wõòÓ…'a½xÝHõ¶êðÈ3c|GeË ¢Ñ#v¸?Ùïai¸1¾V%ôCõÍØ*/‰O‰-ÒÐô ¤ƒ‚éßâ}o¶ D2'ÆŸ¸=V–%'¾¯­þúÊ×"õÜ¿ gȲ^éB¬1‡™ÅB"È»µ‰Öœ´‹Ší@FÔ³-HÑ@›3<¾ è=Q àtºvsÌ‹2ðÞ÷Þ̥ΰUßnÒ®sŸ Yúä=/z©YOí/‹ê‘ªìî®&ùY >M^wùõT/î/löYG"š⠺Τ„t…š…Ëyº¹‰Áw©x£wŒÔ¼][¿J3#&¡’)òll;J®°½ËtÝ\è—ÜuãÆ uìÒ·8­+ƒê›¯³×ʤâÕVDŸ'‰Š|“¶[¾:Ü÷䘮M"!ÖrvH>;ÊÈ©w}ž´×þ÷´áÈè%Fö9Øé¢ n† ­i…~’^cÞ?»›¾ƒG¬á„³F¥èaÛ:önTƒ¼»@uẒTv\:„g¨ÇõO2Dj—åñR!XÜEš›Øà&ŒÉ ÷§j_”¶»‡wß^§=•žNz±r e\j¹gT–7q¾ºë;®¾jc…à×^Q6³u…D?ru³û)È×½„O\¦>gI”[”Õ ÖÂ^¶+šw$ÿøX±¾´GW¯ú87i_,?÷%9œ¦ä.%éw×|‰Ì…æ—‹‘tN–®g8#29lA ùºAA Ò¾tƒÂQå.d‚_íÍÆ†“3™vu?*ùM,½"%ÇrhVÊN|òUݽÐ96B Éóу瘓²ßð{¼^Áê?bºÜj µøB°ê¸g²ãðœ>†êIÅn™8™°+t_Ù¡§(½ÞÌ…—>Áä£ ãæÊ`d7†ë‚dŒŸýc”øKf}jþâ.`a¦ó¶Nõ[ñ6UæG|7w¼æcƒúüC %ƒw^ý¾?˜³«»{î ÆÜð·¥gÊIÔü›ÂUJÈgèó‰üŠN˜²D òN¶|)ÅS฻jSžäß;¾Í8aOþ¹ÔKŸ±aV¬©¿ÞL ú©£Ii{%›GÛøÍ«¿Óm¥…ÍÕ÷óžè¤PP²fn~¦˜NËȺ•ã· qÎGOÅCu0x[t Ê‰Œ}¶wÊ;ëê aƒôy'¢©f‚š·W퉭–­Lñ É,€2ÆJŸ5É,h}9×(УsH`Éf¥žGv_/ºûµmè¿P•[Zä¦D«hŠÄ“Þ5%c 7r%/¥­{¢5ÇiŒìX„ì³=ePmÑ©‚<¸®½2]îx$Úãæá†ã‰˜Ž£¿R̶ߙB ð(8 áÆòøµ:šîÙíÈø8#jy4taÂ’‹jO™…-€Îý§Io!k6Úûù>²yǺIlj²ß¨ÃÿT%N‘Ù,ü~HãõŠI‘Qh Ý¦(ØsÑLJ•©â¼Þ< ^Α+Hú]}×Ço®Bšó,*AŠê«QØìý•½'kž»²0óG™#x(,36Çt6(µt[ŽX"¯ã‡8þCÖÇN.<aÏ@ßÌÔùr³ŠœûL¨TPú¼Ä³? ê:êb‹ˆZ ±.¸M"¤!ɯ%é_Gåõ]=% 2p†i ãV`×~'¥½rmÊ"’p‹ ÿˆ²„b\ùe}M4]?çâ„ Û *8ƬÅ_BØv)¯ûÝZjsþW¿Fˆ$‹¤ë5°ÑèC÷ž¹}ƒßJ²Ù)ÒÕ„™G °Ž”ˆå°àôk9h¼Lºáƒª=Úˆ´ZcÄܬÓ%ú"è >›ø½J«…“%¹G¹Ùí ³­Íùeˆ);ëm©åÚT'·‹ýô>ÿsPÈâ{´~ÑÀ(¨Øà6¥E°ô U%Ðå‹èC7íæöûlÈV¯pù]QÑ«œÐŠ„kæiR»4|ûôqUÑŠ=¨OÝӮõgguùI XÈ«8äÖäÑФ^°ç¤Ï X‚È2ÐexÎ(S¥£¡ɪ}&Që †´­"htEåX+ê`£ yÏ MÇT%èF¿r§´}CA=y -ë^ëUÌ‚¢ÌZÿi㬠h/œõSÉnÙ§ŸõÇc!ô™¨Ye)Û&C:PâÜ‚Ð)™?õ! Lú6p…(ûã[‡¬¬fÐE#ï©™´{…¶=øD Ö!t€vœÛs×HêMôPm¢áaŠØ7¡Ê'¡šúEûú2z"•D¦…³¶‡ÜHø†/'ð;h{;ääoË~í§t$ÈËâ%Ý ¬eÓ¥÷ÀSŸ¬›ðçL/Ùâºæ"=bUÚm ÑÎK©ŠQö Uæ­¥ç¿|í…_Ö1›W3 ÔÖ[ת×;1"¨È}IàÈ«,¢RàvF‘¡€§çuŠ@& €nš)ùUì½,pÁæ›Ðü¥_kõá¶z¼yùëW1©ý†™­}ïG-ð0aOQ:Û^whr”:¿Ú¤ÿ§õcVàù‰Ê}ãkfýËJÙle&ô– ¯¡y [Ÿ1+‚B\=/›¨h Ÿ"ê°)¿7ö`­° ϧŽÙ``Ü î ;æÃƒüHkXà ¥§ÜØñ[7n>ûræíÑ :ƽ@ƒ£"r‡›Ò–#ÆÏ¡ù™.é§J÷R~þt§“Û•¦uìQ·ù«`þÄ1ˆ‹¤ÁÉÜUžQ;¸5Üz_Ò ?‡†Ôár×ÃÉ’ùì/'õ$ÜîùéYÜÕmfèïh×ÞÄJy"qê´„Z¢CýéaŠßT}}Þ3×úÌ£qZüÆç;[àvUª9Æo<¹BýÞÍöc/2t¥Óâ4I‹VD»³ 6 ‡¥¬kõÕîÀWàÙ)ÆRK¾CüNAçÜ&Æl‹Îá1ÛæX7@{V¸­!&¢r–ëFB‚Ü¥G¯1'M<„Pwªu•70vJoλ' ¤Ÿ ’‚¯òGjh“Ôö3<íÅ¢Œ/Vêtiª£”FÇMK}=΋6ûD2’œuàÆë§í H#?z˜‡™Ò©ËÞ—¶tªpUºZ|2Š˜Ñ&‚ös@kq›rÞá›2…0ÌçIª<Ôø Ê}‚îþ-yî›f™ »–}ó9¹]ºCÚsðMͺe¸œú¨ò,Ò¶W'!Ç=#µô?;”ç·#êÔ{ÊÂK G2acJÅ0‰*qð"‘Yõ@ÕŽ†ŠD¥W5Ɉéíå"ñ¼G&ô s.v*¯Ù`{úòuX¿Èž©†Åê+IWôûUø`³Ã+£Š‰Q"ÙBYAÚ¢îư¹4\HSÉërë@Ebiš+´™ArÚíõ•uŸU½© ”Ž?fÏ`³VȈU…Ðlõ¥B5•l¶E(ôÛe=E³ŸŠ‘rA€s t8ÛÄjïgÁà o1…†×h‘2?÷BËNêøOt‹-,81#ÎÉ6Å-ªÏóѤŽñ^—ë ÓYÀŸ¿!®Fû´ËÃ÷ †”–!ø %b¾¯·w½?cjjEñnŸï¹Ü U7ðQš†Þ#&ñ62Î/ó’X—xdG¸ò~†<(æ9S‹çã¢F|–*Ú§ mŸ è¤=ª #×)Èáâ],ÅöLmø½…¶¯×óýòc¨Á¨­8ô> †úNï}ŠäﲚX9Wt—Ã;rÞõðý]æ3Ûü8ÆßBŸ_â)¿¹ª4óÒúç*BYò¬ái“ ÏÃDSíI)UÂ0%u¼ÎÔÆðë¥5ÜÒÌcg9š­Âã*=6ù‘ŸÿàÊ >;§2[„4‰ù.שчŒe&¿G—ÈNðóñ•€Ã'Ѽò9Oë*°ò¢TH féô aQ" YxŸ¢rØË>5;¡x8ß$¡Š š]«Æ »~‹kl¯[]Ì’È_uú¯B…@"}HM”Gä‚E©ØÝ~Ûs[ïÇ«vÝ7ck,ãkÖ•²âöœF¿ª(R÷Ùì‹>VwžÍp­ Hÿè°&¹ÝQQÁ¥ §ªÄ5šÄýÕ@ÑVMsÆà1€ô¬!Gk<’k›ÊïÆ‰GwÙBž€e6Ę@™TÐ% g¿':Õý «ì´W&ÓÝÐGÓ©caSú¼w^«Š®d u‘=C a¢øëNKª6—ªPá ø™7¶UryžP®ax¼Ùž7|—†œmt¥ËŠû…ÎÙxª¬Äù*4 L§d·ëàì·†µ; ù¥ùc¾ÖúÝol¯Ó†vFïiü—~úc‘Kt d†Ñw¸`,÷7Tdæ7ÖÖ­XeòÂXVÄDÁPr5yW)³ÀÉCË«*ë²æm:Ä¢|lAË<Ì->.ŽRžËLõî…P|´uLó2®[ó÷_Ü1ѳŽúüfÊãè&¦ó4w<«Øh¦_taôœNÅ­ kÆ'íûnÐ6çy éɼ÷ÅÉ{‡(/»ŒV‘©Ì~ÄO{¯Û†8b:Ô0PÜúÖ¨†ÝOÑ6ù´U}Æ(ß•$ÐI(dCÑ]>S5ðmì8ËólBlOÜ%§€¡0»¨FÖ#ä»ßyóë<²V[šv¾'Ovrr‡fÆ ,äa"‹[2¹{5¥‘½2©0ã™D¡ûê‡ÒÞ²2èÕFê(ôç2r/S+Y0J[¹ÿ!qùsñ½âr6P0oºø£švé´„†Þ¬Üë‘ð]¬¦†‚¥’Ì2­ÑË7oÿ*õ¤g Ðc¨ÎºƒÉîþä~³ÖÇ„‘N5aͽ㮊©B­I Õ2B­•âŸBÇ …ÉQñk1%mæ#i€—²±}[œ‹îä/#Eõ©M‘ò,tç7*‚×g…c­$ÍA-ûðA~9m ?~f§+]­berb#›Hÿöh§~­}¼$þãòY·óà¬â/…5öý÷Ä1{mùñpj:"-Ùu/b¿o¬PÊËN“/Üý‡½h I§ÌMÔI_Îk|dFá¬D³$¸®‰ju«¶AÍtuÁ¡Ï¬Wò—Ù«6`·o%Êà  9_cÑaÛ%d4]Q_:ÐG£µ¸'¯ì+m޾ƒ#·ƒqÜ×:TH† ôÈQaÆQ<£º.'.¥ =¹¨¯¥ïkÁ‚0gW«çýÖŽìåEÝà=òÝNµZ÷À}&P³¯{ÌYåwÌlü‚ü6Ï“-h¹3›\  %ißO —F“cä÷K½v”¨¥7îÎ êötƒã„‡^ÓÄpÊdQrYuo ƒšÄûáim"îe%•ט Éz“Û¸€=t*†ïê1ƒˆntó1?sþØ·êP«õò,±/i¹“ ‘¸õ–òHÜ~ ak°¯; UeM¼7ĤÍŽ€¥ÃºüÕ”¸A…¬…‰½ºË ×@4e’@z®›×]–PŹêä“;\)£NEš˜GL¦g楦.¿5ÿ~Ü­%í@@DñÉØ'«×Ä4mÒ`hC£„{%S{iðã~»ü[•*ÏpŽ­¹Ër|Žÿá ïhÀùNAxnøö½Tž4]ÊÇ´m1ö3‡ôm'YÐ) YÇ%ààmb#ðnâ^‚Ý$s¤‹~^ýøˆ•¹œ:ù| 8"¸rMÍkÙ‚ÉMÕïîa÷—§gÃÂÌŽwI1÷ A $©ÍrèËÆ’¾™Eåų.÷¦Q ?ûkxÞ¡¯K¬¹÷ÇO“ž$á\îgȰ¥ª°ÔF<û%ÍjÂyG˜ˆžTSÓ ϲßê,øn5ØÒýö– ¤¼¢Û Ѩøˆ†·IËGI\|²Âƒ›>º­å¤Œ·®<>Z5,H_þÓ»Çí]íëYò]lŸ¿Ùç'Žz:³æq0ïxë. ’Ùï˜Î\'u˜2>λynC¿›X ITn^0G¤­~l]L™šg„¶cÐ8·Ë٦䅳!è•g² üžu³†IÊ  [ßaÁJ:b Ö¤ÓÆÚ$Zññ¢Ì æË·!-¸·Á áùïÛ]…•º Æž uÄÚp`47˜<;ì¬ÂÇ ÷?zfÙä·÷[ݘ—•%ÎÙ½JM®«Ík§ÐÔ?À›ïðbþ‚ý¬Á[p{Û”¼vüqÞ<Š˜QeHU²!Ô pµî†—æ®OÈ»ûÈ$…ˆ%]«½AÀò}RH]"¿C ôÞ€¨3?Ò‹²S½Ø ×¥çÌöwíæ_!‘I$éIçÀíŠ:ñPøÓ¯® KNω ™®JÜ»¯/–éƒü]‘¹. *}ë_1Øë›d—)µ¸y5ç$K­ˆøVúÂÏŠ›¨X,ñÜk·kpgá°­6ÔÒÆ™!KÍèUO†6†Ñ”¥ò”Ûõ‡ â]¦T^»:Þ•kJTL¦­äj{=ß^ò³s?DÀÂÜ%°Ë <ÐYa‚:¡…¥I|Þ¯ÒOõþ¿ åI€¾ÛK³Ûy­¸S/ÀùIšÆ}„²,$¥W 7Ü“¬¸‡c:E(‹§SBV?‡À!¢5á©(3ùë£\|…¤ ûùõ’ñÄ `Òu,PÀWᆻ’˜ÂK™X0÷œÝ­ê5Öd@<‰¿ÄK{žÉX:‚×DÿY¼QüãT¤à;¨àX= ÐúE£, €?÷ˆï-@W7[XiÇ-GGàä–Ò ·Ê8èRUœS‘glïh à^I˜Ó̲0®f\'*±uœ6­O¾SäSsûÙƒ5½ýI&¿] 5 U¤mÏeÙ—¤[úaý1±¡Ð!#C>ŠyÏ]ÿ6ÀÖñWE@¼0”†ÙäÞ¨à°È6ŠÁ §Yûs )ÍYgo,ÖBE&÷‡IUÔGˆµ÷uÇü—íROxéa+";Ì~äâæ,ÃbðÒ^?ðXEíÛ812œGD²{¸bšïŠ *Ät$NÓi„Ö¾ÌÄ`$Jö«ˆß¨%,Ö¶&tç³;hÞÛ6ù@plØË9ó>‘•×$]œ=;(ÃBˆ2HbEëXncßSuW]’Ê ~rÄ[âôåÕ§ŸÅ@ÜàÃ8D[¯jÔÐA: I5»º-MxVvµ"òž¾ £i²w€ÛÌŒísä–ôsÝm:A‰ß-AhÎ,TX®%zf¥RÉýÞÁÖÖ°;]Ë9N¥ì©²2½²ŒÇù™Ýž’Pî@X¦3Oð[û ÷H0úkú¬@Læ÷Xm`qk%Kµ¼ÚC¸’sê:ÿ±ô™VÌ*äSfñÅð}ìÊ‚d ùañêP:õ%Ûžê<šB¥Ä 3 Ëò812…ÞΠ[ÎUÁó±ÛýšlH«`à‰6ì„:¸ò¤"Òt{UÌTµa¡†0+gÃ&s(jŽ.œùóKÂÑäÊ Iù nÛϸº4‹#MOHT# \¤ß¦Öµû-{gqëžôš®ö¾öÅÆJFs²ÐM‚¸¦½}?ú;Õbã¥$ñÌÏÌvÖuÕ™ÈwÔ(çMhÐè± A4Zû©(ñ„ˆX(&ދߕ˦.år»Ú­m÷¼3Px”¾÷9é‹¿ñ]ý¬Ï¿0ß÷Æ¡ …ŒðØ_5^oû’gü³g„\Á5·õ`NüŒf„¾¾™S4Ù;æ\&¼¿‘óÔxÅF—²*†ÚÛïŒvÓˆŠyÞ+&·ÿ³‡‹=É;!l³Ø+‰±ë(hºv÷é¢åï( C°<Š'þf,N^¹g™FõD±I*y¿JY T^h¸òèð˜M¨bSž^8ÜXÓ•ó×>>w‘Y—1ü”FᜅAjûŒ£Ï|GPTzD´¤Gi D`†Œ ê@qQ`ùªNÎu"¬âñÆH±=%ñÅ@ ¬üV/<í`¡â› *õ€Æw̧ˑLmþKVóÜEÝtîa™4ÓÈøù½^Êò¨Ð6ºyôÕ’½¦„ÞcL«z °J™Þ>Éb\v—šŠ×ìË8òžyæ«5øËø¡çó®’(¿é&–NŽß#Œ37³AO_w‰OëN®Z1±tØ;]E‹º i-HüK ]°~tª|Én:‰²z‡ÞxâÇl˜Ãkýd’1¯ÖKm÷Â~4è‹ >ì-{ØT[¢_Æ'Þ³H€9{ÊßE!C-h£Ùg ¶¨ÔØ0Ù|ùdmïݲfàX¤ôÉf;ÅÀ¦¥zï‘B‹‘ÿIˆFÞ™ò`éu 6ùáÖ?‚Õ‘ðÐð•Œé©®÷•Ö…¿ê´vóåi¢®wh.¼kèjqõ«k–õLÚ­k€AZEJ}Äð5ϺøÌ²qAÌȥá·BÈæ·àF¿ÙGûÙÚŸèAYD„¢²‡“ÖL_üÅþž`ûHªÒ¹=ã6¹XX•K±¯\7yÆÍÿ6º`iqä.¬»í»qH}¤§D)C­}†ïŠÆmó r:3Î\E›‘(øã±eçF!²M œÐPÙŸNÊ;™òL²2÷ôË„(jʉ_´r1YHYÌÈÙA”ÚÝÖ绘i•VA‘XˆY5*Ѱͤ°ë?ïÌ´¨ãöš%¨º‡Å¹ŠXÜFDoã´Ø®¬UËÌ%ÚèX”•å†V´Ñ>ÿVEñgïFóì€Òø¸£×›¿íxL2ÃJܹpry½—7×'éÄK§ö­=Õqwl"Œ@À@½×È\F !$µ…pæ;ž¾oŒî‡†—óƒïGvóÑ;‰ãËI=sŠ"›p/ˆHåñÀ™G‘¤ü“jX¬&UcWÓºƒdµ.ùêÛ)$H#wuJºö.ñë¹–‰ÌÁE†‘OÃi˜ íº´ü5#06l“Âð:a˜CÍñ¾/†'çÇ;‰b†åž¼;2:äcïᥑëµÔ¶ž³ ³ÅïÛYËV…Þ\ gÝa™Þ¾†àô5vJíDù•䡵MŽ_÷žÝFôädò—»\¤ÓÉÅò<ðq›n+Õ+ûµ˜Ô‚ÙNH_šHÉTz¢Ç—æïkŠyTBÉŠ qL‰,ìÆ|ö’‚Ö«YD 8|‰©ƒœðy’2Çd¶›‘áqg ¬!\~¿*<üò[…Mf áªéX>¹¸»^fíëëŽ!PèœëüNçlºv[+&‚!óûNÏŒvS½ ãz²’O/ʸ—¥¢^Þ(Ú*ãéú˜å‘P®ùÚI/†(Q¾mw¡-·ùô}¹ ññŸo”¯å Ž Û®©¤ë’Åâ}¬9¶,Jย,Êpà\±ø£îÉtuÚÑ7¸\ó ‚|ãmšxÀ»ñ-©*õœ$‰†LDÖ—dMªßßú  VÉSO¬á6°Âš1©9TáGÕdÈ„ÛkY× £®6fµFŸd“+ ŒëGTsIq>m¾T—SÁfœ¨ÅÍæVZŽÜKVÑjZ=È‹ë´ëtùëw“8q’Ñ`Š_’s&뙈‘k ¯7 Gµ–Ó‡qÄšºû¡¤¡BÐõÉl  ½ˆ2CáÆUÞTmû´w+ÍxÍ¿WdIiß‘ù3ˆ¸ÅŸ2‚xÒÑâ0'J—§Ñ„î=Bã¦ñBQiBÇ.§Ý;ÍEŒ •CÁæç°îÿ#ûê1 endstream endobj 188 0 obj << /Type /FontDescriptor /FontName /RBKAAX+CMTT10 /Flags 4 /FontBBox [-4 -233 537 696] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/a/asterisk/at/backslash/c/colon/d/e/f/g/h/hyphen/i/j/k/l/m/n/o/one/p/period/r/s/slash/t/three/two/u/underscore/w/y/zero) /FontFile 187 0 R >> endobj 100 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LIVWEX+CMBX10 /FontDescriptor 156 0 R /FirstChar 11 /LastChar 122 /Widths 145 0 R >> endobj 97 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LCHHCH+CMBX12 /FontDescriptor 158 0 R /FirstChar 12 /LastChar 122 /Widths 148 0 R >> endobj 94 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EUWOLL+CMBX9 /FontDescriptor 160 0 R /FirstChar 65 /LastChar 116 /Widths 151 0 R >> endobj 116 0 obj << /Type /Font /Subtype /Type1 /BaseFont /VTYAIH+CMBXTI10 /FontDescriptor 162 0 R /FirstChar 11 /LastChar 120 /Widths 138 0 R >> endobj 101 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YJFJHR+CMMI10 /FontDescriptor 164 0 R /FirstChar 58 /LastChar 115 /Widths 144 0 R >> endobj 110 0 obj << /Type /Font /Subtype /Type1 /BaseFont /CAFAUS+CMMI7 /FontDescriptor 166 0 R /FirstChar 108 /LastChar 114 /Widths 140 0 R >> endobj 96 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PXFSNJ+CMMI9 /FontDescriptor 168 0 R /FirstChar 107 /LastChar 107 /Widths 149 0 R >> endobj 99 0 obj << /Type /Font /Subtype /Type1 /BaseFont /BMVMOK+CMR10 /FontDescriptor 170 0 R /FirstChar 11 /LastChar 122 /Widths 146 0 R >> endobj 92 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EBUEXZ+CMR12 /FontDescriptor 172 0 R /FirstChar 44 /LastChar 121 /Widths 153 0 R >> endobj 91 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ACFCCW+CMR17 /FontDescriptor 174 0 R /FirstChar 12 /LastChar 121 /Widths 154 0 R >> endobj 111 0 obj << /Type /Font /Subtype /Type1 /BaseFont /SCKCTK+CMR7 /FontDescriptor 176 0 R /FirstChar 53 /LastChar 53 /Widths 139 0 R >> endobj 93 0 obj << /Type /Font /Subtype /Type1 /BaseFont /JSLKNT+CMR9 /FontDescriptor 178 0 R /FirstChar 45 /LastChar 119 /Widths 152 0 R >> endobj 108 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IYMUOQ+CMSL10 /FontDescriptor 180 0 R /FirstChar 46 /LastChar 121 /Widths 142 0 R >> endobj 109 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LNUCPW+CMSY10 /FontDescriptor 182 0 R /FirstChar 0 /LastChar 15 /Widths 141 0 R >> endobj 98 0 obj << /Type /Font /Subtype /Type1 /BaseFont /WOKQZU+CMTI10 /FontDescriptor 184 0 R /FirstChar 12 /LastChar 122 /Widths 147 0 R >> endobj 95 0 obj << /Type /Font /Subtype /Type1 /BaseFont /KACAPG+CMTI9 /FontDescriptor 186 0 R /FirstChar 12 /LastChar 121 /Widths 150 0 R >> endobj 102 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RBKAAX+CMTT10 /FontDescriptor 188 0 R /FirstChar 42 /LastChar 121 /Widths 143 0 R >> endobj 103 0 obj << /Type /Pages /Count 6 /Parent 189 0 R /Kids [86 0 R 105 0 R 113 0 R 118 0 R 122 0 R 126 0 R] >> endobj 133 0 obj << /Type /Pages /Count 2 /Parent 189 0 R /Kids [130 0 R 135 0 R] >> endobj 189 0 obj << /Type /Pages /Count 8 /Kids [103 0 R 133 0 R] >> endobj 190 0 obj << /Type /Outlines /First 3 0 R /Last 83 0 R /Count 21 >> endobj 83 0 obj << /Title 84 0 R /A 81 0 R /Parent 190 0 R /Prev 79 0 R >> endobj 79 0 obj << /Title 80 0 R /A 77 0 R /Parent 190 0 R /Prev 75 0 R /Next 83 0 R >> endobj 75 0 obj << /Title 76 0 R /A 73 0 R /Parent 190 0 R /Prev 71 0 R /Next 79 0 R >> endobj 71 0 obj << /Title 72 0 R /A 69 0 R /Parent 190 0 R /Prev 27 0 R /Next 75 0 R >> endobj 67 0 obj << /Title 68 0 R /A 65 0 R /Parent 27 0 R /Prev 63 0 R >> endobj 63 0 obj << /Title 64 0 R /A 61 0 R /Parent 27 0 R /Prev 59 0 R /Next 67 0 R >> endobj 59 0 obj << /Title 60 0 R /A 57 0 R /Parent 27 0 R /Prev 55 0 R /Next 63 0 R >> endobj 55 0 obj << /Title 56 0 R /A 53 0 R /Parent 27 0 R /Prev 51 0 R /Next 59 0 R >> endobj 51 0 obj << /Title 52 0 R /A 49 0 R /Parent 27 0 R /Prev 47 0 R /Next 55 0 R >> endobj 47 0 obj << /Title 48 0 R /A 45 0 R /Parent 27 0 R /Prev 43 0 R /Next 51 0 R >> endobj 43 0 obj << /Title 44 0 R /A 41 0 R /Parent 27 0 R /Prev 39 0 R /Next 47 0 R >> endobj 39 0 obj << /Title 40 0 R /A 37 0 R /Parent 27 0 R /Prev 35 0 R /Next 43 0 R >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 27 0 R /Prev 31 0 R /Next 39 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 27 0 R /Next 35 0 R >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 190 0 R /Prev 7 0 R /Next 71 0 R /First 31 0 R /Last 67 0 R /Count 10 >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 7 0 R /Prev 19 0 R >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 7 0 R /Prev 15 0 R /Next 23 0 R >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 7 0 R /Prev 11 0 R /Next 19 0 R >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 7 0 R /Next 15 0 R >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 190 0 R /Prev 3 0 R /Next 27 0 R /First 11 0 R /Last 23 0 R /Count 4 >> endobj 3 0 obj << /Title 4 0 R /A 1 0 R /Parent 190 0 R /Next 7 0 R >> endobj 191 0 obj << /Names [(Doc-Start) 90 0 R (page.1) 89 0 R (page.2) 107 0 R (page.3) 115 0 R (page.4) 120 0 R (page.5) 124 0 R] /Limits [(Doc-Start) (page.5)] >> endobj 192 0 obj << /Names [(page.6) 128 0 R (page.7) 132 0 R (page.8) 137 0 R (section.1) 2 0 R (section.2) 6 0 R (section.3) 26 0 R] /Limits [(page.6) (section.3)] >> endobj 193 0 obj << /Names [(section.4) 70 0 R (section.5) 74 0 R (section.6) 78 0 R (section.7) 82 0 R (subsection.2.1) 10 0 R (subsection.2.2) 14 0 R] /Limits [(section.4) (subsection.2.2)] >> endobj 194 0 obj << /Names [(subsection.2.3) 18 0 R (subsection.2.4) 22 0 R (subsection.3.1) 30 0 R (subsection.3.10) 66 0 R (subsection.3.2) 34 0 R (subsection.3.3) 38 0 R] /Limits [(subsection.2.3) (subsection.3.3)] >> endobj 195 0 obj << /Names [(subsection.3.4) 42 0 R (subsection.3.5) 46 0 R (subsection.3.6) 50 0 R (subsection.3.7) 54 0 R (subsection.3.8) 58 0 R (subsection.3.9) 62 0 R] /Limits [(subsection.3.4) (subsection.3.9)] >> endobj 196 0 obj << /Kids [191 0 R 192 0 R 193 0 R 194 0 R 195 0 R] /Limits [(Doc-Start) (subsection.3.9)] >> endobj 197 0 obj << /Dests 196 0 R >> endobj 198 0 obj << /Type /Catalog /Pages 189 0 R /Outlines 190 0 R /Names 197 0 R /PageMode/UseOutlines /OpenAction 85 0 R >> endobj 199 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.10)/Keywords() /CreationDate (D:20120229105849-05'00') /ModDate (D:20120229105849-05'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-1.40.10-2.2 (TeX Live 2009/Debian) kpathsea version 5.0.0) >> endobj xref 0 200 0000000000 65535 f 0000000015 00000 n 0000004163 00000 n 0000236329 00000 n 0000000060 00000 n 0000000088 00000 n 0000004221 00000 n 0000236209 00000 n 0000000133 00000 n 0000000164 00000 n 0000004279 00000 n 0000236137 00000 n 0000000214 00000 n 0000000257 00000 n 0000008375 00000 n 0000236051 00000 n 0000000308 00000 n 0000000342 00000 n 0000008434 00000 n 0000235965 00000 n 0000000393 00000 n 0000000438 00000 n 0000008494 00000 n 0000235892 00000 n 0000000489 00000 n 0000000544 00000 n 0000010762 00000 n 0000235768 00000 n 0000000590 00000 n 0000000634 00000 n 0000010822 00000 n 0000235694 00000 n 0000000685 00000 n 0000000713 00000 n 0000012897 00000 n 0000235607 00000 n 0000000764 00000 n 0000000792 00000 n 0000012957 00000 n 0000235520 00000 n 0000000843 00000 n 0000000871 00000 n 0000014662 00000 n 0000235433 00000 n 0000000922 00000 n 0000000949 00000 n 0000014722 00000 n 0000235346 00000 n 0000001000 00000 n 0000001028 00000 n 0000016482 00000 n 0000235259 00000 n 0000001079 00000 n 0000001107 00000 n 0000016542 00000 n 0000235172 00000 n 0000001158 00000 n 0000001187 00000 n 0000016602 00000 n 0000235085 00000 n 0000001238 00000 n 0000001266 00000 n 0000018099 00000 n 0000234998 00000 n 0000001317 00000 n 0000001346 00000 n 0000018159 00000 n 0000234924 00000 n 0000001398 00000 n 0000001426 00000 n 0000020031 00000 n 0000234836 00000 n 0000001472 00000 n 0000001500 00000 n 0000020091 00000 n 0000234748 00000 n 0000001546 00000 n 0000001571 00000 n 0000020151 00000 n 0000234660 00000 n 0000001617 00000 n 0000001660 00000 n 0000020211 00000 n 0000234585 00000 n 0000001706 00000 n 0000001734 00000 n 0000003936 00000 n 0000004338 00000 n 0000001784 00000 n 0000004045 00000 n 0000004104 00000 n 0000233101 00000 n 0000232959 00000 n 0000233384 00000 n 0000232098 00000 n 0000233954 00000 n 0000232674 00000 n 0000231955 00000 n 0000233811 00000 n 0000232817 00000 n 0000231811 00000 n 0000232386 00000 n 0000234096 00000 n 0000234240 00000 n 0000008554 00000 n 0000008202 00000 n 0000004542 00000 n 0000008314 00000 n 0000233525 00000 n 0000233669 00000 n 0000232530 00000 n 0000233243 00000 n 0000010881 00000 n 0000010589 00000 n 0000008738 00000 n 0000010701 00000 n 0000232240 00000 n 0000013017 00000 n 0000012724 00000 n 0000011039 00000 n 0000012836 00000 n 0000014782 00000 n 0000014489 00000 n 0000013150 00000 n 0000014601 00000 n 0000016662 00000 n 0000016309 00000 n 0000014915 00000 n 0000016421 00000 n 0000018219 00000 n 0000017926 00000 n 0000016795 00000 n 0000018038 00000 n 0000234356 00000 n 0000020271 00000 n 0000019858 00000 n 0000018352 00000 n 0000019970 00000 n 0000020417 00000 n 0000021082 00000 n 0000021107 00000 n 0000021169 00000 n 0000021275 00000 n 0000021703 00000 n 0000022042 00000 n 0000022395 00000 n 0000023034 00000 n 0000023657 00000 n 0000024320 00000 n 0000024961 00000 n 0000024986 00000 n 0000025637 00000 n 0000025966 00000 n 0000026410 00000 n 0000026840 00000 n 0000027515 00000 n 0000042328 00000 n 0000042621 00000 n 0000056788 00000 n 0000057133 00000 n 0000065130 00000 n 0000065362 00000 n 0000078322 00000 n 0000078618 00000 n 0000087423 00000 n 0000087678 00000 n 0000094932 00000 n 0000095154 00000 n 0000102325 00000 n 0000102546 00000 n 0000127644 00000 n 0000128174 00000 n 0000139667 00000 n 0000139952 00000 n 0000150550 00000 n 0000150816 00000 n 0000157889 00000 n 0000158110 00000 n 0000169958 00000 n 0000170233 00000 n 0000185176 00000 n 0000185492 00000 n 0000193035 00000 n 0000193294 00000 n 0000209279 00000 n 0000209607 00000 n 0000217847 00000 n 0000218081 00000 n 0000231475 00000 n 0000234441 00000 n 0000234510 00000 n 0000236400 00000 n 0000236566 00000 n 0000236735 00000 n 0000236930 00000 n 0000237151 00000 n 0000237371 00000 n 0000237481 00000 n 0000237519 00000 n 0000237646 00000 n trailer << /Size 200 /Root 198 0 R /Info 199 0 R /ID [<55A491BB4D7B80BAD47A9689EA742226> <55A491BB4D7B80BAD47A9689EA742226>] >> startxref 237972 %%EOF Jellyfish-2.2.8/doc/jellyfish.tex000066400000000000000000000170561323712541700167520ustar00rootroot00000000000000\documentclass[english]{article} \usepackage[latin1]{inputenc} \usepackage{babel} \usepackage{verbatim} %% do we have the hyperref package? \IfFileExists{hyperref.sty}{ \usepackage[bookmarksopen,bookmarksnumbered]{hyperref} }{} %% do we have the fancyhdr package? \IfFileExists{fancyhdr.sty}{ \usepackage[fancyhdr]{latex2man} }{ %% do we have the fancyheadings package? \IfFileExists{fancyheadings.sty}{ \usepackage[fancy]{latex2man} }{ \usepackage[nofancy]{latex2man} \message{no fancyhdr or fancyheadings package present, discard it} }} \usepackage[letterpaper]{geometry} \newcommand{\ddash}[1]{-\,-#1} \newcommand{\LOpt}[1]{\Opt{\ddash{#1}}} \newcommand{\LoOpt}[1]{\oOpt{\ddash{#1}}} \newcommand{\LOptArg}[2]{\OptArg{\ddash{#1}}{#2}} \newcommand{\LoOptArg}[2]{\oOptArg{\ddash{#1}}{#2}} \newcommand{\LoOptoArg}[2]{\oOptoArg{\ddash{#1}}{#2}} \setVersion{1.1.4} \setDate{2010/10/1} \begin{document} \begin{Name}{1}{jellyfish}{G. Marcais and C. Kingsford}{k-mer counter}{Jellyfish: A fast k-mer counter} \Prog{Jellyfish} is a software to count $k$-mers in DNA sequences. \end{Name} \section{Synopsis} \Prog{jellyfish count} \oOptArg{-o}{prefix} \oOptArg{-m}{merlength} \oOptArg{-t}{threads} \oOptArg{-s}{hashsize} \LoOpt{both-strands} \Arg{fasta} \oArg{fasta \Dots} \\ \Prog{jellyfish merge} \Arg{hash1} \Arg{hash2} \Dots \\ \Prog{jellyfish dump} \Arg{hash} \\ \Prog{jellyfish stats} \Arg{hash} \\ \Prog{jellyfish histo} \oOptArg{-h}{high} \oOptArg{-l}{low} \oOptArg{-i}{increment} \Arg{hash} \\ \Prog{jellyfish query} \Arg{hash} \\ \Prog{jellyfish cite} \\ Plus equivalent version for \Prog{Quake} mode: \Prog{qhisto}, \Prog{qdump} and \Prog{qmerge}. \section{Description} \Prog{Jellyfish} is a $k$-mer counter based on a multi-threaded hash table implementation. \subsection{Counting and merging} To count $k$-mers, use a command like: \begin{verbatim} jellyfish count -m 22 -o output -c 3 -s 10000000 -t 32 input.fasta \end{verbatim} This will count the the 22-mers in input.fasta with 32 threads. The counter field in the hash uses only 3 bits and the hash has at least 10 million entries. The output files will be named output\_0, output\_1, etc. (the prefix is specified with the \Opt{-o} switch). If the hash is large enough (has specified by the \Opt{-s} switch) to fit all the $k$-mers, there will be only one output file named output\_0. If the hash filled up before all the mers were read, the hash is dumped to disk, zeroed out and reading in mers resumes. Multiple intermediary files will be present on the disks, named output\_0, output\_1, etc. To obtain correct results from the other sub-commands (such as histo, stats, etc.), the multiple output files, if any, need to be merged into one with the merge command. For example with the following command: \begin{verbatim} jellyfish merge -o output.jf output\_* \end{verbatim} Should you get many intermediary output files (say hundreds), the size of the hash table is too small. Rerunning \Prog{Jellyfish} with a larger size (option \Opt{-s}) is probably faster than merging all the intermediary files. \subsection{Orientation} When the orientation of the sequences in the input fasta file is not known, e.g. in sequencing reads, using \LOpt{both-strands} (\Opt{-C}) makes the most sense. For any $k$-mer $m$, its canonical representation is $m$ itself or its reverse-complement, whichever comes first lexicographically. With the option \Opt{-C}, only the canonical representation of the mers are stored in the hash and the count value is the number of occurrences of both the mer and its reverse-complement. \subsection{Choosing the hash size} To achieve the best performance, a minimum number of intermediary files should be written to disk. So the parameter \Opt{-s} should be chosen to fit as many $k$-mers as possible (ideally all of them) while still fitting in memory. We consider to examples: counting mers in sequencing reads and in a finished genome. First, suppose we count $k$-mers in short sequencing reads: there are $n$ reads and there is an average of 1 error per reads where each error generates $k$ unique mers. If the genome size is $G$, the size of the hash (option \Opt{-s}) to fit all $k$-mers at once is estimated to: $(G + k*n)/0.8$. The division by $0.8$ compensates for the maximum usage of approximately $80\%$ of the hash table. On the other hand, when counting $k$-mers in an assembled sequence of length $G$, setting \Opt{-s} to $G$ is appropriate. As a matter of convenience, Jellyfish understands ISO suffixes for the size of the hash. Hence '-s 10M' stands 10 million entries while '-s 50G' stands for 50 billion entries. The actual memory usage of the hash table can be computed as follow. The actual size of the hash will be rounded up to the next power of 2: $s=2^l$. The parameter $r$ is such that the maximum reprobe value (\Opt{-p}) plus one is less than $2^r$. Then the memory usage per entry in the hash is (in bits, not bytes) $2k-l+r+1$. The total memory usage of the hash table in bytes is: $2^l*(2k-l+r+1)/8$. \subsection{Choosing the counting field size} To save space, the hash table supports variable length counter, i.e. a $k$-mer occurring only a few times will use a small counter, a $k$-mer occurring many times will used multiple entries in the hash. Important: the size of the couting field does NOT change the result, it only impacts the amount of memory used. In particular, there is no maximum value in the hash. Even if the counting field uses 5 bits, a $k$-mer occuring 2 million times will have a value reported of 2 million (i.e., it is not capped at $2^5$). The \Opt{-c} specify the length (in bits) of the counting field. The trade off is as follows: a low value will save space per entry in the hash but can potentially increase the number of entries used, hence maybe requiring a larger hash. In practice, use a value for \Opt{-c} so that most of you $k$-mers require only 1 entry. For example, to count $k$-mers in a genome, where most of the sequence is unique, use \OptArg{-c}{1} or \OptArg{-c}{2}. For sequencing reads, use a value for \Opt{-c} large enough to counts up to twice the coverage. For example, if the coverage is 10X, choose a counter length of $5$ (\OptArg{-c}{5}) as $2^5 > 20$. \section{Subcommands and options} include(options.tex) \section{Version} Version: \Version\ of \Date \section{Bugs} \begin{itemize} \item \Prog{jellyfish merge} has not been parallelized and is relatively slow. \item The hash table does not grow in memory automatically and \Prog{jellyfish merge} is not called automatically on the intermediary files (if any). \end{itemize} \section{Copyright \& License} \begin{description} \item[Copyright] \copyright\ 2010, Guillaume Marcais \Email{guillaume@marcais.net} and Carl Kingsford \Email{carlk@umiacs.umd.edu}. \item[License] 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 \URL{http://www.gnu.org/licenses/}. \end{description} \section{Authors} \noindent Guillaume Marcais \\ University of Maryland \\ \Email{gmarcais@umd.edu} \noindent Carl Kingsford \\ University of Maryland \\ \Email{carlk@umiacs.umd.edu} \LatexManEnd \end{document} Jellyfish-2.2.8/doc/option_to_tex000066400000000000000000000007621323712541700170500ustar00rootroot00000000000000#! /usr/bin/env ruby exit 1 if ARGV[0].nil? require 'rubygems' require 'treetop' def quote(str) str.gsub(/_/, "\\_") end require 'help_parse.rb' class IsOpen attr_accessor :is_open def initialize @is_open = false end end opened = IsOpen.new parser = HelpGrammarParser.new open(ARGV[0]) { |fd| fd.each { |l| r = parser.parse(l) if r.nil? raise "Got nil for: #{l}" else puts r.to_tex(opened) end } puts("\\end{description}") if opened.is_open } Jellyfish-2.2.8/doc/options.tex000066400000000000000000000225161323712541700164510ustar00rootroot00000000000000\subsection{count} \noindent Usage: jellyfish count [options] file:path+ \noindent Count k-mers or qmers in fasta or fastq files \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-m},\LOptArg{mer-len}{=uint32}] \noindent *Length of mer \item[\Opt{-s},\LOptArg{size}{=uint64}] \noindent *Hash size \item[\Opt{-t},\LOptArg{threads}{=uint32}] \noindent Number of threads (1) \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output prefix (mer\_counts) \item[\Opt{-c},\LOptArg{counter-len}{=Length}] \noindent in bits Length of counting field (7) \item[\LOptArg{out-counter-len}{=Length}] \noindent in bytes Length of counter field in output (4) \item[\Opt{-C},\LOpt{both-strands}] \noindent Count both strand, canonical representation (false) \item[\Opt{-p},\LOptArg{reprobes}{=uint32}] \noindent Maximum number of reprobes (62) \item[\Opt{-r},\LOpt{raw}] \noindent Write raw database (false) \item[\Opt{-q},\LOpt{quake}] \noindent Quake compatibility mode (false) \item[\LOptArg{quality-start}{=uint32}] \noindent Starting ASCII for quality values (64) \item[\LOptArg{min-quality}{=uint32}] \noindent Minimum quality. A base with lesser quality becomes an N (0) \item[\Opt{-L},\LOptArg{lower-count}{=uint64}] \noindent Don't output k-mer with count < lower-count \item[\Opt{-U},\LOptArg{upper-count}{=uint64}] \noindent Don't output k-mer with count > upper-count \item[\LOptArg{matrix}{=Matrix}] \noindent file Hash function binary matrix \item[\LOptArg{timing}{=Timing}] \noindent file Print timing information \item[\LOptArg{stats}{=Stats}] \noindent file Print stats \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\LOpt{full-help}] \noindent Detailed help \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{stats} \noindent Usage: jellyfish stats [options] db:path \noindent Statistics \noindent Display some statistics about the k-mers in the hash: \noindent Unique: Number of k-mers which occur only once. \noindent Distinct: Number of k-mers, not counting multiplicity. \noindent Total: Number of k-mers, including multiplicity. \noindent Max\_count: Maximum number of occurrence of a k-mer. \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-L},\LOptArg{lower-count}{=uint64}] \noindent Don't consider k-mer with count < lower-count \item[\Opt{-U},\LOptArg{upper-count}{=uint64}] \noindent Don't consider k-mer with count > upper-count \item[\Opt{-v},\LOpt{verbose}] \noindent Verbose (false) \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\LOpt{full-help}] \noindent Detailed help \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{histo} \noindent Usage: jellyfish histo [options] db:path \noindent Create an histogram of k-mer occurrences \noindent Create an histogram with the number of k-mers having a given \noindent count. In bucket 'i' are tallied the k-mers which have a count 'c' \noindent satisfying 'low+i*inc <= c < low+(i+1)*inc'. Buckets in the output are \noindent labeled by the low end point (low+i*inc). \noindent The last bucket in the output behaves as a catchall: it tallies all \noindent k-mers with a count greater or equal to the low end point of this \noindent bucket. \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-l},\LOptArg{low}{=uint64}] \noindent Low count value of histogram (1) \item[\Opt{-h},\LOptArg{high}{=uint64}] \noindent High count value of histogram (10000) \item[\Opt{-i},\LOptArg{increment}{=uint64}] \noindent Increment value for buckets (1) \item[\Opt{-t},\LOptArg{threads}{=uint32}] \noindent Number of threads (1) \item[\Opt{-f},\LOpt{full}] \noindent Full histo. Don't skip count 0. (false) \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file \item[\Opt{-v},\LOpt{verbose}] \noindent Output information (false) \item[\LOpt{usage}] \noindent Usage \item[\LOpt{help}] \noindent This message \item[\LOpt{full-help}] \noindent Detailed help \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{dump} \noindent Usage: jellyfish dump [options] db:path \noindent Dump k-mer counts \noindent By default, dump in a fasta format where the header is the count and \noindent the sequence is the sequence of the k-mer. The column format is a 2 \noindent column output: k-mer count. \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-c},\LOpt{column}] \noindent Column format (false) \item[\Opt{-t},\LOpt{tab}] \noindent Tab separator (false) \item[\Opt{-L},\LOptArg{lower-count}{=uint64}] \noindent Don't output k-mer with count < lower-count \item[\Opt{-U},\LOptArg{upper-count}{=uint64}] \noindent Don't output k-mer with count > upper-count \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{merge} \noindent Usage: jellyfish merge [options] input:string+ \noindent Merge jellyfish databases \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-s},\LOptArg{buffer-size}{=Buffer}] \noindent length Length in bytes of input buffer (10000000) \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file (mer\_counts\_merged.jf) \item[\LOptArg{out-counter-len}{=uint32}] \noindent Length (in bytes) of counting field in output (4) \item[\LOptArg{out-buffer-size}{=uint64}] \noindent Size of output buffer per thread (10000000) \item[\Opt{-v},\LOpt{verbose}] \noindent Be verbose (false) \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{query} \noindent Usage: jellyfish query [options] db:path \noindent Query from a compacted database \noindent Query a hash. It reads k-mers from the standard input and write the counts on the standard output. \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-C},\LOpt{both-strands}] \noindent Both strands (false) \item[\Opt{-c},\LOpt{cary-bit}] \noindent Value field as the cary bit information (false) \item[\Opt{-i},\LOptArg{input}{=file}] \noindent Input file \item[\Opt{-o},\LOptArg{output}{=file}] \noindent Output file \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{qhisto} \noindent Usage: jellyfish qhisto [options] db:string \noindent Create an histogram of k-mer occurences \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-l},\LOptArg{low}{=double}] \noindent Low count value of histogram (0.0) \item[\Opt{-h},\LOptArg{high}{=double}] \noindent High count value of histogram (10000.0) \item[\Opt{-i},\LOptArg{increment}{=double}] \noindent Increment value for buckets (1.0) \item[\Opt{-f},\LOpt{full}] \noindent Full histo. Don't skip count 0. (false) \item[\LOpt{usage}] \noindent Usage \item[\LOpt{help}] \noindent This message \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{qdump} \noindent Usage: jellyfish qdump [options] db:path \noindent Dump k-mer from a qmer database \noindent By default, dump in a fasta format where the header is the count and \noindent the sequence is the sequence of the k-mer. The column format is a 2 \noindent column output: k-mer count. \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-c},\LOpt{column}] \noindent Column format (false) \item[\Opt{-t},\LOpt{tab}] \noindent Tab separator (false) \item[\Opt{-L},\LOptArg{lower-count}{=double}] \noindent Don't output k-mer with count < lower-count \item[\Opt{-U},\LOptArg{upper-count}{=double}] \noindent Don't output k-mer with count > upper-count \item[\Opt{-v},\LOpt{verbose}] \noindent Be verbose (false) \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{qmerge} \noindent Usage: jellyfish merge [options] db:string+ \noindent Merge quake databases \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-s},\LOptArg{size}{=uint64}] \noindent *Merged hash table size \item[\Opt{-m},\LOptArg{mer-len}{=uint32}] \noindent *Mer length \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file (merged.jf) \item[\Opt{-p},\LOptArg{reprobes}{=uint32}] \noindent Maximum number of reprobes (62) \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\LOpt{full-help}] \noindent Detailed help \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} \subsection{cite} \noindent Usage: jellyfish cite [options] \noindent How to cite Jellyfish's paper \noindent Citation of paper \noindent Options (default value in (), *required): \begin{description} \item[\Opt{-b},\LOpt{bibtex}] \noindent Bibtex format (false) \item[\Opt{-o},\LOptArg{output}{=string}] \noindent Output file \item[\LOpt{usage}] \noindent Usage \item[\Opt{-h},\LOpt{help}] \noindent This message \item[\Opt{-V},\LOpt{version}] \noindent Version \end{description} Jellyfish-2.2.8/doc/transfile000066400000000000000000000013341323712541700161410ustar00rootroot00000000000000my @opt1_types = ('Opt', 'oOpt'); for my $otype (@opt1_types) { $manMacro1a{'L' . $otype} = $manMacro1a{$otype} . '--'; $manMacro1b{'L' . $otype} = $manMacro1b{$otype}; $htmlMacro1a{'L' . $otype} = $htmlMacro1a{$otype} . '--'; $htmlMacro1b{'L' . $otype} = $htmlMacro1b{$otype}; } my @opt2_types = ('OptArg', 'oOptArg', 'OptoArg', 'oOptoArg'); for my $otype (@opt2_types) { $manMacro2a{'L' . $otype} = $manMacro2a{$otype} . '--'; $manMacro2b{'L' . $otype} = $manMacro2b{$otype}; $manMacro2c{'L' . $otype} = $manMacro2c{$otype}; $htmlMacro2a{'L' . $otype} = $htmlMacro2a{$otype} . '--'; $htmlMacro2b{'L' . $otype} = $htmlMacro2b{$otype}; $htmlMacro2c{'L' . $otype} = $htmlMacro2c{$otype}; } Jellyfish-2.2.8/examples/000077500000000000000000000000001323712541700152775ustar00rootroot00000000000000Jellyfish-2.2.8/examples/README000066400000000000000000000010311323712541700161520ustar00rootroot00000000000000What is it? =========== Here are some examples on how to use the Jellyfish library and potentially useful programs to compute data from Jellyfish output. Each directory is an independent project which relies on Jellyfish between installed and is available with pkg-config. Meaning 'pkg-config --print-provides jellyfish-2.0' returns something like 'jellyfish-2.0 = 2.1.1'. Disclaimer ========== Notice that the code in these directory is not as well tested as the rest of the Jellyfish code. It should work but no guaranteed is made. Jellyfish-2.2.8/examples/count_in_file/000077500000000000000000000000001323712541700201145ustar00rootroot00000000000000Jellyfish-2.2.8/examples/count_in_file/Makefile000066400000000000000000000004231323712541700215530ustar00rootroot00000000000000CC = g++ CXXFLAGS = $(shell pkg-config --cflags jellyfish-2.0) -std=c++0x -Wall -O3 LDFLAGS = -Wl,--rpath=$(shell pkg-config --libs-only-L jellyfish-2.0 | sed -e 's/-L//g') LDLIBS = $(shell pkg-config --libs jellyfish-2.0) all: count_in_file clean: rm -f *.o count_in_file Jellyfish-2.2.8/examples/count_in_file/README000066400000000000000000000026451323712541700210030ustar00rootroot00000000000000What is it? =========== Given a number of jellyfish databases, it outputs for all the k-mers (in the union of the database) the number of occurrences in each of the database. LIMITATION: all the database must have been created with the same size parameter to Jellyfish. It is adivsed to use the --disk switch of 'jellyfish count' to ensure that all the database are created with the same size. For example: jellyfish count -s 100M --disk ... The output is a column format where the first column is the k-mer and the remaining columns are the counts in each of the databases, in the same order as given on the command line. For example: $ ./count_in_file db1.jf db2.jf GCCACGACTCGTGCA 1 0 CAAGCTGTGTGGCCG 0 2 CATAGAAATCGATAA 3 5 TACTATATAAGCAAA 2 0 ... Some details ============ The Jellyfish database are sorted list of k-mers. The sorting order is based on the hash function (a random binary matrix). The program works similarly to how merging sorted lists is done, but instead of summing the count of each k-mers, it displays the count in each of the sorted list. Because all the files must be sorted according to the same criteria, the size of the hash (and therefore the hash function) must be the same for all the input files. See the LIMITATION paragraph above to run Jellyfish properly. Note that the size passed to 'jellyfish count' is NOT a limit on the number k-mers in the file (only a limit on the number of mers in memory). Jellyfish-2.2.8/examples/count_in_file/count_in_file.cc000066400000000000000000000121641323712541700232440ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include // From a list of jellyfish database, output for each mers how many // times it occurs in each db. It is very similar to merging (and the // code is copied/adapted from jellyfish/merge_files.cc). namespace err = jellyfish::err; using jellyfish::file_header; using jellyfish::RectangularBinaryMatrix; using jellyfish::mer_dna; using jellyfish::cpp_array; typedef std::unique_ptr binary_reader_ptr; typedef std::unique_ptr text_reader_ptr; struct file_info { std::ifstream is; file_header header; file_info(const char* path) : is(path), header(is) { } }; struct common_info { unsigned int key_len; size_t max_reprobe_offset; size_t size; unsigned int out_counter_len; std::string format; RectangularBinaryMatrix matrix; common_info(RectangularBinaryMatrix&& m) : matrix(std::move(m)) { } }; common_info read_headers(int argc, char* input_files[], cpp_array& files) { // Read first file files.init(0, input_files[0]); if(!files[0].is.good()) err::die(err::msg() << "Failed to open input file '" << input_files[0] << "'"); file_header& h = files[0].header; common_info res(h.matrix()); res.key_len = h.key_len(); res.max_reprobe_offset = h.max_reprobe_offset(); res.size = h.size(); res.format = h.format(); size_t reprobes[h.max_reprobe() + 1]; h.get_reprobes(reprobes); res.out_counter_len = h.counter_len(); // Other files must match for(int i = 1; i < argc; i++) { files.init(i, input_files[i]); file_header& nh = files[i].header; if(!files[i].is.good()) err::die(err::msg() << "Failed to open input file '" << input_files[i] << "'"); if(res.format != nh.format()) err::die(err::msg() << "Can't compare files with different formats (" << res.format << ", " << nh.format() << ")"); if(res.key_len != nh.key_len()) err::die(err::msg() << "Can't compare hashes of different key lengths (" << res.key_len << ", " << nh.key_len() << ")"); if(res.max_reprobe_offset != nh.max_reprobe_offset()) err::die("Can't compare hashes with different reprobing strategies"); if(res.size != nh.size()) err::die(err::msg() << "Can't compare hash with different size (" << res.size << ", " << nh.size() << ")"); if(res.matrix != nh.matrix()) err::die("Can't compare hash with different hash function"); } return res; } template void output_counts(cpp_array& files) { cpp_array readers(files.size()); typedef jellyfish::mer_heap::heap heap_type; typedef typename heap_type::const_item_t heap_item; heap_type heap(files.size()); // Prime heap for(size_t i = 0; i < files.size(); ++i) { readers.init(i, files[i].is, &files[i].header); if(readers[i].next()) heap.push(readers[i]); } heap_item head = heap.head(); mer_dna key; const int num_files = files.size(); const reader_type* base = &readers[0]; uint64_t counts[num_files]; while(heap.is_not_empty()) { key = head->key_; memset(counts, '\0', sizeof(uint64_t) * num_files); do { counts[head->it_ - base] = head->val_; heap.pop(); if(head->it_->next()) heap.push(*head->it_); head = heap.head(); } while(head->key_ == key && heap.is_not_empty()); std::cout << key; for(int i = 0; i < num_files; ++i) std::cout << " " << counts[i]; std::cout << "\n"; } } int main(int argc, char *argv[]) { // Check number of input files if(argc < 3) err::die(err::msg() << "Usage: " << argv[0] << " file1 file2 ..."); // Read the header of each input files and do sanity checks. cpp_array files(argc - 1); common_info cinfo = read_headers(argc - 1, argv + 1, files); mer_dna::k(cinfo.key_len / 2); if(cinfo.format == binary_dumper::format) output_counts(files); else if(cinfo.format == text_dumper::format) output_counts(files); else err::die(err::msg() << "Format '" << cinfo.format << "' not supported\n"); return 0; } Jellyfish-2.2.8/examples/jf_count_dump/000077500000000000000000000000001323712541700201335ustar00rootroot00000000000000Jellyfish-2.2.8/examples/jf_count_dump/Makefile000066400000000000000000000004231323712541700215720ustar00rootroot00000000000000CC = g++ CXXFLAGS = $(shell pkg-config --cflags jellyfish-2.0) -std=c++0x -Wall -O3 LDFLAGS = -Wl,--rpath=$(shell pkg-config --libs-only-L jellyfish-2.0 | sed -e 's/-L//g') LDLIBS = $(shell pkg-config --libs jellyfish-2.0) all: jf_count_dump clean: rm -f *.o jf_count_dump Jellyfish-2.2.8/examples/jf_count_dump/README000066400000000000000000000033511323712541700210150ustar00rootroot00000000000000What is it? =========== This program is an example on how to count k-mers with Jellyfish and then use the resulting hash of mers. The program counts all the k-mers in the files passed on the command line. Then it generate some random k-mer and displays its count in the hash (by default, k=25 and with good likely hood this value will be zero). Then, it dumps the content of the entire database on stdout. It is equivalent to using 'jellyfish count', 'jellyfish query' and 'jellyfish dump'. Some details ============ Many of the parameters that are switches to 'jellyfish count' are hard coded constant in this program. They are: jellyfish::mer_dna::k(25); The length k of the mers. Here set to 25. const uint64_t hash_size = 10000000; The initial size of the hash. Here set to 10 million. Ideally, this will be set close to the actual number of mers that will be inserted in the hash, so as to limit the number of size doubling of the hash. const uint32_t num_reprobes = 126; The maximum number of reprobes in the hash. The larger this number, the higher the load of the hash table before a size doubling is necessary, at the expense of some computation time. const uint32_t num_threads = 16; Number of threads used for parsing the input files and counting the mers. const uint32_t counter_len = 7; Minimum length of the counting field. Mers that have a count that does not fit in this field will take up the space of 2 mers in the hash table. const bool canonical = true; A mer and its reverse complement are considered to be one and the same mer. The canonical representation is whichever of a mer or its reverse complement that comes first in lexicographic order. This is usually set when counting mers in sequencing reads. Jellyfish-2.2.8/examples/jf_count_dump/jf_count_dump.cc000066400000000000000000000051761323712541700233070ustar00rootroot00000000000000#include #include #include #include #include #include #include typedef jellyfish::cooperative::hash_counter mer_hash_type; typedef jellyfish::mer_overlap_sequence_parser> sequence_parser_type; typedef jellyfish::mer_iterator mer_iterator_type; class mer_counter : public jellyfish::thread_exec { mer_hash_type& mer_hash_; jellyfish::stream_manager streams_; sequence_parser_type parser_; const bool canonical_; public: mer_counter(int nb_threads, mer_hash_type& mer_hash, char** file_begin, char** file_end, bool canonical) : mer_hash_(mer_hash) , streams_(file_begin, file_end) , parser_(jellyfish::mer_dna::k(), streams_.nb_streams(), 3 * nb_threads, 4096, streams_) , canonical_(canonical) { } virtual void start(int thid) { mer_iterator_type mers(parser_, canonical_); for( ; mers; ++mers) mer_hash_.add(*mers, 1); mer_hash_.done(); } }; int main(int argc, char *argv[]) { // Parameters that are hard coded. Most likely some of those should // be switches to this program. jellyfish::mer_dna::k(25); // Set length of mers (k=25) const uint64_t hash_size = 10000000; // Initial size of hash. const uint32_t num_reprobes = 126; const uint32_t num_threads = 16; // Number of concurrent threads const uint32_t counter_len = 7; // Minimum length of counting field const bool canonical = true; // Use canonical representation // create the hash mer_hash_type mer_hash(hash_size, jellyfish::mer_dna::k()*2, counter_len, num_threads, num_reprobes); // count the kmers mer_counter counter(num_threads, mer_hash, argv + 1, argv + argc, canonical); counter.exec_join(num_threads); const auto jf_ary = mer_hash.ary(); // Display value for some random k-mer uint64_t val = 0; jellyfish::mer_dna random_mer; random_mer.randomize(); random_mer.canonicalize(); if(jf_ary->get_val_for_key(random_mer, &val)) { std::cout << random_mer << ' ' << val << '\n'; } else { std::cout << random_mer << " not present in hash\n"; } // Dump all the k-mers on stdout const auto end = jf_ary->end(); for(auto it = jf_ary->begin(); it != end; ++it) { auto& key_val = *it; std::cout << key_val.first << ' ' << key_val.second << '\n'; } return 0; } Jellyfish-2.2.8/examples/query_per_sequence/000077500000000000000000000000001323712541700212025ustar00rootroot00000000000000Jellyfish-2.2.8/examples/query_per_sequence/Makefile000066400000000000000000000005331323712541700226430ustar00rootroot00000000000000CC = g++ CXXFLAGS = $(shell pkg-config --cflags jellyfish-2.0) -std=c++0x -Wall -O3 LDFLAGS = -Wl,--rpath=$(shell pkg-config --libs-only-L jellyfish-2.0 | sed -e 's/-L//g') LDLIBS = $(shell pkg-config --libs jellyfish-2.0) all: query_per_sequence query_per_sequence: query_per_sequence.cc sequence_mers.hpp clean: rm -f *.o query_per_sequence Jellyfish-2.2.8/examples/query_per_sequence/README000066400000000000000000000010631323712541700220620ustar00rootroot00000000000000What is it? =========== Given a jellyfish database and one or more input fast[aq] files, it output for each sequence in the fast[aq] files the count in the database of each of the k-mers. The output format is fasta, where the header is copied from the input files and the content is a number for each of the k-mers. If the sequence has length n, there will be n-k+1 numbers, corresponding in order to the n-k+1 k-mers in the sequence. For example: $ ./query_per_sequence db.jf sequence.fa >read1 0 0 0 1 1 2 3 3 3 4 2 >read2 15 16 17 13 12 11 12 12 10 7 6 ... Jellyfish-2.2.8/examples/query_per_sequence/query_per_sequence.cc000066400000000000000000000063521323712541700254220ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include "sequence_mers.hpp" namespace err = jellyfish::err; using jellyfish::mer_dna; using jellyfish::mer_dna_bloom_counter; typedef jellyfish::whole_sequence_parser > sequence_parser; template void query_from_sequence(PathIterator file_begin, PathIterator file_end, const Database& db, bool canonical) { jellyfish::stream_manager streams(file_begin, file_end); sequence_parser parser(4, 100, 1, streams); sequence_mers mers(canonical); const sequence_mers mers_end(canonical); while(true) { sequence_parser::job j(parser); if(j.is_empty()) break; for(size_t i = 0; i < j->nb_filled; ++i) { std::cout << ">" << j->data[i].header << "\n"; mers = j->data[i].seq; if(mers != mers_end) { std::cout << db.check(*mers); ++mers; } for( ; mers != mers_end; ++mers) std::cout << " " << db.check(*mers); std::cout << "\n"; } } } int main(int argc, char *argv[]) { if(argc < 3) err::die(err::msg() << "Usage: " << argv[0] << "db.jf file.fa [...]"); std::ifstream in(argv[1], std::ios::in|std::ios::binary); jellyfish::file_header header(in); if(!in.good()) err::die(err::msg() << "Failed to parse header of file '" << argv[1] << "'"); mer_dna::k(header.key_len() / 2); if(header.format() == "bloomcounter") { jellyfish::hash_pair fns(header.matrix(1), header.matrix(2)); mer_dna_bloom_counter filter(header.size(), header.nb_hashes(), in, fns); if(!in.good()) err::die("Bloom filter file is truncated"); in.close(); query_from_sequence(argv + 2, argv + argc, filter, header.canonical()); } else if(header.format() == binary_dumper::format) { jellyfish::mapped_file binary_map(argv[1]); binary_query bq(binary_map.base() + header.offset(), header.key_len(), header.counter_len(), header.matrix(), header.size() - 1, binary_map.length() - header.offset()); query_from_sequence(argv + 2, argv + argc, bq, header.canonical()); } else { err::die(err::msg() << "Unsupported format '" << header.format() << "'. Must be a bloom counter or binary list."); } return 0; } Jellyfish-2.2.8/examples/query_per_sequence/sequence_mers.hpp000066400000000000000000000056061323712541700245600ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __SEQUENCE_MERS_H__ #define __SEQUENCE_MERS_H__ #include #include class sequence_mers : public std::iterator { public: typedef jellyfish::mer_dna mer_type; private: const char* cseq_; const char* eseq_; const bool canonical_; unsigned int filled_; mer_type m_; // mer mer_type rcm_; // reverse complement mer public: explicit sequence_mers(bool canonical = false) : cseq_(0), eseq_(0), canonical_(canonical), filled_(0) { } sequence_mers(const sequence_mers& rhs) : cseq_(rhs.cseq_), eseq_(rhs.eseq_), canonical_(rhs.canonical_), filled_(rhs.filled_), m_(rhs.m_), rcm_(rhs.rcm_) { } sequence_mers(sequence_mers&& rhs) : cseq_(rhs.cseq_), eseq_(rhs.eseq_), canonical_(rhs.canonical_), filled_(rhs.filled_), m_(std::move(rhs.m_)), rcm_(std::move(rcm_)) { } void reset(const char* seq, const char* seqe) { cseq_ = seq; eseq_ = seqe; filled_ = 0; this->operator++(); } sequence_mers& operator=(const std::string& seq) { reset(seq.c_str(), seq.c_str() + seq.size()); return *this; } sequence_mers& operator=(const char* seq) { reset(seq, seq + strlen(seq)); return *this; } bool operator==(const sequence_mers& rhs) const { return cseq_ == rhs.cseq_; } bool operator!=(const sequence_mers& rhs) const { return cseq_ != rhs.cseq_; } operator void*() const { return (void*)cseq_; } const mer_type& operator*() const { return !canonical_ || m_ < rcm_ ? m_ : rcm_; } const mer_type* operator->() const { return &this->operator*(); } sequence_mers& operator++() { if(cseq_ >= eseq_) { cseq_ = eseq_ = 0; return *this; } do { int code = m_.code(*cseq_++); if(code >= 0) { m_.shift_left(code); if(canonical_) rcm_.shift_right(rcm_.complement(code)); filled_ = std::min(filled_ + 1, jellyfish::mer_dna::k()); } else filled_ = 0; } while(filled_ < jellyfish::mer_dna::k() && cseq_ < eseq_); return *this; } sequence_mers operator++(int) { sequence_mers res(*this); ++*this; return res; } }; #endif /* __SEQUENCE_MERS_H__ */ Jellyfish-2.2.8/examples/swig/000077500000000000000000000000001323712541700162505ustar00rootroot00000000000000Jellyfish-2.2.8/examples/swig/README.md000066400000000000000000000001761323712541700175330ustar00rootroot00000000000000Simple examples on how to implement (simplified versions of) 'jellyfish dump' and 'jellyfish query' in Python, Ruby and Perl. Jellyfish-2.2.8/examples/swig/dump.pl000066400000000000000000000002311323712541700175460ustar00rootroot00000000000000#! /usr/bin/env perl use jellyfish; my $mf = jellyfish::ReadMerFile->new($ARGV[0]); while($mf->next_mer) { print($mf->mer, " ", $mf->count, "\n"); } Jellyfish-2.2.8/examples/swig/dump.py000066400000000000000000000002251323712541700175660ustar00rootroot00000000000000#! /usr/bin/env python import jellyfish import sys mf = jellyfish.ReadMerFile(sys.argv[1]) for mer, count in mf: print("%s %d" % (mer, count)) Jellyfish-2.2.8/examples/swig/dump.rb000066400000000000000000000002151323712541700175400ustar00rootroot00000000000000#! /usr/bin/env ruby require 'jellyfish' mf = Jellyfish::ReadMerFile.new(ARGV[0]) mf.each { |mer, count| print(mer, " ", count, "\n") } Jellyfish-2.2.8/examples/swig/query.pl000066400000000000000000000002561323712541700177550ustar00rootroot00000000000000#! /usr/bin/env perl use jellyfish; my $qf = jellyfish::QueryMerFile->new(shift @ARGV); for my $s (@ARGV) { print($s, " ", $qf->get(jellyfish::MerDNA->new($s)), "\n"); } Jellyfish-2.2.8/examples/swig/query.py000066400000000000000000000002561323712541700177720ustar00rootroot00000000000000#! /usr/bin/env python import jellyfish import sys qf = jellyfish.QueryMerFile(sys.argv[1]) for str in sys.argv[2:]: print("%s %d" % (str, qf[jellyfish.MerDNA(str)])) Jellyfish-2.2.8/examples/swig/query.rb000066400000000000000000000002431323712541700177410ustar00rootroot00000000000000#! /usr/bin/env ruby require 'jellyfish' qf = Jellyfish::QueryMerFile.new(ARGV[0]) ARGV[1..-1].each { |s| print(s, " ", qf[Jellyfish::MerDNA.new(s)], "\n") } Jellyfish-2.2.8/gtest.mk000077500000000000000000000010571323712541700151460ustar00rootroot00000000000000############################## # Gtest build. ############################## # Build rules for libraries. check_LTLIBRARIES = libgtest.la libgtest_main.la libgtest_la_SOURCES = unit_tests/gtest/src/gtest-all.cc libgtest_main_la_SOURCES = unit_tests/gtest/src/gtest_main.cc libgtest_main_la_LIBADD = libgtest.la libgtest_la_CXXFLAGS = -I$(srcdir)/unit_tests libgtest_main_la_CXXFLAGS = -I$(srcdir)/unit_tests GTEST_SRC = unit_tests/gtest/src/gtest-all.cc \ unit_tests/gtest/src/gtest_main.cc \ unit_tests/gtest/gtest.h EXTRA_DIST += $(GTEST_SRC) Jellyfish-2.2.8/header-license000066400000000000000000000012531323712541700162550ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ Jellyfish-2.2.8/include/000077500000000000000000000000001323712541700151045ustar00rootroot00000000000000Jellyfish-2.2.8/include/jellyfish/000077500000000000000000000000001323712541700170755ustar00rootroot00000000000000Jellyfish-2.2.8/include/jellyfish/allocators_mmap.hpp000066400000000000000000000040071323712541700227640ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_ALLOCATORS_MMAP_HPP__ #define __JELLYFISH_ALLOCATORS_MMAP_HPP__ #include #include #include #include #include #include namespace allocators { class mmap { void *ptr_; size_t size_; public: mmap() : ptr_(MAP_FAILED), size_(0) {} explicit mmap(size_t _size) : ptr_(MAP_FAILED), size_(0) { realloc(_size); } mmap(mmap&& rhs) : ptr_(rhs.ptr_), size_(rhs.size_) { rhs.ptr_ = MAP_FAILED; rhs.size_ = 0; } ~mmap() { free(); } mmap& operator=(mmap&& rhs) { swap(rhs); return *this; } void swap(mmap& rhs) { std::swap(ptr_, rhs.ptr_); std::swap(size_, rhs.size_); } void *get_ptr() const { return ptr_ != MAP_FAILED ? ptr_ : NULL; } size_t get_size() const { return size_; } void free(); void *realloc(size_t new_size); int lock() { return mlock(ptr_, size_); } int unlock() { return munlock(ptr_, size_); } // Return a a number of bytes which is a number of whole pages at // least as large as size. static size_t round_to_page(size_t _size); private: static const int nb_threads = 4; struct tinfo { pthread_t thid; char *start, *end; size_t pgsize; }; void fast_zero(); static void * _fast_zero(void *_info); }; inline void swap(mmap& a, mmap& b) { a.swap(b); } } #endif Jellyfish-2.2.8/include/jellyfish/atomic_bits_array.hpp000066400000000000000000000144351323712541700233100ustar00rootroot00000000000000/* Quorum * Copyright (C) 2012 Genome group at University of Maryland. * * 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 . */ #ifndef __JELLYFISH_ATOMIC_BITS_ARRAY_HPP__ #define __JELLYFISH_ATOMIC_BITS_ARRAY_HPP__ #include #include #include #include #include namespace jellyfish { template class atomic_bits_array_base { static const int w_ = sizeof(T) * 8; const int bits_; const size_t size_; const T mask_; const jflib::divisor64 d_; size_t size_bytes_; T* data_; static atomic::gcc atomic_; friend class iterator; class iterator : public std::iterator { friend class atomic_bits_array_base; const atomic_bits_array_base& ary_; T* word_; T mask_; int off_; iterator(const atomic_bits_array_base& a, T* w, T m, int o) : ary_(a), word_(w), mask_(m), off_(o) { } public: bool operator==(const iterator& rhs) const { return word_ == rhs.word_ && off_ == rhs.off_; } bool operator!=(const iterator& rhs) const { return word_ != rhs.word_ || off_ != rhs.off_; } Value operator*() const { return static_cast((*word_ & mask_) >> off_); } Value* operator->() const { return 0; } iterator& operator++() { off_ += ary_.bits_; if(off_ + ary_.bits_ < w_) { mask_ <<= ary_.bits_; } else { ++word_; mask_ = ary_.mask_; off_ = 0; } return *this; } iterator operator++(int) { iterator res(*this); ++*this; return res; } }; class element_proxy { T* word_; const T mask_; const int off_; T prev_word_; Value get_val(T v) const { return static_cast((v & mask_) >> off_); } public: element_proxy(T* word, T mask, int off) : word_(word), mask_(mask), off_(off) { } operator Value() const { return get_val(*word_); } Value get() { prev_word_ = *word_; return get_val(prev_word_); } bool set(Value& nval) { Value pval; Value cval = get_val(prev_word_); do { pval = cval; const T new_word = (prev_word_ & ~mask_) | ((static_cast(nval) << off_) & mask_); const T actual_word = atomic_.cas(word_, prev_word_, new_word); if(__builtin_expect(actual_word == prev_word_, 1)) return true; prev_word_ = actual_word; cval = get_val(prev_word_); } while(pval == cval); nval = cval; return false; } }; public: atomic_bits_array_base(int bits, // Number of bits per entry size_t size) : // Number of entries bits_(bits), size_(size), mask_((T)-1 >> (w_ - bits)), // mask of one entry at the LSB of a word d_(w_ / bits), // divisor of the number of entries per word size_bytes_((size / d_ + (size % d_ != 0)) * sizeof(T)), data_(static_cast(this)->alloc_data(size_bytes_)) { static_assert(sizeof(T) >= sizeof(Value), "Container type T must have at least as many bits as value type"); if((size_t)bits > sizeof(Value) * 8) throw std::runtime_error("The number of bits per entry must be less than the number of bits in the value type"); if(!data_) throw std::runtime_error("Can't allocate memory for atomic_bits_array"); } // Return the element at position pos. No check for out of bounds. element_proxy operator[](size_t pos) { uint64_t q, r; d_.division(pos, q, r); const int off = r * bits_; return element_proxy(data_ + q, mask_ << off, off); } const element_proxy operator[](size_t pos) const { uint64_t q, r; d_.division(pos, q, r); const int off = r * bits_; return element_proxy(data_ + q, mask_ << off, off); } void write(std::ostream& os) const { os.write((const char*)data_, size_bytes_); } size_t size_bytes() const { return size_bytes_; } int bits() const { return bits_; } iterator begin() const { return iterator(*this, data_, mask_, 0); } iterator end() const { uint64_t q, r; d_.division(size_, q, r); const int off = r * bits_; return iterator(*this, data_ + q, mask_ << off, off); } }; template class atomic_bits_array : protected allocators::mmap, public atomic_bits_array_base > { typedef atomic_bits_array_base > super; friend class atomic_bits_array_base >; public: atomic_bits_array(int bits, size_t size) : allocators::mmap(), super(bits, size) { } protected: T* alloc_data(size_t s) { allocators::mmap::realloc(s); return (T*)allocators::mmap::get_ptr(); } }; struct mem_info { void* ptr_; size_t bytes_; mem_info(void* ptr, size_t bytes) : ptr_(ptr), bytes_(bytes) { } }; template class atomic_bits_array_raw : protected mem_info, public atomic_bits_array_base > { typedef atomic_bits_array_base > super; friend class atomic_bits_array_base >; public: atomic_bits_array_raw(void* ptr, size_t bytes, int bits, size_t size) : mem_info(ptr, bytes), super(bits, size) { } protected: T* alloc_data(size_t s) { assert(bytes_ == s); return (T*)ptr_; } }; } // namespace jellyfish #endif /* __JELLYFISH_ATOMIC_BITS_ARRAY_HPP__ */ Jellyfish-2.2.8/include/jellyfish/atomic_field.hpp000066400000000000000000000121551323712541700222310ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_ATOMIC_FIELD_HPP__ #define __JELLYFISH_ATOMIC_FIELD_HPP__ #include namespace jflib { /* Define a_get, a_set and a_update */ template T a_load(T *x) { return *(volatile T*)x; } template T a_store(T* lhs, const U& rhs) { return (*(volatile T*)lhs = rhs); } template T* a_load_ptr(T* x) { return a_load((T**)&x); } template T* a_store_ptr(T* x, const U& rhs) { return a_store((T**)&x, rhs); } /** Set value to f(value). * @return f(value) * * The function f may be called more than once. Be careful about * side effects (probably better if f has no side effects). */ template T a_update(T* x, T (*f)(T)) { T ov(a_load(x)); T nv(f(ov)); while(!cas(x, ov, nv, &ov)) { nv = f(ov); } return nv; } template T a_load(T &x) { return a_load(&x); } template T a_store(T &lhs, const U& rhs) { return a_store(&lhs, rhs); } /* POD with atomic operators. */ template struct atomic_pod { typedef T type; T x; }; #define AF_COMPOUND_ASSIGN(op) \ template \ T operator op ## = (atomic_pod &x, const U &rhs) { \ T ov(a_load(&x.x)); \ T nv(ov op rhs); \ while(!cas(&x.x, ov, nv, &ov)) { nv = ov op rhs; } \ return nv; \ } AF_COMPOUND_ASSIGN(+); AF_COMPOUND_ASSIGN(-); AF_COMPOUND_ASSIGN(*); AF_COMPOUND_ASSIGN(/); AF_COMPOUND_ASSIGN(%); AF_COMPOUND_ASSIGN(>>); AF_COMPOUND_ASSIGN(<<); AF_COMPOUND_ASSIGN(&); AF_COMPOUND_ASSIGN(|); AF_COMPOUND_ASSIGN(^); /** Set value to f(value). * @return f(value) * * The function f may be called more than once. Be careful about * side effects (probably better if f has no side effects). */ template T a_load(atomic_pod &x) { return a_load(&x.x); } template T a_store(atomic_pod &lhs, const U &rhs) { return a_store(&lhs.x, rhs); } template T a_update(atomic_pod &x, T (*f)(T)) { return a_update(&x.x, f); } /* Similar to an atomic_pod, but not a POD, because of its constructor and other member functions. Easier to use. */ template class atomic_field : public atomic_pod { public: typedef typename atomic_pod::type type; explicit atomic_field() { } explicit atomic_field(const T& v) { a_store(&this->x, v); } atomic_field& operator=(const atomic_pod& rhs) { a_store(&this->x, rhs.x); return *this; } atomic_field& operator=(const T& v) { a_store(&this->x, v); return *this; } operator T() const { return a_load(&this->x); } T update(T (*f)(T)) { return a_update(&this->x, f); } }; template T a_load(atomic_field &x) { return a_load((atomic_pod&)x); } template atomic_field& a_store(atomic_field& lhs, const U& rhs) { a_store((atomic_pod&)lhs, rhs); return lhs; } template T a_update(atomic_field& x, T (*f)(T)) { return a_update((atomic_pod&)x, f); } /* Allows atomic operation on any (already allocated) data. */ template class atomic_ref { T *ptr; public: typedef T type; explicit atomic_ref(T& x) : ptr(&x) { } explicit atomic_ref(T* x) : ptr(x) { } atomic_ref& operator=(const T& v) { a_store(ptr, v); return *this; } operator T() const { assert(ptr != 0); return a_load(ptr); } T* operator&() const { return ptr; } }; #define AR_COMPOUND_ASSIGN(op) \ template \ T operator op ## = (atomic_ref &x, const U &rhs) { \ T ov(x); \ T nv(ov op rhs); \ while(!cas(&x, ov, nv, &ov)) { nv = ov op rhs; } \ return nv; \ } AR_COMPOUND_ASSIGN(+); AR_COMPOUND_ASSIGN(-); AR_COMPOUND_ASSIGN(*); AR_COMPOUND_ASSIGN(/); AR_COMPOUND_ASSIGN(%); AR_COMPOUND_ASSIGN(>>); AR_COMPOUND_ASSIGN(<<); AR_COMPOUND_ASSIGN(&); AR_COMPOUND_ASSIGN(|); AR_COMPOUND_ASSIGN(^); } #endif /* __JELLYFISH_ATOMIC_FIELD_HPP__ */ Jellyfish-2.2.8/include/jellyfish/atomic_gcc.hpp000066400000000000000000000034731323712541700217050ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_ATOMIC_GCC_HPP__ #define __JELLYFISH_ATOMIC_GCC_HPP__ namespace atomic { class gcc { public: template static inline T cas(volatile T *ptr, T oval, T nval) { return __sync_val_compare_and_swap(ptr, oval, nval); } template static inline T set(T *ptr, T nval) { return __sync_lock_test_and_set(ptr, nval); } template static inline T add_fetch(volatile T *ptr, T x) { T ncount = *ptr, count; do { count = ncount; ncount = cas((T *)ptr, count, count + x); } while(ncount != count); return count + x; } template static inline T fetch_add(volatile T *ptr, T x) { T ncount = *ptr, count; do { count = ncount; ncount = cas((T *)ptr, count, (T)(count + x)); } while(ncount != count); return count; } template static inline T set_to_max(volatile T *ptr, T x) { T count = *ptr; while(x > count) { T ncount = cas(ptr, count, x); if(ncount == count) return x; count = ncount; } return count; } }; } #endif Jellyfish-2.2.8/include/jellyfish/backtrace.hpp000066400000000000000000000013331323712541700215250ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ void print_backtrace(); void show_backtrace(); Jellyfish-2.2.8/include/jellyfish/binary_dumper.hpp000066400000000000000000000161701323712541700224530ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_BINARY_DUMPER_HPP__ #define __JELLYFISH_BINARY_DUMPER_HPP__ #include #include #include namespace jellyfish { template class binary_writer { int val_len_; Val max_val_; int key_len_; // length of output key field in bytes public: binary_writer(int val_len, // length of value field in bytes int key_len) : // length of key field in bits val_len_(val_len), max_val_(((Val)1 << (8 * val_len)) - 1), key_len_(key_len / 8 + (key_len % 8 != 0)) { } int val_len() const { return val_len_; } Val max_val() const { return max_val_; } int key_len() const { return key_len_; } void write(std::ostream& out, const Key& key, const Val val) { out.write((const char*)key.data(), key_len_); Val v = std::min(max_val_, val); out.write((const char*)&v, val_len_); } }; /// Dump a hash array in sorted binary format. The key/value pairs are /// written in a sorted list according to the hash function order. The /// k-mer and count are written in binary, byte aligned. template class binary_dumper : public sorted_dumper, storage_t> { typedef sorted_dumper, storage_t> super; binary_writer writer; public: static const char* format; binary_dumper(int val_len, // length of value field in bytes int key_len, // length of key field in bits int nb_threads, const char* file_prefix, file_header* header = 0) : super(nb_threads, file_prefix, header), writer(val_len, key_len) { } virtual void _dump(storage_t* ary) { if(super::header_) { super::header_->update_from_ary(*ary); super::header_->format(format); super::header_->counter_len(writer.val_len()); } super::_dump(ary); } void write_key_value_pair(std::ostream& out, typename super::heap_item item) { writer.write(out, item->key_, item->val_); } }; template const char* jellyfish::binary_dumper::format = "binary/sorted"; /// Reader of the format written by binary_dumper. Behaves like an /// iterator (has next() method which behaves similarly to the next() /// method of the hash array). /// The header should be of format binary/sorted, but no check is made. template class binary_reader { std::istream& is_; const int val_len_; Key key_; Val val_; const RectangularBinaryMatrix m_; const size_t size_mask_; public: binary_reader(std::istream& is, // stream containing data (past any header) file_header* header) : // header which contains counter_len, matrix, size and key_len is_(is), val_len_(header->counter_len()), key_(header->key_len() / 2), m_(header->matrix()), size_mask_(header->size() - 1) { } const Key& key() const { return key_; } const Val& val() const { return val_; } size_t pos() const { return m_.times(key_) & size_mask_; } bool next() { key_.template read<1>(is_); val_ = 0; is_.read((char*)&val_, val_len_); return is_.good(); } }; template class binary_query_base { const char* const data_; const unsigned int val_len_; // In bytes const unsigned int key_len_; // In bytes const RectangularBinaryMatrix m_; const size_t mask_; const size_t record_len_; const size_t last_id_; Key first_key_, last_key_; mutable Key mid_key_; uint64_t first_pos_, last_pos_; public: // key_len passed in bits binary_query_base(const char* data, unsigned int key_len, unsigned int val_len, const RectangularBinaryMatrix& m, size_t mask, size_t size) : data_(data), val_len_(val_len), key_len_(key_len / 8 + (key_len % 8 != 0)), m_(m), mask_(mask), record_len_(val_len + key_len_), last_id_(size / record_len_), first_key_(key_len / 2), last_key_(key_len / 2), mid_key_(key_len / 2) { if(size % record_len_ != 0) throw std::length_error(err::msg() << "Size of database (" << size << ") must be a multiple of the length of a record (" << record_len_ << ")"); key_at(0, first_key_); first_pos_ = key_pos(first_key_); key_at(last_id_ - 1, last_key_); last_pos_ = key_pos(last_key_); } bool val_id(const Key& key, Val* res, uint64_t* id) const { if(last_id_ == 0) return false; uint64_t first = 0; uint64_t last = last_id_; uint64_t first_pos = first_pos_; uint64_t last_pos = last_pos_; const uint64_t pos = key_pos(key); uint64_t cid = 0; if(key == first_key_) goto found; cid = last_id_ - 1; if(key == last_key_) goto found; if(pos < first_pos_ || pos > last_pos_) return false; // First a guided binary search for(uint64_t diff = last - first; diff >= 8; diff = last - first) { cid = first + lrint(diff * ((double)(pos - first_pos) / (double)(last_pos - first_pos))); cid = std::max(first + 1, cid); cid = std::min(cid, last - 1); key_at(cid, mid_key_); if(key == mid_key_) goto found; uint64_t mid_pos = key_pos(mid_key_); if(mid_pos > pos || (mid_pos == pos && mid_key_ > key)) { last = cid; last_pos = mid_pos; } else { first = cid; first_pos = mid_pos; } } // Then a linear search (avoids matrix computation) for(cid = first + 1; cid < last; ++cid) { key_at(cid, mid_key_); if(key == mid_key_) goto found; } return false; found: val_at(cid, res); *id = cid; return true; } Val operator[](const Key& key) const { Val res; uint64_t id; if(!val_id(key, &res, &id)) return 0; return res; } inline Val check(const Key& key) const { return (*this)[key]; } protected: void key_at(size_t id, Key& key) const { memcpy(key.data__(), data_ + id * record_len_, key_len_); key.clean_msw(); } void val_at(size_t id, Val* val) const { *val = 0; memcpy(val, data_ + id * record_len_ + key_len_, val_len_); } uint64_t key_pos(const Key& key) const { return m_.times(key) & mask_; } }; } #endif /* __JELLYFISH_BINARY_DUMPER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/bloom_common.hpp000066400000000000000000000075431323712541700222770ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_BLOOM_COMMON_HPP__ #define __JELLYFISH_BLOOM_COMMON_HPP__ #include #include #include namespace jellyfish { template struct hash_pair { }; template > class bloom_base { protected: struct prefetch_info { size_t boff; unsigned char* pos; }; // The number of bits in the structure, previously known as m_, is // know stored as d_.d() const jflib::divisor64 d_; const unsigned long k_; unsigned char * const data_; HashPair hash_fns_; public: typedef Key key_type; bloom_base(size_t m, unsigned long k, unsigned char* ptr, const HashPair& fns = HashPair()) : d_(m), k_(k), data_(ptr), hash_fns_(fns) { } bloom_base(const bloom_base& rhs) = delete; bloom_base(bloom_base&& rhs) : d_(rhs.d_), k_(rhs.k_), data_(rhs.data_), hash_fns_(std::move(rhs.hash_fns_)) { } void write_bits(std::ostream& out) { out.write((char*)data_, static_cast(this)->nb_bytes()); } // Number of hash functions unsigned long k() const { return k_; } // Size of bit vector size_t m() const { return d_.d(); } const HashPair& hash_functions() const { return hash_fns_; } static const double LOG2; static const double LOG2_SQ; static size_t opt_m(const double fp, const size_t n) { return n * (size_t)lrint(-log(fp) / LOG2_SQ); } static unsigned long opt_k(const double fp) { return lrint(-log(fp) / LOG2); } // Insert key k. Returns previous value of k unsigned int insert(const Key &k) { uint64_t hashes[2]; hash_fns_(k, hashes); return static_cast(this)->insert__(hashes); } unsigned int check(const Key &k) const { uint64_t hashes[2]; hash_fns_(k, hashes); return static_cast(this)->check__(hashes); } // Limited std::map interface compatibility class element_proxy { Derived& bc_; const Key& k_; public: element_proxy(Derived& bc, const Key& k) : bc_(bc), k_(k) { } unsigned int operator++() { unsigned int res = bc_.insert(k_); return res == 0 ? 1 : 2; } unsigned int operator++(int) { return bc_.insert(k_); } unsigned int operator*() const { return bc_.check(k_); } operator unsigned int() const { return bc_.check(k_); } }; class const_element_proxy { const Derived& bc_; const Key& k_; public: const_element_proxy(const Derived& bc, const Key& k) : bc_(bc), k_(k) { } unsigned int operator*() const { return bc_.check(k_); } operator unsigned int() const { return bc_.check(k_); } }; element_proxy operator[](const Key& k) { return element_proxy(*static_cast(this), k); } const_element_proxy operator[](const Key& k) const { return const_element_proxy(*static_cast(this), k); } }; template const double bloom_base::LOG2 = 0.6931471805599453; template const double bloom_base::LOG2_SQ = 0.4804530139182014; } #endif /* __JELLYFISH_BLOOM_COMMON_HPP__ */ Jellyfish-2.2.8/include/jellyfish/bloom_counter2.hpp000066400000000000000000000161051323712541700225420ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __BLOOM_COUNTER2_HPP__ #define __BLOOM_COUNTER2_HPP__ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif namespace jellyfish { /* Bloom counter with 3 values: 0, 1 or 2. It is thread safe and lock free. */ template, typename atomic_t = ::atomic::gcc> class bloom_counter2_base : public bloom_base, HashPair> { typedef bloom_base, HashPair> super; atomic_t atomic_; protected: static size_t nb_bytes__(size_t l) { return l / 5 + (l % 5 != 0); } public: bloom_counter2_base(size_t m, unsigned long k, unsigned char* ptr, const HashPair& fns = HashPair()) : super(m, k, ptr, fns) { } bloom_counter2_base(bloom_counter2_base&& rhs) : super(std::move(rhs)) { } size_t nb_bytes() const { return nb_bytes__(super::d_.d()); } // Insert key with given hashes unsigned int insert__(const uint64_t* hashes) { // Prefetch memory locations static_assert(std::is_pod::value, "prefetch_info must be a POD"); typename super::prefetch_info pinfo[super::k_]; const size_t base = super::d_.remainder(hashes[0]); const size_t inc = super::d_.remainder(hashes[1]); for(unsigned long i = 0; i < super::k_; ++i) { const size_t p = super::d_.remainder(base + i * inc); const size_t off = p / 5; pinfo[i].boff = p % 5; pinfo[i].pos = super::data_ + off; // prefetch_write_no(pinfo[i].pos); __builtin_prefetch(pinfo[i].pos, 1, 0); } // Insert element unsigned char res = 2; for(unsigned long i = 0; i < super::k_; ++i) { size_t boff = pinfo[i].boff; unsigned char v = jflib::a_load(pinfo[i].pos); while(true) { unsigned char w = v; switch(boff) { case 0: break; case 1: w /= 3; break; case 2: w /= 9; break; case 3: w /= 27; break; case 4: w /= 81; break; } w = w % 3; if(w == 2) break; unsigned char nv = v; switch(boff) { case 0: nv += 1; break; case 1: nv += 3; break; case 2: nv += 9; break; case 3: nv += 27; break; case 4: nv += 81; break; } unsigned char cv = atomic_.cas(pinfo[i].pos, v, nv); if(cv == v) { if(w < res) res = w; break; } v = cv; } } return res; } unsigned int check__(uint64_t *hashes) const { // Prefetch memory locations static_assert(std::is_pod::value, "prefetch_info must be a POD"); typename super::prefetch_info pinfo[super::k_]; const size_t base = super::d_.remainder(hashes[0]); const size_t inc = super::d_.remainder(hashes[1]); for(unsigned long i = 0; i < super::k_; ++i) { const size_t p = super::d_.remainder(base + i * inc); const size_t off = p / 5; pinfo[i].boff = p % 5; pinfo[i].pos = super::data_ + off; // prefetch_read_no(pinfo[i].pos); __builtin_prefetch(pinfo[i].pos, 0, 0); } // Check element unsigned char res = 2; for(unsigned long i = 0; i < super::k_; ++i) { size_t boff = pinfo[i].boff; unsigned char w = jflib::a_load(pinfo[i].pos); switch(boff) { case 0: break; case 1: w /= 3; break; case 2: w /= 9; break; case 3: w /= 27; break; case 4: w /= 81; break; } w = w % 3; if(w < res) res = w; } return res; } }; template, typename atomic_t = ::atomic::gcc, typename mem_block_t = allocators::mmap> class bloom_counter2: protected mem_block_t, public bloom_counter2_base { typedef bloom_counter2_base super; public: typedef typename super::key_type key_type; bloom_counter2(const double fp, const size_t n, const HashPair& fns = HashPair()) : mem_block_t(super::nb_bytes__(super::opt_m(fp, n))), super(super::opt_m(fp, n), super::opt_k(fp), (unsigned char*)mem_block_t::get_ptr(), fns) { if(!mem_block_t::get_ptr()) throw std::runtime_error(err::msg() << "Failed to allocate " << super::nb_bytes__(super::opt_m(fp, n)) << " bytes of memory for bloom_counter"); } bloom_counter2(size_t m, unsigned long k, const HashPair& fns = HashPair()) : mem_block_t(super::nb_bytes__(m)), super(m, k, (unsigned char*)mem_block_t::get_ptr(), fns) { if(!mem_block_t::get_ptr()) throw std::runtime_error(err::msg() << "Failed to allocate " << super::nb_bytes__(m) << " bytes of memory for bloom_counter"); } bloom_counter2(size_t m, unsigned long k, std::istream& is, const HashPair& fns = HashPair()) : mem_block_t(super::nb_bytes__(m)), super(m, k, (unsigned char*)mem_block_t::get_ptr(), fns) { if(!mem_block_t::get_ptr()) throw std::runtime_error(err::msg() << "Failed to allocate " << super::nb_bytes__(m) << " bytes of memory for bloom_counter"); is.read((char*)mem_block_t::get_ptr(), mem_block_t::get_size()); } bloom_counter2(const bloom_counter2& rhs) = delete; bloom_counter2(bloom_counter2&& rhs) : mem_block_t(std::move(rhs)), super(std::move(rhs)) { } }; template, typename atomic_t = ::atomic::gcc> class bloom_counter2_file : protected mapped_file, public bloom_counter2_base { typedef bloom_counter2_base super; public: typedef typename super::key_type key_type; bloom_counter2_file(size_t m, unsigned long k, const char* path, const HashPair& fns = HashPair(), off_t offset = 0) : mapped_file(path), super(m, k, (unsigned char*)mapped_file::base() + offset, fns) { } bloom_counter2_file(const bloom_counter2_file& rhs) = delete; bloom_counter2_file(bloom_counter2_file&& rhs) : mapped_file(std::move(rhs)), super(std::move(rhs)) { } }; } // namespace jellyfish { #endif // __BLOOM_COUNTER2_HPP__ Jellyfish-2.2.8/include/jellyfish/bloom_filter.hpp000066400000000000000000000134221323712541700222650ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_BLOOM_FILTER_HPP__ #define __JELLYFISH_BLOOM_FILTER_HPP__ #include #include #include namespace jellyfish { template, typename atomic_t = ::atomic::gcc> class bloom_filter_base : public bloom_base, HashPair> { typedef bloom_base, HashPair> super; protected: static size_t nb_bytes__(size_t l) { return l / 8 + (l % 8 != 0); } public: bloom_filter_base(size_t m, unsigned long k, unsigned char* ptr, const HashPair& fns = HashPair()) : super(m, k, ptr, fns) { } bloom_filter_base(bloom_filter_base&& rhs) : super(std::move(rhs)) { } size_t nb_bytes() const { return nb_bytes__(super::d_.d()); } // Insert key with given hashes unsigned int insert__(const uint64_t *hashes) { // Prefetch memory locations // This static_assert make clang++ happy... static_assert(std::is_pod::value, "prefetch_info must be a POD"); typename super::prefetch_info pinfo[super::k_]; const size_t base = super::d_.remainder(hashes[0]); const size_t inc = super::d_.remainder(hashes[1]); for(unsigned long i = 0; i < super::k_; ++i) { const size_t pos = super::d_.remainder(base + i * inc); const size_t elt_i = pos / 8; pinfo[i].boff = pos % 8; pinfo[i].pos = super::data_ + elt_i; __builtin_prefetch(pinfo[i].pos, 1, 0); } // Check if element present bool present = true; for(unsigned long i = 0; i < super::k_; ++i) { const char mask = (char)1 << pinfo[i].boff; const char prev = __sync_fetch_and_or(pinfo[i].pos, mask); present = present && (prev & mask); } return present; } // Compute hashes of key k void hash(const Key &k, uint64_t *hashes) const { hash_fns_(k, hashes); } unsigned int check__(const uint64_t *hashes) const { // Prefetch memory locations static_assert(std::is_pod::value, "prefetch_info must be a POD"); typename super::prefetch_info pinfo[super::k_]; const size_t base = super::d_.remainder(hashes[0]); const size_t inc = super::d_.remainder(hashes[1]); for(unsigned long i = 0; i < super::k_; ++i) { const size_t pos = super::d_.remainder(base + i * inc); const size_t elt_i = pos / 8; pinfo[i].boff = pos % 8; pinfo[i].pos = super::data_ + elt_i; __builtin_prefetch(pinfo[i].pos, 0, 0); } for(unsigned long i = 0; i < super::k_; ++i) if(!(jflib::a_load(pinfo[i].pos) & ((char)1 << pinfo[i].boff))) return 0; return 1; } }; template, typename atomic_t = ::atomic::gcc, typename mem_block_t = allocators::mmap> class bloom_filter : protected mem_block_t, public bloom_filter_base { typedef bloom_filter_base super; public: bloom_filter(double fp, size_t n, const HashPair& fns = HashPair()) : mem_block_t(super::nb_bytes__(super::opt_m(fp, n))), super(super::opt_m(fp, n), super::opt_k(fp), (unsigned char*)mem_block_t::get_ptr(), fns) { if(!mem_block_t::get_ptr()) throw std::runtime_error(err::msg() << "Failed to allocate " << super::nb_bytes__(super::opt_m(fp, n)) << " bytes of memory for bloom_filter"); } bloom_filter(size_t m, unsigned long k, const HashPair& fns = HashPair()) : mem_block_t(super::nb_bytes__(m)), super(m, k, (unsigned char*)mem_block_t::get_ptr(), fns) { if(!mem_block_t::get_ptr()) throw std::runtime_error(err::msg() << "Failed to allocate " << super::nb_bytes__(m) << " bytes of memory for bloom_filter"); } bloom_filter(size_t m, unsigned long k, std::istream& is, const HashPair& fns = HashPair()) : mem_block_t(super::nb_bytes__(m)), super(m, k, (unsigned char*)mem_block_t::get_ptr(), fns) { if(!mem_block_t::get_ptr()) throw std::runtime_error(err::msg() << "Failed to allocate " << super::nb_bytes__(m) << " bytes of memory for bloom_filter"); is.read((char*)mem_block_t::get_ptr(), mem_block_t::get_size()); } bloom_filter(bloom_filter&& rhs) : mem_block_t(std::move(rhs)), super(std::move(rhs)) { } }; template, typename atomic_t = ::atomic::gcc> class bloom_filter_file : protected mapped_file, public bloom_filter_base { typedef bloom_filter_base super; public: typedef typename super::key_type key_type; bloom_filter_file(size_t m, unsigned long k, const char* path, const HashPair& fns = HashPair(), off_t offset = 0) : mapped_file(path), super(m, k, (unsigned char*)mapped_file::base() + offset, fns) { } bloom_filter_file(const bloom_filter_file& rhs) = delete; bloom_filter_file(bloom_filter_file&& rhs) : mapped_file(std::move(rhs)), super(std::move(rhs)) { } }; } #endif /* __JELLYFISH_BLOOM_FILTER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/circular_buffer.hpp000066400000000000000000000130461323712541700227470ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_CIRCULAR_BUFFER_HPP__ #define __JELLYFISH_CIRCULAR_BUFFER_HPP__ #include #include #include #include namespace jflib { template class basic_circular_buffer { static const unsigned int m = std::numeric_limits::digits - n; struct splitT { T id:m; T val:n; }; union elt { T binary; splitT split; }; // size_t _size; divisor64 _size; T *_buffer; size_t _head; size_t _tail; bool _closed; public: typedef T value_type; static const T guard = g; basic_circular_buffer(size_t size) : _size(size+1), _buffer(new T[_size.d()]), _head(0), _tail(0), _closed(false) { elt init; init.split.id = 0; init.split.val = guard; for(size_t i = 0; i < _size.d(); ++i) _buffer[i] = init.binary; } virtual ~basic_circular_buffer() { if(_buffer) delete [] _buffer; } /** Enqueue an element. * @return false if the FIFO is full. */ bool enqueue(const T &v); /** Enqueue an element, optimization. No check is made that the * FIFO is full. Undetermined behavior if an element is inserted * in a full FIFO. */ void enqueue_no_check(const T &v); /** Dequeue an element. * @return 0 if the FIFO is empty. */ T dequeue(); bool is_closed() const { return a_load(_closed); } void close() { a_store(_closed, true); } /// Return capacity of circular buffer size_t size() { return _size.d(); } /// Return the number of element currently in circular buffer size_t fill() { size_t head, tail; size_t nhead = a_load(_head); do { head = nhead; tail = a_load(_tail); } while(head != (nhead = a_load(_head))); return head >= tail ? head - tail : head + _size.d() - tail; } }; template class circular_buffer : public basic_circular_buffer::digits, g> { public: circular_buffer(size_t size) : basic_circular_buffer::digits, g>(size) { } virtual ~circular_buffer() { } bool enqueue(const T &v) { return basic_circular_buffer::digits, g>::enqueue((uint64_t)v); } T dequeue() { return basic_circular_buffer::digits, g>::dequeue(); } }; } template bool jflib::basic_circular_buffer::enqueue(const T &v) { bool done = false; size_t chead = a_load(_head); while(!done) { size_t ctail = a_load(_tail); elt celt; celt.binary = a_load(_buffer[chead % _size]); size_t achead = a_load(_head); if(achead != chead) { chead = achead; continue; } size_t nhead = chead + 1; if(nhead % _size == ctail % _size) return false; if(celt.split.val == guard) { // entry is empty elt nelt; nelt.split.id = celt.split.id + 1; nelt.split.val = v; done = cas(&_buffer[chead % _size], celt.binary, nelt.binary); // done == true <=> sucessfully written entry } cas(&_head, chead, nhead, &chead); } return true; } template void jflib::basic_circular_buffer::enqueue_no_check(const T &v) { bool done = false; size_t chead = a_load(_head); while(!done) { elt celt; celt.binary = a_load(_buffer[chead % _size]); size_t achead = a_load(_head); if(achead != chead) { chead = achead; continue; } size_t nhead = chead + 1; if(celt.split.val == guard) { // entry is empty elt nelt; nelt.split.id = celt.split.id + 1; nelt.split.val = v; done = cas(&_buffer[chead % _size], celt.binary, nelt.binary); // done == true <=> sucessfully written entry } cas(&_head, chead, nhead, &chead); } } template T jflib::basic_circular_buffer::dequeue() { bool done = false; elt res; size_t ctail = a_load(_tail); while(!done) { bool dequeued = false; do { if(ctail % _size == a_load(_head) % _size) return guard; size_t ntail = ctail + 1; dequeued = cas(&_tail, ctail, ntail, &ctail); } while(!dequeued); res.binary = a_load(_buffer[ctail % _size]); elt nres; nres.split.val = guard; while(true) { nres.split.id = res.split.id + 1; if(res.split.val == guard) { if(cas(&_buffer[ctail % _size], res.binary, nres.binary, &res.binary)) break; } else { done = cas(&_buffer[ctail % _size], res.binary, nres.binary); break; } } } return res.split.val; } #endif /* __JELLYFISH_CIRCULAR_BUFFER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/compare_and_swap.hpp000066400000000000000000000054431323712541700231160ustar00rootroot00000000000000/* This file is part of Jflib. Jflib 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. Jflib 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 Jflib. If not, see . */ #ifndef _JFLIB_COMPARE_AND_SWAP_H_ #define _JFLIB_COMPARE_AND_SWAP_H_ #include #include namespace jflib { // // Atomic load (get) and store (set). For now assume that the // // architecture does this based on the virtual key word (true for // // x86_64). TODO: improve on other architectures. // template // T a_get(const T &x) { return *(volatile T*)&x; } // template // T &a_set(T &lhs, const U &rhs) { // *(volatile T*)&lhs = rhs; // return lhs; // } // Numeric type of length rounded up to the size of a // word. Undefined, and raise a compilation error, if the length is // not a machine word size template union word_t; template union word_t { typedef uint8_t w_t; T v; w_t w; }; template union word_t { typedef uint16_t w_t; T v; w_t w; }; template union word_t { typedef uint32_t w_t; T v; w_t w; }; template union word_t { typedef uint64_t w_t; T v; w_t w; }; /** Type safe version of CAS. * @param [in] ptr Memory location. * @param [in] ov Presumed value at location. * @param [in] nv Value to write. * @param [out] cv Value at location at time of call. * @return true if CAS is successful. * * The CAS operation is successful if, at the time of call, ov is * equal to *ptr, the value at the memory location. In that case, nv * is written to *ptr, and when the call returns, cv == ov. * * If it fails, cv contains *ptr at the time of call. */ template bool cas(T *ptr, const T &ov, const T &nv, T *cv) { typedef word_t val_t; val_t _cv, _ov, _nv; _ov.v = ov; _nv.v = nv; _cv.w = __sync_val_compare_and_swap((typename val_t::w_t *)ptr, _ov.w, _nv.w); *cv = _cv.v; return _cv.w == _ov.w; } /** Type safe version of CAS. Identical to 4 argument version, * except does not return the previous value. */ template bool cas(T *ptr, const T &ov, const T &nv) { T cv; return cas(ptr, ov, nv, &cv); } } #endif /* _JFLIB_COMPARE_AND_SWAP_H_ */ Jellyfish-2.2.8/include/jellyfish/cooperative_pool.hpp000066400000000000000000000173731323712541700231720ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_COOPERATIVE_POOL_HPP__ #define __JELLYFISH_COOPERATIVE_POOL_HPP__ #include #include #include #include #include /// Cooperative pool. Provide a link between a producer and many /// consumers. It is cooperative in the sense that there is no /// dedicated thread to the producer. When the number of elements in /// the queue from the producer to the consumer is less than half, /// then the thread requesting an element attempts to become the /// producer. It stays a producer until the producer to consumer queue /// is full. /// /// This class must be subclassed using CRTP. `T` is the type of the /// element passed around in the queues. The derived class must /// implement the method `bool produce(T& e)`. It is called when a /// thread has become a producer. It must set in `e` the new element, /// unless there is nothing more to produce. It returns `true` if /// there is nothing more to produce (and `e` is not used), `false` /// otherwise. /// /// The following example will produce the integers `[0, 1000000]`: /// /// ~~~{.cc} /// class sequence : public cooperative_bool { /// int cur_; /// public: /// sequence() : cur_(0) { } /// bool produce(int& e) { /// if(cur_ <= 1000000) { /// e = cur_++; /// return false; /// } /// return true; /// } /// }; /// ~~~ /// /// To access the elements (or the jobs) of the sequence, instantiate /// a `sequence::job` object and check that it is not empty. If empty, /// the sequence is over. /// /// ~~~{.cc} /// sequence seq; // Sequence, instantiated in main thread /// // In each consumer thread: /// while(true) { /// sequence::job j(seq); /// if(j.is_empty()) /// break; /// // Do computation using *j and j-> /// } /// ~~~ namespace jellyfish { template class cooperative_pool { public: typedef jflib::circular_buffer cbT; typedef T element_type; private: uint32_t size_; element_type* elts_; cbT cons_prod_; // FIFO from Consumers to Producers cbT prod_cons_; // FIFO from Producers to Consumers int has_producer_; // Tell whether a thread is acting as a producer // RAII token. class take_token { int* const token_; const bool has_token_; public: take_token(int* token) : token_(token), has_token_(jflib::cas(token_, 0, 1)) { } ~take_token() { if(has_token_) // cas(token_, 1, 0); // Guaranteed to succeed. Memory barrier jflib::a_store(token_, 0); } bool has_token() const { return has_token_; } }; explicit cooperative_pool(const cooperative_pool& rhs) : size_(0), elts_(0), cons_prod_(0), prod_cons_(0), has_producer_(0) { } public: cooperative_pool(uint32_t size) : size_(size), elts_(new element_type[size_]), cons_prod_(size_ + 100), prod_cons_(size_ + 100), has_producer_(0) { // Every element is empty and ready to be filled by the producer for(size_t i = 0; i < size_; ++i) cons_prod_.enqueue_no_check(i); } ~cooperative_pool() { delete [] elts_; } uint32_t size() const { return size_; } element_type* element_begin() { return elts_; } element_type* element_end() { return elts_ + size_; } // Contains a filled element or is empty. In which case the producer // is done and we should stop processing. class job { cooperative_pool& cp_; uint32_t i_; // Index of element public: job(cooperative_pool& cp) : cp_(cp), i_(cp_.get_element()) { } ~job() { release(); } void release() { if(!is_empty()) { cp_.cons_prod_.enqueue_no_check(i_); } } bool is_empty() const { return i_ == cbT::guard; } void next() { release(); i_ = cp_.get_element(); } element_type& operator*() { return cp_.elts_[i_]; } element_type* operator->() { return &cp_.elts_[i_]; } private: // Disable copy of job job(const job& rhs) { } job& operator=(const job& rhs) { } }; friend class job; /// STL compliant iterator class iterator : public std::iterator { job* j_; public: iterator() : j_(0) { } iterator(cooperative_pool& cp) : j_(new job(cp)) { } iterator(const iterator& rhs) : j_(rhs.j_) { } bool operator==(const iterator& rhs) const { return j_ == rhs.j_; } bool operator!=(const iterator& rhs) const { return j_ != rhs.j_; } element_type& operator*() { return j_->operator*(); } element_type* operator->() { return j_->operator->(); } iterator& operator++() { j_->next(); if(j_->is_empty()) { delete j_; j_ = 0; } return *this; } iterator operator++(int) { iterator res(*this); ++*this; return res; } }; iterator begin() { return iterator(*this); } const iterator begin() const { return iterator(*this); } const iterator end() const { return iterator(); } private: enum PRODUCER_STATUS { PRODUCER_PRODUCED, PRODUCER_DONE, PRODUCER_EXISTS }; uint32_t get_element() { int iteration = 0; while(true) { // If less than half full -> try to fill up producer to consumer // queue. Disregard return value: in any every case will // attempt to get an element for ourselves if(prod_cons_.fill() < prod_cons_.size() / 2) become_producer(); uint32_t i = prod_cons_.dequeue(); if(i != cbT::guard) return i; // Try to become producer switch(become_producer()) { case PRODUCER_PRODUCED: iteration = 0; // Produced. Attempt anew to get an element break; case PRODUCER_DONE: return prod_cons_.dequeue(); case PRODUCER_EXISTS: delay(iteration++); // Already a producer. Wait a bit it adds things to queue break; } } } PRODUCER_STATUS become_producer() { if(prod_cons_.is_closed()) return PRODUCER_DONE; // Mark that we have a produce (myself). If not, return. Token // will be release automatically at end of method. take_token producer_token(&has_producer_); if(!producer_token.has_token()) return PRODUCER_EXISTS; uint32_t i = cbT::guard; try { while(true) { // Only way out is if produce method is done (returns true or throw an exception) i = cons_prod_.dequeue(); if(i == cbT::guard) return PRODUCER_PRODUCED; if(static_cast(this)->produce(elts_[i])) // produce returns true if done break; prod_cons_.enqueue_no_check(i); } } catch(...) { } // Threw an exception -> same as being done // Producing is done cons_prod_.enqueue_no_check(i); prod_cons_.close(); return PRODUCER_DONE; } // First 16 operations -> no delay. Then exponential back-off up to a second. void delay(int iteration) { if(iteration < 16) return; int shift = 10 - std::min(iteration - 16, 10); usleep((1000000 - 1) >> shift); } }; } // namespace jellyfish { #endif /* __JELLYFISH_COOPERATIVE_POOL_HPP__ */ Jellyfish-2.2.8/include/jellyfish/cooperative_pool2.hpp000066400000000000000000000213711323712541700232450ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_COOPERATIVE_POOL2_HPP__ #define __JELLYFISH_COOPERATIVE_POOL2_HPP__ #include #include #include #include #include /// Cooperative pool. Provide a link between many producers and many /// consumers. It is cooperative in the sense that there is no /// dedicated threads as producer. When the number of elements in the /// queue from the producer to the consumer is less than half, then /// the thread requesting an element attempts to become an additional /// producer. It stays a producer until the producer to consumer queue /// is full. /// /// This class must be subclassed using CRTP. `T` is the type of the /// element passed around in the queues. The derived class must /// implement the method `bool produce(uint32_t i, T& e)`. It is /// called when a thread has become a producer. It must set in `e` the /// new element, unless there is nothing more to produce. It returns /// `true` if there is nothing more to produce (and `e` is not used), /// `false` otherwise. /// /// The maximum number of producers is specified to the constructor of /// the class (`max_producers`). The parameter `i` passed to `produce` /// is in [0, max_producers) and it is guaranteed that at any given /// time, no two producers have the same `i`. /// /// The following example will produce the integers `[0, 1000 * max)`, /// with max producers. /// /// ~~~{.cc} /// class sequence : public cooperative_bool { /// const uint32_t max_; /// std::vector cur_; /// uint32_t done_; /// public: /// sequence(uint32_t max) : max_(max), cur_(max, 0), done_(0) { } /// bool produce(uint32_t i, int& e) { /// int& cur = cur_[i]; /// if(cur < max_) { /// e = i * max_ + cur++; /// return false; /// } /// return true; /// } /// }; /// ~~~ /// /// To access the elements (or the jobs) of the sequence, instantiate /// a `sequence::job` object and check that it is not empty. If empty, /// the sequence is over. /// /// ~~~{.cc} /// sequence seq; // Sequence, instantiated in main thread /// // In each consumer thread: /// while(true) { /// sequence::job j(seq); /// if(j.is_empty()) /// break; /// // Do computation using *j and j-> /// } /// ~~~ namespace jellyfish { template class cooperative_pool2 { public: typedef jflib::circular_buffer cbT; typedef T element_type; private: uint32_t size_; element_type* elts_; cbT cons_prod_; // FIFO from Consumers to Producers cbT prod_cons_; // FIFO from Producers to Consumers cbT tokens_; // FIFO with producer tokens const uint32_t max_producers_; uint32_t done_; // Number of producer that are done // RAII token. struct take_token { cbT& tokens_; uint32_t token_; bool drop_; take_token(cbT& tokens) : tokens_(tokens), token_(tokens.dequeue()), drop_(false) { } ~take_token() { if(has_token() && !drop_) { tokens_.enqueue_no_check(token_); // assert(tokens_.enqueue(token_)); } } bool has_token() const { return token_ != cbT::guard; } void drop() { drop_ = true; } }; // explicit cooperative_pool2(const cooperative_pool2& rhs) : size_(0), elts_(0), cons_prod_(0), prod_cons_(0) { } public: cooperative_pool2(uint32_t max_producers, uint32_t size) : size_(size), elts_(new element_type[size_]), cons_prod_(size_ + 100), prod_cons_(size_ + 100), tokens_(max_producers + 1), max_producers_(max_producers), done_(0) { // Every element is empty and ready to be filled by the producer for(size_t i = 0; i < size_; ++i) cons_prod_.enqueue_no_check(i); // Every producer token is free for(uint32_t i = 0; i < max_producers_; ++i) tokens_.enqueue(i); // tokens_.enqueue_no_check(i); } ~cooperative_pool2() { delete [] elts_; } uint32_t size() const { return size_; } element_type* element_begin() { return elts_; } element_type* element_end() { return elts_ + size_; } // Contains a filled element or is empty. In which case the producer // is done and we should stop processing. class job { cooperative_pool2& cp_; uint32_t i_; // Index of element public: job(cooperative_pool2& cp) : cp_(cp), i_(cp_.get_element()) { } ~job() { release(); } void release() { if(!is_empty()) { cp_.cons_prod_.enqueue_no_check(i_); } } bool is_empty() const { return i_ == cbT::guard; } void next() { release(); i_ = cp_.get_element(); } element_type& operator*() { return cp_.elts_[i_]; } element_type* operator->() { return &cp_.elts_[i_]; } private: // Disable copy of job job(const job& rhs) { } job& operator=(const job& rhs) { } }; friend class job; /// STL compliant iterator class iterator : public std::iterator { job* j_; public: iterator() : j_(0) { } iterator(cooperative_pool2& cp) : j_(new job(cp)) { } iterator(const iterator& rhs) : j_(rhs.j_) { } bool operator==(const iterator& rhs) const { return j_ == rhs.j_; } bool operator!=(const iterator& rhs) const { return j_ != rhs.j_; } element_type& operator*() { return j_->operator*(); } element_type* operator->() { return j_->operator->(); } iterator& operator++() { j_->next(); if(j_->is_empty()) { delete j_; j_ = 0; } return *this; } iterator operator++(int) { iterator res(*this); ++*this; return res; } }; iterator begin() { return iterator(*this); } const iterator begin() const { return iterator(*this); } const iterator end() const { return iterator(); } private: enum PRODUCER_STATUS { PRODUCER_PRODUCED, PRODUCER_DONE, PRODUCER_EXISTS }; uint32_t get_element() { int iteration = 0; while(true) { // If less than half full -> try to fill up producer to consumer // queue. Disregard return value: in any every case will // attempt to get an element for ourselves if(prod_cons_.fill() < prod_cons_.size() / 2) become_producer(); uint32_t i = prod_cons_.dequeue(); if(i != cbT::guard) return i; // Try to become producer switch(become_producer()) { case PRODUCER_PRODUCED: iteration = 0; // Produced. Attempt anew to get an element break; case PRODUCER_DONE: return prod_cons_.dequeue(); case PRODUCER_EXISTS: delay(iteration++); // Already a producer. Wait a bit it adds things to queue break; } } } PRODUCER_STATUS become_producer() { if(prod_cons_.is_closed()) return PRODUCER_DONE; // Mark that we have a produce (myself). If not, return. Token // will be release automatically at end of method. take_token producer_token(tokens_); if(!producer_token.has_token()) return PRODUCER_EXISTS; uint32_t i = cbT::guard; try { while(true) { // Only way out is if produce method is done (returns true or throw an exception) i = cons_prod_.dequeue(); if(i == cbT::guard) return PRODUCER_PRODUCED; if(static_cast(this)->produce(producer_token.token_, elts_[i])) // produce returns true if done break; prod_cons_.enqueue_no_check(i); } } catch(...) { } // Threw an exception -> same as being done // Producing is done for this producer cons_prod_.enqueue_no_check(i); producer_token.drop(); uint32_t is_done = __sync_add_and_fetch(&done_, (uint32_t)1); if(is_done < max_producers_) return PRODUCER_PRODUCED; prod_cons_.close(); return PRODUCER_DONE; } // First 16 operations -> no delay. Then exponential back-off up to a second. void delay(int iteration) { if(iteration < 16) return; int shift = 10 - std::min(iteration - 16, 10); usleep((1000000 - 1) >> shift); } }; } // namespace jellyfish { #endif /* __JELLYFISH_COOPERATIVE_POOL2_HPP__ */ Jellyfish-2.2.8/include/jellyfish/cpp_array.hpp000066400000000000000000000107501323712541700215710ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_CPP_ARRAY_HPP_ #define __JELLYFISH_CPP_ARRAY_HPP_ #include #include namespace jellyfish { /// Fix length array of type T. An element is initialized with the init method. /// new (this->data() + i) T( template class cpp_array { protected: std::pair data_; std::pair init_; size_t size_; public: cpp_array(size_t size) : data_(std::get_temporary_buffer(size)), init_(std::get_temporary_buffer(size)), size_(size) { if(data_.first == 0 || init_.first == 0) { std::return_temporary_buffer(data_.first); std::return_temporary_buffer(init_.first); throw std::bad_alloc(); } memset(init_.first, '\0', sizeof(bool) * size_); } ~cpp_array() { clear(); std::return_temporary_buffer(data_.first); std::return_temporary_buffer(init_.first); } /// Initialize element i with 0 argument void init(size_t i) { release(i); new (data_.first + i) T(); init_.first[i] = true; } /// Initialize element i with 1 argument template void init(size_t i, A1& a1) { release(i); new (data_.first + i) T(a1); init_.first[i] = true; } template void init(size_t i, A1* a1) { release(i); new (data_.first + i) T(a1); init_.first[i] = true; } /// Initialize element i with 2 arguments template void init(size_t i, A1& a1, A2& a2) { release(i); new (data_.first + i) T(a1, a2); init_.first[i] = true; } template void init(size_t i, A1* a1, A2& a2) { release(i); new (data_.first + i) T(a1, a2); init_.first[i] = true; } template void init(size_t i, A1& a1, A2* a2) { release(i); new (data_.first + i) T(a1, a2); init_.first[i] = true; } template void init(size_t i, A1* a1, A2* a2) { release(i); new (data_.first + i) T(a1, a2); init_.first[i] = true; } /// Initialize element i with 3 arguments template void init(size_t i, A1 a1, A2 a2, A3 a3) { release(i); new (data_.first + i) T(a1, a2, a3); init_.first[i] = true; } /// Initialize element i with 4 arguments template void init(size_t i, A1 a1, A2 a2, A3 a3, A4 a4) { release(i); new (data_.first + i) T(a1, a2, a3, a4); init_.first[i] = true; } /// Initialize element i with 5 arguments template void init(size_t i, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { release(i); new (data_.first + i) T(a1, a2, a3, a4, a5); init_.first[i] = true; } void release(size_t i) { if(init_.first[i]) { data_.first[i].~T(); init_.first[i] = false; } } size_t size() const { return size_; } bool empty() const { return size_ == 0; } T& operator[](size_t i) { return data_.first[i]; } const T& operator[](size_t i) const { return data_.first[i]; } bool initialized(size_t i) const { return init_.first[i]; } T* begin() { return data_.first; } T* end() { return data_.first + size_; } const T* begin() const { return data_.first; } const T* end() const { return data_.end + size_; } const T* cbegin() const { return data_.first; } const T* cend() const { return data_.end + size_; } T* data() { return data_.first; } const T* data() const { return data_.first; } T& front() { return data_.first[0]; } T& back() { return data_.first[size_ - 1]; } const T& front() const { return data_.first[0]; } const T& back() const { return data_.first[size_ - 1]; } void clear() { for(size_t i = 0; i < size_; ++i) release(i); } }; } // namespace jellyfish #endif /* __JELLYFISH_CPP_ARRAY_HPP_ */ Jellyfish-2.2.8/include/jellyfish/divisor.hpp000066400000000000000000000062011323712541700212640ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_DIVISOR_HPP__ #define __JELLYFISH_DIVISOR_HPP__ #include #ifdef HAVE_CONFIG_H #include #endif namespace jflib { class divisor64 { const uint64_t d_; #ifdef HAVE_INT128 const uint16_t p_; const unsigned __int128 m_; #endif template static T div_ceil(T x, T y) { T q = x / y; T r = x % y; return q + (r > 0); } template static uint16_t ceilLog2(T x, uint16_t r = 0, uint16_t i = 0) { if(x > 1) return ceilLog2(x >> 1, r + 1, i | (x & 1)); return r + i; } public: explicit divisor64(uint64_t d) : d_(d) #ifdef HAVE_INT128 , p_(ceilLog2(d_)), m_((div_ceil((unsigned __int128)1 << (64 + p_), (unsigned __int128)d_)) & (uint64_t)-1) #endif { } divisor64() : d_(0) #ifdef HAVE_INT128 , p_(0), m_(0) #endif { } explicit divisor64(const divisor64& rhs) : d_(rhs.d_) #ifdef HAVE_INT128 , p_(rhs.p_), m_(rhs.m_) #endif { } inline uint64_t divide(const uint64_t n) const { #ifdef HAVE_INT128 switch(m_) { case 0: return n >> p_; default: const unsigned __int128 n_ = (unsigned __int128)n; return (n_ + ((n_ * m_) >> 64)) >> p_; } #else return n / d_; #endif } inline uint64_t remainder(uint64_t n) const { #ifdef HAVE_INT128 switch(m_) { case 0: return n & (((uint64_t)1 << p_) - 1); default: return n - divide(n) * d_; } #else return n % d_; #endif } // Euclidian division: d.division(n, q, r) sets q <- n / d and r // <- n % d. This is faster than doing each independently. inline void division(uint64_t n, uint64_t &q, uint64_t &r) const { #ifdef HAVE_INT128 switch(m_) { case 0: q = n >> p_; r = n & (((uint64_t)1 << p_) - 1); break; default: q = divide(n); r = n - q * d_; break; } #else q = n / d_; r = n % d_; #endif } uint64_t d() const { return d_; } uint64_t p() const { #ifdef HAVE_INT128 return p_; #else return 0; #endif } uint64_t m() const { #ifdef HAVE_INT128 return m_; #else return 0; #endif } }; inline uint64_t operator/(uint64_t n, const divisor64& d) { return d.divide(n); } inline uint64_t operator%(uint64_t n, const divisor64& d) { return d.remainder(n); } inline std::ostream& operator<<(std::ostream& os, const divisor64& d) { return os << "d:" << d.d() << ",p:" << d.p() << ",m:" << d.m(); } } // namespace jflib #endif /* __JELLYFISH_DIVISOR_HPP__ */ Jellyfish-2.2.8/include/jellyfish/dumper.hpp000066400000000000000000000061411323712541700211040ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_DUMPER_HPP__ #define __JELLYFISH_DUMPER_HPP__ #include #include #include #include #include #include #include /** * A dumper is responsible to dump the hash array to permanent storage * and zero out the array. **/ namespace jellyfish { template class dumper_t { Time writing_time_; int index_; bool one_file_; std::vector file_names_; protected: uint64_t min_; uint64_t max_; public: define_error_class(ErrorWriting); protected: /// Open the next file with given prefix. If one_file is false, /// append _0, _1, etc. to the prefix for actual file name. If /// one_file is true, the prefix is the file name. The first time /// the file is open in trunc mode, the subsequent times in append /// mode. void open_next_file(const char *prefix, std::ofstream &out) { std::ostringstream name; name << prefix; std::ios::openmode mode = std::ios::out; if(one_file_) { mode |= (index_++ ? std::ios::ate : std::ios::trunc); } else { name << index_++; mode |= std::ios::trunc; } file_names_.push_back(name.str()); out.open(name.str().c_str()); if(out.fail()) throw ErrorWriting(err::msg() << "'" << name.str() << "': " << "Can't open file for writing" << err::no); } public: dumper_t() : writing_time_(::Time::zero), index_(0), one_file_(false), min_(0), max_(std::numeric_limits::max()) {} void dump(storage_t* ary) { Time start; _dump(ary); Time end; writing_time_ += end - start; } bool one_file() const { return one_file_; } void one_file(bool v) { one_file_ = v; } virtual void _dump(storage_t* ary) = 0; uint64_t min() const { return min_; } void min(uint64_t m) { min_ = m; } uint64_t max() const { return max_; } void max(uint64_t m) { max_ = m; } Time get_writing_time() const { return writing_time_; } int nb_files() const { return index_; } std::vector file_names() { return file_names_; } std::vector file_names_cstr() { std::vector res; for(size_t i = 0; i < file_names_.size(); ++i) res.push_back(file_names_[i].c_str()); return res; } virtual ~dumper_t() {}; }; } #endif // __DUMPER_HPP__ Jellyfish-2.2.8/include/jellyfish/err.hpp000066400000000000000000000052341323712541700204020ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_ERR_HPP__ #define __JELLYFISH_ERR_HPP__ #include #include #include #include #include #include #include #include namespace jellyfish { namespace err { struct msg { std::ostringstream msg_; msg() { } explicit msg(const std::exception& e) { *this << e; } template explicit msg(const T& x) { *this << x; } operator std::string() const { return msg_.str(); } template msg& operator<<(const T& x) { msg_ << x; return *this; } msg& operator<<(const std::exception& e) { msg_ << e.what(); // try { // std::rethrow_if_nested(e); // } catch (const std::exception& nested) { // msg_ << '\n'; // return *this << nested; // } return *this; } msg& operator<<(msg& (*pf)(msg&)) { return pf(*this); } }; // Select the correct version (GNU or XSI) version of // ::strerror_r. err::strerror_ behaves like the GNU version of strerror_r, // regardless of which version is provided by the system. inline const char* strerror__(char* buf, int res) { return res != -1 ? buf : "error"; } inline const char* strerror__(char* buf, char* res) { return res; } inline const char* strerror_r(int err, char* buf, size_t buflen) { return strerror__(buf, ::strerror_r(err, buf, buflen)); } inline std::ostream& no(std::ostream& os) { char buf[128]; return os << strerror_r(errno, buf, sizeof(buf)); } inline msg& no(msg& m) { char buf[128]; return m << strerror_r(errno, buf, sizeof(buf)); } inline void die(int code, std::string msg) { std::cerr << msg << '\n'; exit(code); } inline void die(std::string msg) { die(1, msg); } } // namespace err } // namespace jellyfish #define define_error_class(name) \ class name : public std::runtime_error { \ public: explicit name(const std::string &txt) : std::runtime_error(txt) {} \ } #endif // __JELLYFISH_ERR_HPP__ Jellyfish-2.2.8/include/jellyfish/file_header.hpp000066400000000000000000000106141323712541700220370ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_FILE_HEADER_HPP__ #define __JELLYFISH_FILE_HEADER_HPP__ #include #include #include namespace jellyfish { /// A header with jellyfish hash specific entries: size, matrix, etc. class file_header : public generic_file_header { public: file_header() : generic_file_header(sizeof(uint64_t)) { } file_header(std::istream& is) : generic_file_header(sizeof(uint64_t)) { this->read(is); } template void update_from_ary(const storage& ary) { this->size(ary.size()); this->key_len(ary.key_len()); this->val_len(ary.val_len()); this->matrix(ary.matrix()); this->max_reprobe(ary.max_reprobe()); this->set_reprobes(ary.reprobes()); } RectangularBinaryMatrix matrix(int i = 1) const { std::string name("matrix"); name += std::to_string((long long int)i); // Cast to make gcc4.4 happy! const unsigned int r = root_[name]["r"].asUInt(); const unsigned int c = root_[name]["c"].asUInt(); if(root_[name]["identity"].asBool()) return RectangularBinaryMatrix::identity(r, c); std::vector raw(c, (uint64_t)0); for(unsigned int i = 0; i < c; ++i) raw[i] = root_[name]["columns"][i].asUInt64(); return RectangularBinaryMatrix(raw.data(), r, c); } void matrix(const RectangularBinaryMatrix& m, int i = 1) { std::string name("matrix"); name += std::to_string((long long int)i); root_[name].clear(); root_[name]["r"] = m.r(); root_[name]["c"] = m.c(); if(m.is_low_identity()) { root_[name]["identity"] = true; } else { root_[name]["identity"] = false; for(unsigned int i = 0; i < m.c(); ++i) { Json::UInt64 x = m[i]; root_[name]["columns"].append(x); } } } size_t size() const { return root_["size"].asLargestUInt(); } void size(size_t s) { root_["size"] = (Json::UInt64)s; } unsigned int key_len() const { return root_["key_len"].asUInt(); } void key_len(unsigned int k) { root_["key_len"] = (Json::UInt)k; } unsigned int val_len() const { return root_["val_len"].asUInt(); } void val_len(unsigned int k) { root_["val_len"] = (Json::UInt)k; } unsigned int max_reprobe() const { return root_["max_reprobe"].asUInt(); } void max_reprobe(unsigned int m) { root_["max_reprobe"] = (Json::UInt)m; } size_t max_reprobe_offset() const { return root_["reprobes"][max_reprobe()].asLargestUInt(); } double fpr() const { return root_["fpr"].asDouble(); } void fpr(double f) { root_["fpr"] = f; } unsigned long nb_hashes() const { return root_["nb_hashes"].asUInt(); } void nb_hashes(unsigned long nbh) { root_["nb_hashes"] = (Json::UInt)nbh; } bool canonical() const { return root_.get("canonical", false).asBool(); } void canonical(bool v) { root_["canonical"] = v; } /// reprobes must be at least max_reprobe() + 1 long void get_reprobes(size_t* reprobes) const { for(unsigned int i = 0; i <= max_reprobe(); ++i) reprobes[i] = root_["reprobes"][i].asLargestUInt(); } /// This must be call after max_reprobe has been set. reprobes must /// be at least max_reprobe() + 1 long. void set_reprobes(const size_t* reprobes) { root_["reprobes"].clear(); for(unsigned int i = 0; i <= max_reprobe(); ++i) root_["reprobes"].append((Json::UInt64)reprobes[i]); } /// Length of counter field in binary/sorted format unsigned int counter_len() const { return root_["counter_len"].asUInt(); } void counter_len(unsigned int l) { root_["counter_len"] = (Json::UInt)l; } std::string format() const { return root_["format"].asString(); } void format(const std::string& s) { root_["format"] = s; } }; } // namespace jellyfish #endif /* __JELLYFISH_FILE_HEADER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/generator_manager.hpp000066400000000000000000000117501323712541700232720ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_GENERATOR_MANAGER_H__ #define __JELLYFISH_GENERATOR_MANAGER_H__ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_EXT_STDIO_FILEBUF_H #include #define STDIO_FILEBUF_TYPE __gnu_cxx::stdio_filebuf #else #include #define STDIO_FILEBUF_TYPE jellyfish::stdio_filebuf #endif #include namespace jellyfish { // Open a path and set CLOEXEC flags int open_cloexec(const char* path, int flags); // Input stream (inherit from std::istream, behaves mostly like an // ifstream), with flag O_CLOEXEC (close-on-exec) turned on. class cloexec_istream : public std::istream { static std::streambuf* open_file(const char* path) { int fd = open_cloexec(path, O_RDONLY); return new STDIO_FILEBUF_TYPE(fd, std::ios::in); } public: cloexec_istream(const cloexec_istream&) = delete; cloexec_istream(const char* path) : std::istream((open_file(path))) { } cloexec_istream(const std::string& path) : std::istream(open_file(path.c_str())) { } virtual ~cloexec_istream() { close(); } void close() { delete std::istream::rdbuf(0); } }; // This class is responsible for creating a tmp directory and // populating it with fifos. class tmp_pipes { static std::string create_tmp_dir(); std::vector create_pipes(const std::string& tmpdir, int nb_pipes); std::string tmpdir_; std::vector pipes_; std::vector pipes_paths_; public: tmp_pipes(int nb_pipes): tmpdir_(create_tmp_dir()), pipes_(create_pipes(tmpdir_, nb_pipes)) { for(auto it = pipes_.cbegin(); it != pipes_.cend(); ++it) pipes_paths_.push_back(it->c_str()); } ~tmp_pipes() { cleanup(); } size_t size() const { return pipes_.size(); } const char* operator[](int i) const { return pipes_[i].c_str(); } std::vector::const_iterator begin() const { return pipes_paths_.cbegin(); } std::vector::const_iterator end() const { return pipes_paths_.cend(); } // Discard a pipe: unlink it while it is open for writing. The // reading process will get no data and won't be able to reopen the // file, marking the end of this pipe. void discard(int i); // Discard all pipes void cleanup(); }; // This class creates a new process which manages a bunch of // "generators", sub-processes that writes into a fifo (named pipe) // and generate sequence. class generator_manager_base { tmp_pipes pipes_; pid_t manager_pid_; const char* shell_; int kill_signal_; // if >0, process has received that signal struct cmd_info_type { std::string command; int pipe; }; typedef std::map pid2pipe_type; pid2pipe_type pid2pipe_; public: generator_manager_base(int nb_pipes, const char* shell = 0) : pipes_(nb_pipes), manager_pid_(-1), shell_(shell), kill_signal_(0) { if(!shell_) shell_ = getenv("SHELL"); if(!shell_) shell_ = "/bin/sh"; } virtual ~generator_manager_base() { wait(); } const tmp_pipes& pipes() const { return pipes_; } pid_t pid() const { return manager_pid_; } // Start the manager process void start(); // Wait for manager process to finish. Return true if it finishes // with no error, false otherwise. bool wait(); protected: virtual std::string get_cmd() = 0; virtual void parent_cleanup() { } void start_commands(); void start_one_command(const std::string& command, int pipe); bool display_status(int status, const std::string& command); int setup_signal_handlers(); void unset_signal_handlers(); static void signal_handler(int signal); void cleanup(); }; class generator_manager : public generator_manager_base { cloexec_istream cmds_; public: generator_manager(const char* cmds, int nb_pipes, const char* shell = 0) : generator_manager_base(nb_pipes, shell) , cmds_(cmds) { if(!cmds_.good()) throw std::runtime_error(err::msg() << "Failed to open cmds file '" << cmds << "'"); } void parent_cleanup() { cmds_.close(); } std::string get_cmd(); }; } #endif /* __JELLYFISH_GENERATOR_MANAGER_H__ */ Jellyfish-2.2.8/include/jellyfish/generic_file_header.hpp000066400000000000000000000152361323712541700235400ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_GENERIC_FILE_HEADER_HPP__ #define __JELLYFISH_GENERIC_FILE_HEADER_HPP__ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_NSGETEXECUTABLEPATH #include #endif #include #include #include #include #include #include #include #include #include #include namespace jellyfish { /// Generic file header. It contains by default the hostname, the /// current time, the current working directory and the path to the /// executable. class generic_file_header { protected: static const int MAX_HEADER_DIGITS = 9; Json::Value root_; size_t offset_; // Nb of bytes past header struct buffer { char* data; buffer(size_t size) : data(new char[size]) { } ~buffer() { delete [] data; } }; struct restore_fmtflags { std::ostream& os_; std::ios::fmtflags flags_; std::streamsize width_; char fill_; restore_fmtflags(std::ostream& os) : os_(os), flags_(os.flags(std::ios::fmtflags())), width_(os.width()), fill_(os.fill()) { } ~restore_fmtflags() { os_.flags(flags_); os_.width(width_); os_.fill(fill_); } }; static void chomp(std::string& s) { size_t found = s.find_last_not_of(" \t\f\v\n\r"); if (found != std::string::npos) s.erase(found+1); else s.clear(); } public: explicit generic_file_header(int alignment = 0) { root_["alignment"] = alignment; } bool operator==(const generic_file_header& rhs) const { std::cerr << "operator== " << (root_ == rhs.root_) << "\n"; return root_ == rhs.root_; } bool operator!=(const generic_file_header& rhs) const { return root_ != rhs.root_; } /// Write the header to an output stream. The format will be: the /// length written in text and decimal, followed by the header in /// terse JSON format, followed by some padding to align according /// to the `alignment_` member. void write(std::ostream& os) { restore_fmtflags flags(os); Json::FastWriter writer; std::string header = writer.write(root_); chomp(header); int align = alignment(); int padding = 0; size_t hlen = header.size(); if(align > 0) { padding = (MAX_HEADER_DIGITS + header.size()) % align; if(padding) hlen += align - padding; } os << std::dec << std::right << std::setw(MAX_HEADER_DIGITS) << std::setfill('0') << hlen; os.write(header.c_str(), header.size()); offset_ = MAX_HEADER_DIGITS + hlen; if(padding) { char pad[align - padding]; memset(pad, '\0', align - padding); os.write(pad, align - padding); } } /// Read an input stream to search for a header. If one is found, /// true is returned. In that case, the position in the input stream points after the header and padding. /// /// If false is returned, the parsing failed. The /// position in the input stream may have changed and the keys /// present in this header may be anything. bool read(std::istream& is) { std::string len; int i; for(i = 0; i < MAX_HEADER_DIGITS && isdigit(is.peek()); ++i) len += is.get(); if(is.peek() != '{') return false; unsigned long hlen = atol(len.c_str()); if(hlen < 2) return false; offset_ = MAX_HEADER_DIGITS + hlen; buffer hbuf(hlen); is.read(hbuf.data, hlen); if(!is.good()) return false; const char* end = hbuf.data + hlen; while(end > hbuf.data && *(end - 1) == '\0') --end; Json::Reader reader; if(!reader.parse(hbuf.data, end, root_, false)) return false; return true; } const Json::Value root() const { return root_; } void fill_standard() { root_["hostname"] = get_hostname(); root_["pwd"] = get_pwd(); root_["time"] = get_localtime(); root_["exe_path"] = get_exe_path(); } std::string operator[](const std::string& key) const { return root_.get(key, "").asString(); } std::string operator[](const char* key) const { return root_.get(key, "").asString(); } int alignment() const { return std::max(0, root_.get("alignment", 0).asInt()); } size_t offset() const { return offset_; } std::vector cmdline() const { std::vector res; for(unsigned int i = 0; i < root_["cmdline"].size(); ++i) res.push_back(root_["cmdline"][i].asString()); return res; } void set_cmdline(int argc, char* argv[]) { root_["cmdline"].clear(); for(int i = 0; i < argc; i++) root_["cmdline"].append(argv[i]); } protected: std::string get_hostname() const { struct utsname buf; if(uname(&buf) == -1) return ""; return buf.nodename; } std::string get_pwd() const { #ifdef PATH_MAX size_t len = PATH_MAX; #else size_t len = 1024; #endif char path[len + 1]; if(!getcwd(path, len + 1)) path[0] = '\0'; return path; } std::string get_localtime() const { time_t t = time(0); std::string res(ctime(&t)); chomp(res); return res; } std::string get_exe_path() const { #ifdef HAVE_NSGETEXECUTABLEPATH return get_exe_path_macosx(); #else return get_exe_path_linux(); #endif } #ifdef HAVE_NSGETEXECUTABLEPATH std::string get_exe_path_macosx() const { #ifdef MAXPATHLEN size_t len = MAXPATHLEN; #else size_t len = 1024; #endif char path[len + 1]; if(_NSGetExecutablePath(path, (uint32_t*)&len) == -1) return ""; return std::string(path); } #endif // HAVE_NSGETEXECUTABLEPATH std::string get_exe_path_linux() const { #ifdef PATH_MAX size_t len = PATH_MAX; #else size_t len = 1024; #endif char path[len + 1]; ssize_t l = readlink("/proc/self/exe", path, len + 1); if(l == -1) return ""; return std::string(path, l); } }; inline std::ostream& operator<<(std::ostream& os, const generic_file_header& h) { Json::StyledWriter w; return os << w.write(h.root()); } } // namespace jellyfish #endif /* __JELLYFISH_GENERIC_FILE_HEADER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/hash_counter.hpp000066400000000000000000000211161323712541700222710ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __HASH_COUNTER_HPP__ #define __HASH_COUNTER_HPP__ #include #include #include #include /// Cooperative version of the hash_counter. In this implementation, /// it is expected that the given number of threads will call the /// `add` method regularly. In case the hash table is full, it gets /// enlarged using all the threads. After the work is done, every /// thread must call promptly the `done` method. namespace jellyfish{ namespace cooperative { template class hash_counter { public: typedef typename large_hash::array array; typedef typename array::key_type key_type; typedef typename array::mapped_type mapped_type; typedef typename array::value_type value_type; typedef typename array::reference reference; typedef typename array::const_reference const_reference; typedef typename array::pointer pointer; typedef typename array::const_pointer const_pointer; typedef typename array::eager_iterator eager_iterator; typedef typename array::lazy_iterator lazy_iterator; protected: array* ary_; array* new_ary_; uint16_t nb_threads_; locks::pthread::barrier size_barrier_; volatile uint16_t size_thid_, done_threads_; bool do_size_doubling_; dumper_t* dumper_; public: hash_counter(size_t size, // Size of hash. To be rounded up to a power of 2 uint16_t key_len, // Size of key in bits uint16_t val_len, // Size of val in bits uint16_t nb_threads, // Number of threads accessing this hash uint16_t reprobe_limit = 126, // Maximum reprobe const size_t* reprobes = jellyfish::quadratic_reprobes) : ary_(new array(size, key_len, val_len, reprobe_limit, reprobes)), new_ary_(0), nb_threads_(nb_threads), size_barrier_(nb_threads), size_thid_(0), done_threads_(0), do_size_doubling_(true), dumper_(0) { } ~hash_counter() { delete ary_; } array* ary() { return ary_; } const array* ary() const { return ary_; } size_t size() const { return ary_->size(); } uint16_t key_len() const { return ary_->key_len(); } uint16_t val_len() const { return ary_->val_len(); } uint16_t nb_threads() const { return nb_threads; } uint16_t reprobe_limit() const { return ary_->max_reprobe(); } /// Whether we attempt to double the size of the hash when full. bool do_size_doubling() const { return do_size_doubling_; } /// Set whether we attempt to double the size of the hash when full. void do_size_doubling(bool v) { do_size_doubling_ = v; } /// Set dumper responsible for cleaning out the array. void dumper(dumper_t *d) { dumper_ = d; } /// Add `v` to the entry `k`. It returns in `is_new` true if the /// entry `k` did not exist in the hash. In `id` is returned the /// final position of `k` in the hash array. void add(const Key& k, uint64_t v, bool* is_new, size_t* id) { unsigned int carry_shift = 0; bool* is_new_ptr = is_new; size_t* id_ptr = id; bool is_new_void = false; size_t id_void = false; while(!ary_->add(k, v, &carry_shift, is_new_ptr, id_ptr)) { handle_full_ary(); v &= ~(uint64_t)0 << carry_shift; // If carry_shift == 0, failed to allocate the first field for // key, hence status of is_new and value for id are not // determined yet. On the other hand, if carry_shift > 0, we // failed while adding extra field for large key, so the status // of is_new and value of id are known. We do not update them in future // calls. if(carry_shift) { is_new_ptr = &is_new_void; id_ptr = &id_void; } } } /// Add `v` to the entry `k`. This method is multi-thread safe. If /// the entry for `k` does not exists, it is inserted. /// /// @param k Key to add to /// @param v Value to add inline void add(const Key& k, uint64_t v) { bool is_new; size_t id; add(k, v, &is_new, &id); } /// Insert the key `k` in the hash. The value is not changed or set /// to 0 if not already in the hash. /// /// @param k Key to insert inline void set(const Key& k) { bool is_new; size_t id; set(k, &is_new, &id); } /// Insert the key `k` in the hash. The value is not changed or set /// to 0 if not already in the hash. Set `is_new` to true if `k` did /// not already exist in the hash. In `id` is returned the final /// position of `k` in the hash. void set(const Key& k, bool* is_new, size_t* id) { while(!ary_->set(k, is_new, id)) handle_full_ary(); } /// Update the value of key `k` by adding `v`, if `k` is already /// present in the hash, otherwise this nothing happens. Returns /// true if `k` is already in the hash, false otherwise. bool update_add(const Key& k, uint64_t v) { Key tmp_key; return update_add(k, v, tmp_key); } bool update_add(const Key& k, uint64_t v, Key& tmp_key) { unsigned int carry_shift = 0; while(true) { if(ary_->update_add(k, v, &carry_shift, tmp_key)) return true; if(carry_shift == 0) return false; handle_full_ary(); v &= ~(uint64_t)0 << carry_shift; } } /// Signify that thread is done and wait for all threads to be done. void done() { atomic_t::fetch_add(&done_threads_, (uint16_t)1); while(!handle_full_ary()) ; } protected: // Double the size of the hash and return false. Unless all the // thread have reported they are done, in which case do nothing and // return true. bool handle_full_ary() { bool serial_thread = size_barrier_.wait(); if(done_threads_ >= nb_threads_) // All done? return true; bool success = false; if(do_size_doubling_) success = success || double_size(serial_thread); if(!success && dumper_) { if(serial_thread) dumper_->dump(ary_); success = true; size_barrier_.wait(); } if(!success) throw std::runtime_error("Hash full"); return false; } bool double_size(bool serial_thread) { if(serial_thread) {// Allocate new array for size doubling try { if(ary_->key_len() >= sizeof(size_t) * 8 || ary_->size() < ((size_t)1 << ary_->key_len())) { // Increase number of keys new_ary_ = new array(ary_->size() * 2, ary_->key_len(), ary_->val_len(), ary_->max_reprobe(), ary_->reprobes()); } else { // Array is already maximum compared to key len, increase val_len new_ary_ = new array(ary_->size(), ary_->key_len(), ary_->val_len() + 1, ary_->max_reprobe(), ary_->reprobes()); } } catch(typename array::ErrorAllocation e) { new_ary_ = 0; } } size_thid_ = 0; size_barrier_.wait(); array* my_ary = *(array* volatile*)&new_ary_; if(!my_ary) // Allocation failed return false; // Copy data from old to new uint16_t id = atomic_t::fetch_add(&size_thid_, (uint16_t)1); eager_iterator it = ary_->eager_slice(id, nb_threads_); while(it.next()) my_ary->add(it.key(), it.val()); size_barrier_.wait(); if(serial_thread) { // Set new ary to be current and free old delete ary_; ary_ = new_ary_; } // Done. Last sync point size_barrier_.wait(); return true; } }; } } // namespace jellyfish { namespace cooperative { #endif /* __HASH_COUNTER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/int128.hpp000066400000000000000000000164741323712541700206470ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef _INT128_H_ #define _INT128_H_ #ifdef HAVE_CONFIG_H #include #ifndef HAVE_INT128 #error "The type __int128 is not supported" #endif #endif #include #include #include #include #include #include // Output of __int128: this might be slow namespace __int128_ns { template void __print_digits(std::ostream& os, unsigned __int128 x, bool lower = true) { char buf[50]; char* ptr = buf + sizeof(buf); do { int o = x % base; if(o < 10) { *--ptr = '0' + o; } else { *--ptr = (lower ? 'a' : 'A') + o - 10; } x /= base; } while (x > 0); os.write(ptr, buf + sizeof(buf) - ptr); } inline bool is_negative(unsigned __int128 x) { return false; } inline bool is_negative(__int128 x) { return x < 0; } template void __print_decimal(std::ostream& prefix, std::ostream& os, T x, const std::ios::fmtflags& ff) { if((ff & std::ios::showpos) && x > 0) prefix << "+"; if(x == 0) { os << "0"; return; } if(is_negative(x)) { prefix << "-"; x = -x; } __print_digits<10>(os, x); } void __print_bases(std::ostream& prefix, std::ostream& os, unsigned __int128 x, const std::ios::fmtflags& ff); template void __print_buf(std::ostream& prefix, std::ostream& os, T x, const std::ios::fmtflags& ff) { if(ff & std::ios::dec) __print_decimal(prefix, os, x, ff); else __print_bases(prefix, os, (unsigned __int128)x, ff); } template void __print(std::ostream&os, T x) { const std::ios_base::fmtflags ff = os.flags(); if(!(ff & std::ios::adjustfield)) return __print_buf(os, os, x, ff); std::ostringstream prefix; std::ostringstream buf; __print_buf(prefix, buf, x, ff); ssize_t nb_padding = os.width() - (prefix.str().size() + buf.str().size()); if(nb_padding <= 0) { os.write(prefix.str().c_str(), prefix.tellp()); os.write(buf.str().c_str(), buf.tellp()); return; } char padding[nb_padding]; memset(padding, os.fill(), nb_padding); if(ff & std::ios::right) os.write(padding, nb_padding); os.write(prefix.str().c_str(), prefix.tellp()); if(ff & std::ios::internal) os.write(padding, nb_padding); os.write(buf.str().c_str(), buf.tellp()); if(ff & std::ios::left) os.write(padding, nb_padding); } } inline std::ostream& operator<<(std::ostream& os, __int128 x) { __int128_ns::__print(os, x); return os; } inline std::ostream& operator<<(std::ostream& os, unsigned __int128 x) { __int128_ns::__print(os, x); return os; } #ifndef HAVE_NUMERIC_LIMITS128 namespace std { template<> class numeric_limits<__int128> { public: static const bool is_specialized = true; static __int128 max() { return (unsigned __int128)-1 >> 1; } static __int128 min() { return max() + 1; } static const int digits = 127; static const int digits10 = 38; #define NLS64 numeric_limits static const bool is_signed = NLS64::is_signed; static const bool is_integer = NLS64::is_integer; static const bool is_exact = NLS64::is_exact; static const int radix = NLS64::radix; static __int128 epsilon() { return NLS64::epsilon(); } static __int128 round_error() { return NLS64::round_error(); } static const int min_exponent = NLS64::min_exponent; static const int min_exponent10 = NLS64::min_exponent10; static const int max_exponent = NLS64::max_exponent; static const int max_exponent10 = NLS64::max_exponent10; static const bool has_infinity = NLS64::has_infinity; static const bool has_quiet_NaN = NLS64::has_quiet_NaN; static const bool has_signaling_NaN = NLS64::has_signaling_NaN; static const float_denorm_style has_denorm = NLS64::has_denorm; static const bool has_denorm_loss = NLS64::has_denorm_loss; static __int128 infinity() { return NLS64::infinity(); } static __int128 quiet_NaN() { return NLS64::quiet_NaN(); } static __int128 signaling_NaN() { return NLS64::signaling_NaN(); } static __int128 denorm_min() { return NLS64::denorm_min(); } static const bool is_iec559 = NLS64::is_iec559; static const bool is_bounded = NLS64::is_bounded; static const bool is_modulo = NLS64::is_modulo; static const bool traps = NLS64::traps; static const bool tinyness_before = NLS64::tinyness_before; static const float_round_style round_style = NLS64::round_style; }; template<> class numeric_limits { public: static const bool is_specialized = true; static __int128 max() { return (unsigned __int128)-1; } static __int128 min() { return 0; } static const int digits = 128; static const int digits10 = 39; #define NLU64 numeric_limits static const bool is_signed = NLU64::is_signed; static const bool is_integer = NLU64::is_integer; static const bool is_exact = NLU64::is_exact; static const int radix = NLU64::radix; static __int128 epsilon() { return NLU64::epsilon(); } static __int128 round_error() { return NLU64::round_error(); } static const int min_exponent = NLU64::min_exponent; static const int min_exponent10 = NLU64::min_exponent10; static const int max_exponent = NLU64::max_exponent; static const int max_exponent10 = NLU64::max_exponent10; static const bool has_infinity = NLU64::has_infinity; static const bool has_quiet_NaN = NLU64::has_quiet_NaN; static const bool has_signaling_NaN = NLU64::has_signaling_NaN; static const float_denorm_style has_denorm = NLU64::has_denorm; static const bool has_denorm_loss = NLU64::has_denorm_loss; static __int128 infinity() { return NLU64::infinity(); } static __int128 quiet_NaN() { return NLU64::quiet_NaN(); } static __int128 signaling_NaN() { return NLU64::signaling_NaN(); } static __int128 denorm_min() { return NLU64::denorm_min(); } static const bool is_iec559 = NLU64::is_iec559; static const bool is_bounded = NLU64::is_bounded; static const bool is_modulo = NLU64::is_modulo; static const bool traps = NLU64::traps; static const bool tinyness_before = NLU64::tinyness_before; static const float_round_style round_style = NLU64::round_style; }; } // namespace std #endif /* HAVE_NUMERIC_LIMITS128 */ #endif /* _INT128_H_ */ Jellyfish-2.2.8/include/jellyfish/jellyfish.hpp000066400000000000000000000030511323712541700215760ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_JELLYFISH_HPP__ #define __JELLYFISH_JELLYFISH_HPP__ #include #include #include #include #include typedef jellyfish::cooperative::hash_counter mer_hash; typedef mer_hash::array mer_array; typedef jellyfish::text_dumper text_dumper; typedef jellyfish::text_reader text_reader; typedef jellyfish::binary_dumper binary_dumper; typedef jellyfish::binary_reader binary_reader; typedef jellyfish::binary_query_base binary_query; typedef jellyfish::binary_writer binary_writer; typedef jellyfish::text_writer text_writer; #endif /* __JELLYFISH_JELLYFISH_HPP__ */ Jellyfish-2.2.8/include/jellyfish/json.h000066400000000000000000001704011323712541700202220ustar00rootroot00000000000000/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). /// It is intented to be used with #include // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: LICENSE // ////////////////////////////////////////////////////////////////////// /* The JsonCpp library's source code, including accompanying documentation, tests and demonstration applications, are licensed under the following conditions... The author (Baptiste Lepilleur) explicitly disclaims copyright in all jurisdictions which recognize such a disclaimer. In such jurisdictions, this software is released into the Public Domain. In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is released under the terms of the MIT License (see below). In jurisdictions which recognize Public Domain property, the user of this software may choose to accept it either as 1) Public Domain, 2) under the conditions of the MIT License (see below), or 3) under the terms of dual Public Domain/MIT License conditions described here, as they choose. The MIT License is about as close to Public Domain as a license can get, and is described in clear, concise terms at: http://en.wikipedia.org/wiki/MIT_License The full text of the MIT License follows: ======================================================================== Copyright (c) 2007-2010 Baptiste Lepilleur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ======================================================================== (END LICENSE TEXT) The MIT license is compatible with both the GPL and commercial software, affording one all of the rights of Public Domain with the minor nuisance of being required to keep the above copyright notice and license text in the source code. Note also that by accepting the Public Domain "license" you can re-license your copy using whatever license you like. */ // ////////////////////////////////////////////////////////////////////// // End of content of file: LICENSE // ////////////////////////////////////////////////////////////////////// #ifndef JSON_AMALGATED_H_INCLUDED # define JSON_AMALGATED_H_INCLUDED /// If defined, indicates that the source file is amalgated /// to prevent private header inclusion. #define JSON_IS_AMALGATED // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: include/json/config.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef JSON_CONFIG_H_INCLUDED # define JSON_CONFIG_H_INCLUDED /// If defined, indicates that json library is embedded in CppTL library. //# define JSON_IN_CPPTL 1 /// If defined, indicates that json may leverage CppTL library //# define JSON_USE_CPPTL 1 /// If defined, indicates that cpptl vector based map should be used instead of std::map /// as Value container. //# define JSON_USE_CPPTL_SMALLMAP 1 /// If defined, indicates that Json specific container should be used /// (hash table & simple deque container with customizable allocator). /// THIS FEATURE IS STILL EXPERIMENTAL! There is know bugs: See #3177332 //# define JSON_VALUE_USE_INTERNAL_MAP 1 /// Force usage of standard new/malloc based allocator instead of memory pool based allocator. /// The memory pools allocator used optimization (initializing Value and ValueInternalLink /// as if it was a POD) that may cause some validation tool to report errors. /// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined. //# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1 /// If defined, indicates that Json use exception to report invalid type manipulation /// instead of C assert macro. /// # define JSON_USE_EXCEPTION 1 /// If defined, indicates that the source file is amalgated /// to prevent private header inclusion. /// Remarks: it is automatically defined in the generated amalgated header. #define JSON_IS_AMALGAMATION 1 # ifdef JSON_IN_CPPTL # include # ifndef JSON_USE_CPPTL # define JSON_USE_CPPTL 1 # endif # endif # ifdef JSON_IN_CPPTL # define JSON_API CPPTL_API # elif defined(JSON_DLL_BUILD) # define JSON_API __declspec(dllexport) # elif defined(JSON_DLL) # define JSON_API __declspec(dllimport) # else # define JSON_API # endif // If JSON_NO_INT64 is defined, then Json only support C++ "int" type for integer // Storages, and 64 bits integer support is disabled. // #define JSON_NO_INT64 1 #if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 // Microsoft Visual Studio 6 only support conversion from __int64 to double // (no conversion from unsigned __int64). #define JSON_USE_INT64_DOUBLE_CONVERSION 1 #endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 #if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 /// Indicates that the following function is deprecated. # define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) #endif #if !defined(JSONCPP_DEPRECATED) # define JSONCPP_DEPRECATED(message) #endif // if !defined(JSONCPP_DEPRECATED) namespace Json { typedef int Int; typedef unsigned int UInt; # if defined(JSON_NO_INT64) typedef int LargestInt; typedef unsigned int LargestUInt; # undef JSON_HAS_INT64 # else // if defined(JSON_NO_INT64) // For Microsoft Visual use specific types as long long is not supported # if defined(_MSC_VER) // Microsoft Visual Studio typedef __int64 Int64; typedef unsigned __int64 UInt64; # else // if defined(_MSC_VER) // Other platforms, use long long typedef long long int Int64; typedef unsigned long long int UInt64; # endif // if defined(_MSC_VER) typedef Int64 LargestInt; typedef UInt64 LargestUInt; # define JSON_HAS_INT64 # endif // if defined(JSON_NO_INT64) } // end namespace Json #endif // JSON_CONFIG_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: include/json/config.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: include/json/forwards.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef JSON_FORWARDS_H_INCLUDED # define JSON_FORWARDS_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) # include "config.h" #endif // if !defined(JSON_IS_AMALGAMATION) namespace Json { // writer.h class FastWriter; class StyledWriter; // reader.h class Reader; // features.h class Features; // value.h typedef unsigned int ArrayIndex; class StaticString; class Path; class PathArgument; class Value; class ValueIteratorBase; class ValueIterator; class ValueConstIterator; #ifdef JSON_VALUE_USE_INTERNAL_MAP class ValueMapAllocator; class ValueInternalLink; class ValueInternalArray; class ValueInternalMap; #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP } // namespace Json #endif // JSON_FORWARDS_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: include/json/forwards.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: include/json/features.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef CPPTL_JSON_FEATURES_H_INCLUDED # define CPPTL_JSON_FEATURES_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) # include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) namespace Json { /** \brief Configuration passed to reader and writer. * This configuration object can be used to force the Reader or Writer * to behave in a standard conforming way. */ class JSON_API Features { public: /** \brief A configuration that allows all features and assumes all strings are UTF-8. * - C & C++ comments are allowed * - Root object can be any JSON value * - Assumes Value strings are encoded in UTF-8 */ static Features all(); /** \brief A configuration that is strictly compatible with the JSON specification. * - Comments are forbidden. * - Root object must be either an array or an object value. * - Assumes Value strings are encoded in UTF-8 */ static Features strictMode(); /** \brief Initialize the configuration like JsonConfig::allFeatures; */ Features(); /// \c true if comments are allowed. Default: \c true. bool allowComments_; /// \c true if root must be either an array or an object value. Default: \c false. bool strictRoot_; }; } // namespace Json #endif // CPPTL_JSON_FEATURES_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: include/json/features.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: include/json/value.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef CPPTL_JSON_H_INCLUDED # define CPPTL_JSON_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) # include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) # include # include # ifndef JSON_USE_CPPTL_SMALLMAP # include # else # include # endif # ifdef JSON_USE_CPPTL # include # endif /** \brief JSON (JavaScript Object Notation). */ namespace Json { /** \brief Type of the value held by a Value object. */ enum ValueType { nullValue = 0, ///< 'null' value intValue, ///< signed integer value uintValue, ///< unsigned integer value realValue, ///< double value stringValue, ///< UTF-8 string value booleanValue, ///< bool value arrayValue, ///< array value (ordered list) objectValue ///< object value (collection of name/value pairs). }; enum CommentPlacement { commentBefore = 0, ///< a comment placed on the line before a value commentAfterOnSameLine, ///< a comment just after a value on the same line commentAfter, ///< a comment on the line after a value (only make sense for root value) numberOfCommentPlacement }; //# ifdef JSON_USE_CPPTL // typedef CppTL::AnyEnumerator EnumMemberNames; // typedef CppTL::AnyEnumerator EnumValues; //# endif /** \brief Lightweight wrapper to tag static string. * * Value constructor and objectValue member assignement takes advantage of the * StaticString and avoid the cost of string duplication when storing the * string or the member name. * * Example of usage: * \code * Json::Value aValue( StaticString("some text") ); * Json::Value object; * static const StaticString code("code"); * object[code] = 1234; * \endcode */ class JSON_API StaticString { public: explicit StaticString( const char *czstring ) : str_( czstring ) { } operator const char *() const { return str_; } const char *c_str() const { return str_; } private: const char *str_; }; /** \brief Represents a JSON value. * * This class is a discriminated union wrapper that can represents a: * - signed integer [range: Value::minInt - Value::maxInt] * - unsigned integer (range: 0 - Value::maxUInt) * - double * - UTF-8 string * - boolean * - 'null' * - an ordered list of Value * - collection of name/value pairs (javascript object) * * The type of the held value is represented by a #ValueType and * can be obtained using type(). * * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. * Non const methods will automatically create the a #nullValue element * if it does not exist. * The sequence of an #arrayValue will be automatically resize and initialized * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. * * The get() methods can be used to obtanis default value in the case the required element * does not exist. * * It is possible to iterate over the list of a #objectValue values using * the getMemberNames() method. */ class JSON_API Value { friend class ValueIteratorBase; # ifdef JSON_VALUE_USE_INTERNAL_MAP friend class ValueInternalLink; friend class ValueInternalMap; # endif public: typedef std::vector Members; typedef ValueIterator iterator; typedef ValueConstIterator const_iterator; typedef Json::UInt UInt; typedef Json::Int Int; # if defined(JSON_HAS_INT64) typedef Json::UInt64 UInt64; typedef Json::Int64 Int64; #endif // defined(JSON_HAS_INT64) typedef Json::LargestInt LargestInt; typedef Json::LargestUInt LargestUInt; typedef Json::ArrayIndex ArrayIndex; static const Value null; /// Minimum signed integer value that can be stored in a Json::Value. static const LargestInt minLargestInt; /// Maximum signed integer value that can be stored in a Json::Value. static const LargestInt maxLargestInt; /// Maximum unsigned integer value that can be stored in a Json::Value. static const LargestUInt maxLargestUInt; /// Minimum signed int value that can be stored in a Json::Value. static const Int minInt; /// Maximum signed int value that can be stored in a Json::Value. static const Int maxInt; /// Maximum unsigned int value that can be stored in a Json::Value. static const UInt maxUInt; /// Minimum signed 64 bits int value that can be stored in a Json::Value. static const Int64 minInt64; /// Maximum signed 64 bits int value that can be stored in a Json::Value. static const Int64 maxInt64; /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. static const UInt64 maxUInt64; private: #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION # ifndef JSON_VALUE_USE_INTERNAL_MAP class CZString { public: enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; CZString( ArrayIndex index ); CZString( const char *cstr, DuplicationPolicy allocate ); CZString( const CZString &other ); ~CZString(); CZString &operator =( const CZString &other ); bool operator<( const CZString &other ) const; bool operator==( const CZString &other ) const; ArrayIndex index() const; const char *c_str() const; bool isStaticString() const; private: void swap( CZString &other ); const char *cstr_; ArrayIndex index_; }; public: # ifndef JSON_USE_CPPTL_SMALLMAP typedef std::map ObjectValues; # else typedef CppTL::SmallMap ObjectValues; # endif // ifndef JSON_USE_CPPTL_SMALLMAP # endif // ifndef JSON_VALUE_USE_INTERNAL_MAP #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION public: /** \brief Create a default Value of the given type. This is a very useful constructor. To create an empty array, pass arrayValue. To create an empty object, pass objectValue. Another Value can then be set to this one by assignment. This is useful since clear() and resize() will not alter types. Examples: \code Json::Value null_value; // null Json::Value arr_value(Json::arrayValue); // [] Json::Value obj_value(Json::objectValue); // {} \endcode */ Value( ValueType type = nullValue ); Value( Int value ); Value( UInt value ); #if defined(JSON_HAS_INT64) Value( Int64 value ); Value( UInt64 value ); #endif // if defined(JSON_HAS_INT64) Value( double value ); Value( const char *value ); Value( const char *beginValue, const char *endValue ); /** \brief Constructs a value from a static string. * Like other value string constructor but do not duplicate the string for * internal storage. The given string must remain alive after the call to this * constructor. * Example of usage: * \code * Json::Value aValue( StaticString("some text") ); * \endcode */ Value( const StaticString &value ); Value( const std::string &value ); # ifdef JSON_USE_CPPTL Value( const CppTL::ConstString &value ); # endif Value( bool value ); Value( const Value &other ); ~Value(); Value &operator=( const Value &other ); /// Swap values. /// \note Currently, comments are intentionally not swapped, for /// both logic and efficiency. void swap( Value &other ); ValueType type() const; bool operator <( const Value &other ) const; bool operator <=( const Value &other ) const; bool operator >=( const Value &other ) const; bool operator >( const Value &other ) const; bool operator ==( const Value &other ) const; bool operator !=( const Value &other ) const; int compare( const Value &other ) const; const char *asCString() const; std::string asString() const; # ifdef JSON_USE_CPPTL CppTL::ConstString asConstString() const; # endif Int asInt() const; UInt asUInt() const; Int64 asInt64() const; UInt64 asUInt64() const; LargestInt asLargestInt() const; LargestUInt asLargestUInt() const; float asFloat() const; double asDouble() const; bool asBool() const; bool isNull() const; bool isBool() const; bool isInt() const; bool isUInt() const; bool isIntegral() const; bool isDouble() const; bool isNumeric() const; bool isString() const; bool isArray() const; bool isObject() const; bool isConvertibleTo( ValueType other ) const; /// Number of values in array or object ArrayIndex size() const; /// \brief Return true if empty array, empty object, or null; /// otherwise, false. bool empty() const; /// Return isNull() bool operator!() const; /// Remove all object members and array elements. /// \pre type() is arrayValue, objectValue, or nullValue /// \post type() is unchanged void clear(); /// Resize the array to size elements. /// New elements are initialized to null. /// May only be called on nullValue or arrayValue. /// \pre type() is arrayValue or nullValue /// \post type() is arrayValue void resize( ArrayIndex size ); /// Access an array element (zero based index ). /// If the array contains less than index element, then null value are inserted /// in the array so that its size is index+1. /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) Value &operator[]( ArrayIndex index ); /// Access an array element (zero based index ). /// If the array contains less than index element, then null value are inserted /// in the array so that its size is index+1. /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) Value &operator[]( int index ); /// Access an array element (zero based index ) /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) const Value &operator[]( ArrayIndex index ) const; /// Access an array element (zero based index ) /// (You may need to say 'value[0u]' to get your compiler to distinguish /// this from the operator[] which takes a string.) const Value &operator[]( int index ) const; /// If the array contains at least index+1 elements, returns the element value, /// otherwise returns defaultValue. Value get( ArrayIndex index, const Value &defaultValue ) const; /// Return true if index < size(). bool isValidIndex( ArrayIndex index ) const; /// \brief Append value to array at the end. /// /// Equivalent to jsonvalue[jsonvalue.size()] = value; Value &append( const Value &value ); /// Access an object value by name, create a null member if it does not exist. Value &operator[]( const char *key ); /// Access an object value by name, returns null if there is no member with that name. const Value &operator[]( const char *key ) const; /// Access an object value by name, create a null member if it does not exist. Value &operator[]( const std::string &key ); /// Access an object value by name, returns null if there is no member with that name. const Value &operator[]( const std::string &key ) const; /** \brief Access an object value by name, create a null member if it does not exist. * If the object as no entry for that name, then the member name used to store * the new entry is not duplicated. * Example of use: * \code * Json::Value object; * static const StaticString code("code"); * object[code] = 1234; * \endcode */ Value &operator[]( const StaticString &key ); # ifdef JSON_USE_CPPTL /// Access an object value by name, create a null member if it does not exist. Value &operator[]( const CppTL::ConstString &key ); /// Access an object value by name, returns null if there is no member with that name. const Value &operator[]( const CppTL::ConstString &key ) const; # endif /// Return the member named key if it exist, defaultValue otherwise. Value get( const char *key, const Value &defaultValue ) const; /// Return the member named key if it exist, defaultValue otherwise. Value get( const std::string &key, const Value &defaultValue ) const; # ifdef JSON_USE_CPPTL /// Return the member named key if it exist, defaultValue otherwise. Value get( const CppTL::ConstString &key, const Value &defaultValue ) const; # endif /// \brief Remove and return the named member. /// /// Do nothing if it did not exist. /// \return the removed Value, or null. /// \pre type() is objectValue or nullValue /// \post type() is unchanged Value removeMember( const char* key ); /// Same as removeMember(const char*) Value removeMember( const std::string &key ); /// Return true if the object has a member named key. bool isMember( const char *key ) const; /// Return true if the object has a member named key. bool isMember( const std::string &key ) const; # ifdef JSON_USE_CPPTL /// Return true if the object has a member named key. bool isMember( const CppTL::ConstString &key ) const; # endif /// \brief Return a list of the member names. /// /// If null, return an empty list. /// \pre type() is objectValue or nullValue /// \post if type() was nullValue, it remains nullValue Members getMemberNames() const; //# ifdef JSON_USE_CPPTL // EnumMemberNames enumMemberNames() const; // EnumValues enumValues() const; //# endif /// Comments must be //... or /* ... */ void setComment( const char *comment, CommentPlacement placement ); /// Comments must be //... or /* ... */ void setComment( const std::string &comment, CommentPlacement placement ); bool hasComment( CommentPlacement placement ) const; /// Include delimiters and embedded newlines. std::string getComment( CommentPlacement placement ) const; std::string toStyledString() const; const_iterator begin() const; const_iterator end() const; iterator begin(); iterator end(); private: Value &resolveReference( const char *key, bool isStatic ); # ifdef JSON_VALUE_USE_INTERNAL_MAP inline bool isItemAvailable() const { return itemIsUsed_ == 0; } inline void setItemUsed( bool isUsed = true ) { itemIsUsed_ = isUsed ? 1 : 0; } inline bool isMemberNameStatic() const { return memberNameIsStatic_ == 0; } inline void setMemberNameIsStatic( bool isStatic ) { memberNameIsStatic_ = isStatic ? 1 : 0; } # endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP private: struct CommentInfo { CommentInfo(); ~CommentInfo(); void setComment( const char *text ); char *comment_; }; //struct MemberNamesTransform //{ // typedef const char *result_type; // const char *operator()( const CZString &name ) const // { // return name.c_str(); // } //}; union ValueHolder { LargestInt int_; LargestUInt uint_; double real_; bool bool_; char *string_; # ifdef JSON_VALUE_USE_INTERNAL_MAP ValueInternalArray *array_; ValueInternalMap *map_; #else ObjectValues *map_; # endif } value_; ValueType type_ : 8; int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. # ifdef JSON_VALUE_USE_INTERNAL_MAP unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. # endif CommentInfo *comments_; }; /** \brief Experimental and untested: represents an element of the "path" to access a node. */ class PathArgument { public: friend class Path; PathArgument(); PathArgument( ArrayIndex index ); PathArgument( const char *key ); PathArgument( const std::string &key ); private: enum Kind { kindNone = 0, kindIndex, kindKey }; std::string key_; ArrayIndex index_; Kind kind_; }; /** \brief Experimental and untested: represents a "path" to access a node. * * Syntax: * - "." => root node * - ".[n]" => elements at index 'n' of root node (an array value) * - ".name" => member named 'name' of root node (an object value) * - ".name1.name2.name3" * - ".[0][1][2].name1[3]" * - ".%" => member name is provided as parameter * - ".[%]" => index is provied as parameter */ class Path { public: Path( const std::string &path, const PathArgument &a1 = PathArgument(), const PathArgument &a2 = PathArgument(), const PathArgument &a3 = PathArgument(), const PathArgument &a4 = PathArgument(), const PathArgument &a5 = PathArgument() ); const Value &resolve( const Value &root ) const; Value resolve( const Value &root, const Value &defaultValue ) const; /// Creates the "path" to access the specified node and returns a reference on the node. Value &make( Value &root ) const; private: typedef std::vector InArgs; typedef std::vector Args; void makePath( const std::string &path, const InArgs &in ); void addPathInArg( const std::string &path, const InArgs &in, InArgs::const_iterator &itInArg, PathArgument::Kind kind ); void invalidPath( const std::string &path, int location ); Args args_; }; #ifdef JSON_VALUE_USE_INTERNAL_MAP /** \brief Allocator to customize Value internal map. * Below is an example of a simple implementation (default implementation actually * use memory pool for speed). * \code class DefaultValueMapAllocator : public ValueMapAllocator { public: // overridden from ValueMapAllocator virtual ValueInternalMap *newMap() { return new ValueInternalMap(); } virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) { return new ValueInternalMap( other ); } virtual void destructMap( ValueInternalMap *map ) { delete map; } virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) { return new ValueInternalLink[size]; } virtual void releaseMapBuckets( ValueInternalLink *links ) { delete [] links; } virtual ValueInternalLink *allocateMapLink() { return new ValueInternalLink(); } virtual void releaseMapLink( ValueInternalLink *link ) { delete link; } }; * \endcode */ class JSON_API ValueMapAllocator { public: virtual ~ValueMapAllocator(); virtual ValueInternalMap *newMap() = 0; virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; virtual void destructMap( ValueInternalMap *map ) = 0; virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; virtual ValueInternalLink *allocateMapLink() = 0; virtual void releaseMapLink( ValueInternalLink *link ) = 0; }; /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). * \internal previous_ & next_ allows for bidirectional traversal. */ class JSON_API ValueInternalLink { public: enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. enum InternalFlags { flagAvailable = 0, flagUsed = 1 }; ValueInternalLink(); ~ValueInternalLink(); Value items_[itemPerLink]; char *keys_[itemPerLink]; ValueInternalLink *previous_; ValueInternalLink *next_; }; /** \brief A linked page based hash-table implementation used internally by Value. * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked * list in each bucket to handle collision. There is an addional twist in that * each node of the collision linked list is a page containing a fixed amount of * value. This provides a better compromise between memory usage and speed. * * Each bucket is made up of a chained list of ValueInternalLink. The last * link of a given bucket can be found in the 'previous_' field of the following bucket. * The last link of the last bucket is stored in tailLink_ as it has no following bucket. * Only the last link of a bucket may contains 'available' item. The last link always * contains at least one element unless is it the bucket one very first link. */ class JSON_API ValueInternalMap { friend class ValueIteratorBase; friend class Value; public: typedef unsigned int HashKey; typedef unsigned int BucketIndex; # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION struct IteratorState { IteratorState() : map_(0) , link_(0) , itemIndex_(0) , bucketIndex_(0) { } ValueInternalMap *map_; ValueInternalLink *link_; BucketIndex itemIndex_; BucketIndex bucketIndex_; }; # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION ValueInternalMap(); ValueInternalMap( const ValueInternalMap &other ); ValueInternalMap &operator =( const ValueInternalMap &other ); ~ValueInternalMap(); void swap( ValueInternalMap &other ); BucketIndex size() const; void clear(); bool reserveDelta( BucketIndex growth ); bool reserve( BucketIndex newItemCount ); const Value *find( const char *key ) const; Value *find( const char *key ); Value &resolveReference( const char *key, bool isStatic ); void remove( const char *key ); void doActualRemove( ValueInternalLink *link, BucketIndex index, BucketIndex bucketIndex ); ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); Value &setNewItem( const char *key, bool isStatic, ValueInternalLink *link, BucketIndex index ); Value &unsafeAdd( const char *key, bool isStatic, HashKey hashedKey ); HashKey hash( const char *key ) const; int compare( const ValueInternalMap &other ) const; private: void makeBeginIterator( IteratorState &it ) const; void makeEndIterator( IteratorState &it ) const; static bool equals( const IteratorState &x, const IteratorState &other ); static void increment( IteratorState &iterator ); static void incrementBucket( IteratorState &iterator ); static void decrement( IteratorState &iterator ); static const char *key( const IteratorState &iterator ); static const char *key( const IteratorState &iterator, bool &isStatic ); static Value &value( const IteratorState &iterator ); static int distance( const IteratorState &x, const IteratorState &y ); private: ValueInternalLink *buckets_; ValueInternalLink *tailLink_; BucketIndex bucketsSize_; BucketIndex itemCount_; }; /** \brief A simplified deque implementation used internally by Value. * \internal * It is based on a list of fixed "page", each page contains a fixed number of items. * Instead of using a linked-list, a array of pointer is used for fast item look-up. * Look-up for an element is as follow: * - compute page index: pageIndex = itemIndex / itemsPerPage * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] * * Insertion is amortized constant time (only the array containing the index of pointers * need to be reallocated when items are appended). */ class JSON_API ValueInternalArray { friend class Value; friend class ValueIteratorBase; public: enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. typedef Value::ArrayIndex ArrayIndex; typedef unsigned int PageIndex; # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION struct IteratorState // Must be a POD { IteratorState() : array_(0) , currentPageIndex_(0) , currentItemIndex_(0) { } ValueInternalArray *array_; Value **currentPageIndex_; unsigned int currentItemIndex_; }; # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION ValueInternalArray(); ValueInternalArray( const ValueInternalArray &other ); ValueInternalArray &operator =( const ValueInternalArray &other ); ~ValueInternalArray(); void swap( ValueInternalArray &other ); void clear(); void resize( ArrayIndex newSize ); Value &resolveReference( ArrayIndex index ); Value *find( ArrayIndex index ) const; ArrayIndex size() const; int compare( const ValueInternalArray &other ) const; private: static bool equals( const IteratorState &x, const IteratorState &other ); static void increment( IteratorState &iterator ); static void decrement( IteratorState &iterator ); static Value &dereference( const IteratorState &iterator ); static Value &unsafeDereference( const IteratorState &iterator ); static int distance( const IteratorState &x, const IteratorState &y ); static ArrayIndex indexOf( const IteratorState &iterator ); void makeBeginIterator( IteratorState &it ) const; void makeEndIterator( IteratorState &it ) const; void makeIterator( IteratorState &it, ArrayIndex index ) const; void makeIndexValid( ArrayIndex index ); Value **pages_; ArrayIndex size_; PageIndex pageCount_; }; /** \brief Experimental: do not use. Allocator to customize Value internal array. * Below is an example of a simple implementation (actual implementation use * memory pool). \code class DefaultValueArrayAllocator : public ValueArrayAllocator { public: // overridden from ValueArrayAllocator virtual ~DefaultValueArrayAllocator() { } virtual ValueInternalArray *newArray() { return new ValueInternalArray(); } virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) { return new ValueInternalArray( other ); } virtual void destruct( ValueInternalArray *array ) { delete array; } virtual void reallocateArrayPageIndex( Value **&indexes, ValueInternalArray::PageIndex &indexCount, ValueInternalArray::PageIndex minNewIndexCount ) { ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; if ( minNewIndexCount > newIndexCount ) newIndexCount = minNewIndexCount; void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); if ( !newIndexes ) throw std::bad_alloc(); indexCount = newIndexCount; indexes = static_cast( newIndexes ); } virtual void releaseArrayPageIndex( Value **indexes, ValueInternalArray::PageIndex indexCount ) { if ( indexes ) free( indexes ); } virtual Value *allocateArrayPage() { return static_cast( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); } virtual void releaseArrayPage( Value *value ) { if ( value ) free( value ); } }; \endcode */ class JSON_API ValueArrayAllocator { public: virtual ~ValueArrayAllocator(); virtual ValueInternalArray *newArray() = 0; virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; virtual void destructArray( ValueInternalArray *array ) = 0; /** \brief Reallocate array page index. * Reallocates an array of pointer on each page. * \param indexes [input] pointer on the current index. May be \c NULL. * [output] pointer on the new index of at least * \a minNewIndexCount pages. * \param indexCount [input] current number of pages in the index. * [output] number of page the reallocated index can handle. * \b MUST be >= \a minNewIndexCount. * \param minNewIndexCount Minimum number of page the new index must be able to * handle. */ virtual void reallocateArrayPageIndex( Value **&indexes, ValueInternalArray::PageIndex &indexCount, ValueInternalArray::PageIndex minNewIndexCount ) = 0; virtual void releaseArrayPageIndex( Value **indexes, ValueInternalArray::PageIndex indexCount ) = 0; virtual Value *allocateArrayPage() = 0; virtual void releaseArrayPage( Value *value ) = 0; }; #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP /** \brief base class for Value iterators. * */ class ValueIteratorBase { public: typedef unsigned int size_t; typedef int difference_type; typedef ValueIteratorBase SelfType; ValueIteratorBase(); #ifndef JSON_VALUE_USE_INTERNAL_MAP explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); #else ValueIteratorBase( const ValueInternalArray::IteratorState &state ); ValueIteratorBase( const ValueInternalMap::IteratorState &state ); #endif bool operator ==( const SelfType &other ) const { return isEqual( other ); } bool operator !=( const SelfType &other ) const { return !isEqual( other ); } difference_type operator -( const SelfType &other ) const { return computeDistance( other ); } /// Return either the index or the member name of the referenced value as a Value. Value key() const; /// Return the index of the referenced Value. -1 if it is not an arrayValue. UInt index() const; /// Return the member name of the referenced Value. "" if it is not an objectValue. const char *memberName() const; protected: Value &deref() const; void increment(); void decrement(); difference_type computeDistance( const SelfType &other ) const; bool isEqual( const SelfType &other ) const; void copy( const SelfType &other ); private: #ifndef JSON_VALUE_USE_INTERNAL_MAP Value::ObjectValues::iterator current_; // Indicates that iterator is for a null value. bool isNull_; #else union { ValueInternalArray::IteratorState array_; ValueInternalMap::IteratorState map_; } iterator_; bool isArray_; #endif }; /** \brief const iterator for object and array value. * */ class ValueConstIterator : public ValueIteratorBase { friend class Value; public: typedef unsigned int size_t; typedef int difference_type; typedef const Value &reference; typedef const Value *pointer; typedef ValueConstIterator SelfType; ValueConstIterator(); private: /*! \internal Use by Value to create an iterator. */ #ifndef JSON_VALUE_USE_INTERNAL_MAP explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); #else ValueConstIterator( const ValueInternalArray::IteratorState &state ); ValueConstIterator( const ValueInternalMap::IteratorState &state ); #endif public: SelfType &operator =( const ValueIteratorBase &other ); SelfType operator++( int ) { SelfType temp( *this ); ++*this; return temp; } SelfType operator--( int ) { SelfType temp( *this ); --*this; return temp; } SelfType &operator--() { decrement(); return *this; } SelfType &operator++() { increment(); return *this; } reference operator *() const { return deref(); } }; /** \brief Iterator for object and array value. */ class ValueIterator : public ValueIteratorBase { friend class Value; public: typedef unsigned int size_t; typedef int difference_type; typedef Value &reference; typedef Value *pointer; typedef ValueIterator SelfType; ValueIterator(); ValueIterator( const ValueConstIterator &other ); ValueIterator( const ValueIterator &other ); private: /*! \internal Use by Value to create an iterator. */ #ifndef JSON_VALUE_USE_INTERNAL_MAP explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); #else ValueIterator( const ValueInternalArray::IteratorState &state ); ValueIterator( const ValueInternalMap::IteratorState &state ); #endif public: SelfType &operator =( const SelfType &other ); SelfType operator++( int ) { SelfType temp( *this ); ++*this; return temp; } SelfType operator--( int ) { SelfType temp( *this ); --*this; return temp; } SelfType &operator--() { decrement(); return *this; } SelfType &operator++() { increment(); return *this; } reference operator *() const { return deref(); } }; } // namespace Json #endif // CPPTL_JSON_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: include/json/value.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: include/json/reader.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef CPPTL_JSON_READER_H_INCLUDED # define CPPTL_JSON_READER_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) # include "features.h" # include "value.h" #endif // if !defined(JSON_IS_AMALGAMATION) # include # include # include # include namespace Json { /** \brief Unserialize a JSON document into a Value. * */ class JSON_API Reader { public: typedef char Char; typedef const Char *Location; /** \brief Constructs a Reader allowing all features * for parsing. */ Reader(); /** \brief Constructs a Reader allowing the specified feature set * for parsing. */ Reader( const Features &features ); /** \brief Read a Value from a JSON document. * \param document UTF-8 encoded string containing the document to read. * \param root [out] Contains the root value of the document if it was * successfully parsed. * \param collectComments \c true to collect comment and allow writing them back during * serialization, \c false to discard comments. * This parameter is ignored if Features::allowComments_ * is \c false. * \return \c true if the document was successfully parsed, \c false if an error occurred. */ bool parse( const std::string &document, Value &root, bool collectComments = true ); /** \brief Read a Value from a JSON document. * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the document to read. * \param endDoc Pointer on the end of the UTF-8 encoded string of the document to read. \ Must be >= beginDoc. * \param root [out] Contains the root value of the document if it was * successfully parsed. * \param collectComments \c true to collect comment and allow writing them back during * serialization, \c false to discard comments. * This parameter is ignored if Features::allowComments_ * is \c false. * \return \c true if the document was successfully parsed, \c false if an error occurred. */ bool parse( const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true ); /// \brief Parse from input stream. /// \see Json::operator>>(std::istream&, Json::Value&). bool parse( std::istream &is, Value &root, bool collectComments = true ); /** \brief Returns a user friendly string that list errors in the parsed document. * \return Formatted error message with the list of errors with their location in * the parsed document. An empty string is returned if no error occurred * during parsing. * \deprecated Use getFormattedErrorMessages() instead (typo fix). */ JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead") std::string getFormatedErrorMessages() const; /** \brief Returns a user friendly string that list errors in the parsed document. * \return Formatted error message with the list of errors with their location in * the parsed document. An empty string is returned if no error occurred * during parsing. */ std::string getFormattedErrorMessages() const; private: enum TokenType { tokenEndOfStream = 0, tokenObjectBegin, tokenObjectEnd, tokenArrayBegin, tokenArrayEnd, tokenString, tokenNumber, tokenTrue, tokenFalse, tokenNull, tokenArraySeparator, tokenMemberSeparator, tokenComment, tokenError }; class Token { public: TokenType type_; Location start_; Location end_; }; class ErrorInfo { public: Token token_; std::string message_; Location extra_; }; typedef std::deque Errors; bool expectToken( TokenType type, Token &token, const char *message ); bool readToken( Token &token ); void skipSpaces(); bool match( Location pattern, int patternLength ); bool readComment(); bool readCStyleComment(); bool readCppStyleComment(); bool readString(); void readNumber(); bool readValue(); bool readObject( Token &token ); bool readArray( Token &token ); bool decodeNumber( Token &token ); bool decodeString( Token &token ); bool decodeString( Token &token, std::string &decoded ); bool decodeDouble( Token &token ); bool decodeUnicodeCodePoint( Token &token, Location ¤t, Location end, unsigned int &unicode ); bool decodeUnicodeEscapeSequence( Token &token, Location ¤t, Location end, unsigned int &unicode ); bool addError( const std::string &message, Token &token, Location extra = 0 ); bool recoverFromError( TokenType skipUntilToken ); bool addErrorAndRecover( const std::string &message, Token &token, TokenType skipUntilToken ); void skipUntilSpace(); Value ¤tValue(); Char getNextChar(); void getLocationLineAndColumn( Location location, int &line, int &column ) const; std::string getLocationLineAndColumn( Location location ) const; void addComment( Location begin, Location end, CommentPlacement placement ); void skipCommentTokens( Token &token ); typedef std::stack Nodes; Nodes nodes_; Errors errors_; std::string document_; Location begin_; Location end_; Location current_; Location lastValueEnd_; Value *lastValue_; std::string commentsBefore_; Features features_; bool collectComments_; }; /** \brief Read from 'sin' into 'root'. Always keep comments from the input JSON. This can be used to read a file into a particular sub-object. For example: \code Json::Value root; cin >> root["dir"]["file"]; cout << root; \endcode Result: \verbatim { "dir": { "file": { // The input stream JSON would be nested here. } } } \endverbatim \throw std::exception on parse error. \see Json::operator<<() */ std::istream& operator>>( std::istream&, Value& ); } // namespace Json #endif // CPPTL_JSON_READER_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: include/json/reader.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: include/json/writer.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef JSON_WRITER_H_INCLUDED # define JSON_WRITER_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) # include "value.h" #endif // if !defined(JSON_IS_AMALGAMATION) # include # include # include namespace Json { class Value; /** \brief Abstract class for writers. */ class JSON_API Writer { public: virtual ~Writer(); virtual std::string write( const Value &root ) = 0; }; /** \brief Outputs a Value in JSON format without formatting (not human friendly). * * The JSON document is written in a single line. It is not intended for 'human' consumption, * but may be usefull to support feature such as RPC where bandwith is limited. * \sa Reader, Value */ class JSON_API FastWriter : public Writer { public: FastWriter(); virtual ~FastWriter(){} void enableYAMLCompatibility(); public: // overridden from Writer virtual std::string write( const Value &root ); private: void writeValue( const Value &value ); std::string document_; bool yamlCompatiblityEnabled_; }; /** \brief Writes a Value in JSON format in a human friendly way. * * The rules for line break and indent are as follow: * - Object value: * - if empty then print {} without indent and line break * - if not empty the print '{', line break & indent, print one value per line * and then unindent and line break and print '}'. * - Array value: * - if empty then print [] without indent and line break * - if the array contains no object value, empty array or some other value types, * and all the values fit on one lines, then print the array on a single line. * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * * If the Value have comments then they are outputed according to their #CommentPlacement. * * \sa Reader, Value, Value::setComment() */ class JSON_API StyledWriter: public Writer { public: StyledWriter(); virtual ~StyledWriter(){} public: // overridden from Writer /** \brief Serialize a Value in JSON format. * \param root Value to serialize. * \return String containing the JSON document that represents the root value. */ virtual std::string write( const Value &root ); private: void writeValue( const Value &value ); void writeArrayValue( const Value &value ); bool isMultineArray( const Value &value ); void pushValue( const std::string &value ); void writeIndent(); void writeWithIndent( const std::string &value ); void indent(); void unindent(); void writeCommentBeforeValue( const Value &root ); void writeCommentAfterValueOnSameLine( const Value &root ); bool hasCommentForValue( const Value &value ); static std::string normalizeEOL( const std::string &text ); typedef std::vector ChildValues; ChildValues childValues_; std::string document_; std::string indentString_; int rightMargin_; int indentSize_; bool addChildValues_; }; /** \brief Writes a Value in JSON format in a human friendly way, to a stream rather than to a string. * * The rules for line break and indent are as follow: * - Object value: * - if empty then print {} without indent and line break * - if not empty the print '{', line break & indent, print one value per line * and then unindent and line break and print '}'. * - Array value: * - if empty then print [] without indent and line break * - if the array contains no object value, empty array or some other value types, * and all the values fit on one lines, then print the array on a single line. * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * * If the Value have comments then they are outputed according to their #CommentPlacement. * * \param indentation Each level will be indented by this amount extra. * \sa Reader, Value, Value::setComment() */ class JSON_API StyledStreamWriter { public: StyledStreamWriter( std::string indentation="\t" ); ~StyledStreamWriter(){} public: /** \brief Serialize a Value in JSON format. * \param out Stream to write to. (Can be ostringstream, e.g.) * \param root Value to serialize. * \note There is no point in deriving from Writer, since write() should not return a value. */ void write( std::ostream &out, const Value &root ); private: void writeValue( const Value &value ); void writeArrayValue( const Value &value ); bool isMultineArray( const Value &value ); void pushValue( const std::string &value ); void writeIndent(); void writeWithIndent( const std::string &value ); void indent(); void unindent(); void writeCommentBeforeValue( const Value &root ); void writeCommentAfterValueOnSameLine( const Value &root ); bool hasCommentForValue( const Value &value ); static std::string normalizeEOL( const std::string &text ); typedef std::vector ChildValues; ChildValues childValues_; std::ostream* document_; std::string indentString_; int rightMargin_; std::string indentation_; bool addChildValues_; }; # if defined(JSON_HAS_INT64) std::string JSON_API valueToString( Int value ); std::string JSON_API valueToString( UInt value ); # endif // if defined(JSON_HAS_INT64) std::string JSON_API valueToString( LargestInt value ); std::string JSON_API valueToString( LargestUInt value ); std::string JSON_API valueToString( double value ); std::string JSON_API valueToString( bool value ); std::string JSON_API valueToQuotedString( const char *value ); /// \brief Output using the StyledStreamWriter. /// \see Json::operator>>() std::ostream& operator<<( std::ostream&, const Value &root ); } // namespace Json #endif // JSON_WRITER_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: include/json/writer.h // ////////////////////////////////////////////////////////////////////// #endif //ifndef JSON_AMALGATED_H_INCLUDED Jellyfish-2.2.8/include/jellyfish/large_hash_array.hpp000066400000000000000000001167711323712541700231160ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_LARGE_HASH_ARRAY_HPP__ #define __JELLYFISH_LARGE_HASH_ARRAY_HPP__ #include #include #include #include #include #include #include #include #include #include namespace jellyfish { namespace large_hash { /* Contains an integer, the reprobe limit. It is capped based on the * reprobe strategy to not be bigger than the size of the hash * array. Also, the length to encode reprobe limit must not be larger * than the length to encode _size. */ class reprobe_limit_t { uint_t limit; public: reprobe_limit_t(uint_t _limit, const size_t *_reprobes, size_t _size) : limit(_limit) { while(_reprobes[limit] >= _size && limit >= 1) limit--; } inline uint_t val() const { return limit; } }; // Key is any type with the following two methods: get_bits(unsigned // int start, unsigned int len); and set_bits(unsigned int start, // unsigned int len, uint64_t bits). These methods get and set the // bits [start, start + len). Start and len may not be aligned to word // boundaries. On the other hand, len is guaranteed to be < // sizeof(uint64_t). I.e. never more than 1 word is fetched or set. template class array_base { static const int wsize = std::numeric_limits::digits; // Word size in bits // Can't be done. Resort to an evil macro! // static const word fmask = std::numeric_limits::max(); // Mask full of ones #define fmask (std::numeric_limits::max()) public: define_error_class(ErrorAllocation); typedef word data_word; typedef typename Offsets::offset_t offset_t; typedef struct offset_t::key key_offsets; typedef struct offset_t::val val_offsets; typedef Key key_type; typedef uint64_t mapped_type; typedef std::pair value_type; typedef stl_iterator_base iterator; typedef stl_iterator_base const_iterator; typedef value_type& reference; typedef const value_type& const_reference; typedef value_type* pointer; typedef const value_type* const_pointer; typedef eager_iterator_base eager_iterator; typedef lazy_iterator_base lazy_iterator; typedef region_iterator_base region_iterator; /// Status of a (key,value) pair. LBSET means that the large bit is /// set. Hence, it contains a pointer back to the original key and a /// large value. enum key_status { FILLED, EMPTY, LBSET}; protected: uint16_t lsize_; // log of size size_t size_, size_mask_; reprobe_limit_t reprobe_limit_; uint16_t key_len_; // Length of key in bits uint16_t raw_key_len_; // Length of key stored raw (i.e. complement of implied length) Offsets offsets_; // key len reduced by size of hash array size_t size_bytes_; word * const data_; atomic_t atomic_; const size_t *reprobes_; RectangularBinaryMatrix hash_matrix_; RectangularBinaryMatrix hash_inverse_matrix_; public: /// Give information about memory usage and array size. struct usage_info { uint16_t key_len_, val_len_, reprobe_limit_; const size_t* reprobes_; usage_info(uint16_t key_len, uint16_t val_len, uint16_t reprobe_limit, const size_t* reprobes = jellyfish::quadratic_reprobes) : key_len_(key_len), val_len_(val_len), reprobe_limit_(reprobe_limit), reprobes_(reprobes) { } /// Memory usage for a given size. size_t mem(size_t size) { uint16_t lsize(ceilLog2(size)); size_t asize((size_t)1 << lsize); reprobe_limit_t areprobe_limit(reprobe_limit_, reprobes_, asize); uint16_t raw_key_len(key_len_ > lsize ? key_len_ - lsize : 0); Offsets offsets(raw_key_len + bitsize(areprobe_limit.val() + 1), val_len_, areprobe_limit.val() + 1); return div_ceil(asize, (size_t)offsets.block_len()) * offsets.block_word_len() * sizeof(word) + sizeof(array_base) + sizeof(Offsets); } /// Actual size for a given size. size_t asize(size_t size) { return (size_t)1 << ceilLog2(size); } struct fit_in { usage_info* i_; size_t mem_; fit_in(usage_info* i, size_t mem) : i_(i), mem_(mem) { } bool operator()(uint16_t size_bits) const { return i_->mem((size_t)1 << size_bits) < mem_; } }; /// Maximum size for a given maximum memory. size_t size(size_t mem) { return (size_t)1 << size_bits(mem); } /// Log of maximum size for a given maximum memory uint16_t size_bits(size_t mem) { uint16_t res = *binary_search_first_false(pointer_integer(0), pointer_integer(64), fit_in(this, mem)); return res > 0 ? res - 1 : 0; } size_t size_bits_linear(size_t mem) { fit_in predicate(this, mem); uint16_t i = 0; for( ; i < 64; ++i) if(!predicate(i)) break; return i > 0 ? i - 1 : 0; } }; array_base(size_t size, // Size of hash. To be rounded up to a power of 2 uint16_t key_len, // Size of key in bits uint16_t val_len, // Size of val in bits uint16_t reprobe_limit, // Maximum reprobe RectangularBinaryMatrix m, const size_t* reprobes = quadratic_reprobes) : // Reprobing policy lsize_(ceilLog2(size)), size_((size_t)1 << lsize_), size_mask_(size_ - 1), reprobe_limit_(reprobe_limit, reprobes, size_), key_len_(key_len), raw_key_len_(key_len_ > lsize_ ? key_len_ - lsize_ : 0), offsets_(raw_key_len_ + bitsize(reprobe_limit_.val() + 1), val_len, reprobe_limit_.val() + 1), size_bytes_(div_ceil(size_, (size_t)offsets_.block_len()) * offsets_.block_word_len() * sizeof(word)), data_(static_cast(this)->alloc_data(size_bytes_)), reprobes_(reprobes), hash_matrix_(m), hash_inverse_matrix_(hash_matrix_.pseudo_inverse()) { if(!data_) throw ErrorAllocation(err::msg() << "Failed to allocate " << (div_ceil(size, (size_t)offsets_.block_len()) * offsets_.block_word_len() * sizeof(word)) << " bytes of memory"); } array_base(array_base&& ary) : lsize_(ary.lsize_), size_(ary.size_), size_mask_(size_ - 1), reprobe_limit_(ary.reprobe_limit_), key_len_(ary.key_len_), raw_key_len_(ary.raw_key_len_), offsets_(std::move(ary.offsets_)), size_bytes_(ary.size_bytes_), data_(ary.data_), reprobes_(ary.reprobes_), hash_matrix_(std::move(ary.hash_matrix_)), hash_inverse_matrix_(std::move(ary.hash_inverse_matrix_)) { } array_base& operator=(const array_base& rhs) = delete; array_base& operator=(array_base&& rhs) = delete; size_t size() const { return size_; } size_t lsize() const { return lsize_; } size_t size_mask() const { return size_mask_; } uint_t key_len() const { return key_len_; } uint_t val_len() const { return offsets_.val_len(); } const size_t* reprobes() const { return reprobes_; } uint_t max_reprobe() const { return reprobe_limit_.val(); } size_t max_reprobe_offset() const { return reprobes_[reprobe_limit_.val()]; } const RectangularBinaryMatrix& matrix() const { return hash_matrix_; } const RectangularBinaryMatrix& inverse_matrix() const { return hash_inverse_matrix_; } void matrix(const RectangularBinaryMatrix& m) { hash_inverse_matrix_ = m.pseudo_inverse(); hash_matrix_ = m; } /** * Clear hash table. Not thread safe. */ void clear() { memset(data_, '\0', size_bytes_); } /** * Write the hash table raw to a stream. Not thread safe. */ void write(std::ostream& os) const { os.write((const char*)data_, size_bytes_); } size_t size_bytes() const { return size_bytes_; } /* The storage of the hash is organized in "blocks". A (key,value) * pair always start at bit 0 of the block. The following methods * work with the blocks of the hash. */ /** * Number of blocks needed to fit at least a given number of * records. Given a number of records, it returns the number of * blocks necessary and the actual number of records these blocks * contain. */ std::pair blocks_for_records(size_t nb_records) const { return offsets_.blocks_for_records(nb_records); } /** * Convert coordinate from (start, blen) given in blocks to * coordinate in char* and length in bytes. It also makes sure that * the pointer and length returned do not go beyond allocated * memory. */ void block_to_ptr(const size_t start, const size_t blen, char **start_ptr, size_t *memlen) const { *start_ptr = (char *)(data_ + start * offsets_.block_word_len()); char *end_ptr = (char *)data_ + size_bytes_; if(*start_ptr >= end_ptr) { *memlen = 0; return; } *memlen = blen * offsets_.block_word_len() * sizeof(word); if(*start_ptr + *memlen > end_ptr) *memlen = end_ptr - *start_ptr; } /** * Zero out blocks in [start, start+length), where start and * length are given in number of blocks. **/ void zero_blocks(const size_t start, const size_t length) { char *start_ptr; size_t memlen; block_to_ptr(start, length, &start_ptr, &memlen); memset(start_ptr, '\0', memlen); } /** * Use hash values as counters. * * The matrix multiplication gets only a uint64_t. The lsb of the * matrix product, the hsb are assume to be equal to the key itself * (the matrix has a partial identity on the first rows). * * In case of failure (false is returned), carry_shift contains the * number of bits of the value that were successfully stored in the * hash (low significant bits). If carry_shift == 0, then nothing * was stored and the key is not in the hash at all. In that case, * the value of *is_new and *id are not valid. If carry_shift > 0, * then the key is present but the value stored is not correct * (missing the high significant bits of value), but *is_new and *id * contain the proper information. */ inline bool add(const key_type& key, mapped_type val, unsigned int* carry_shift, bool* is_new, size_t* id) { uint64_t hash = hash_matrix_.times(key); *carry_shift = 0; return add_rec(hash & size_mask_, key, val, false, is_new, id, carry_shift); } inline bool add(const key_type& key, mapped_type val, unsigned int* carry_shift) { bool is_new = false; size_t id = 0; return add(key, val, carry_shift, &is_new, &id); } inline bool add(const key_type& key, mapped_type val) { unsigned int carry_shift = 0; return add(key, val, &carry_shift); } inline bool set(const key_type& key) { bool is_new; size_t id; return set(key, &is_new, &id); } bool set(const key_type& key, bool* is_new, size_t* id) { word* w; const offset_t* o; *id = hash_matrix_.times(key) & size_mask_; return claim_key(key, is_new, id, &o, &w); } /** * Use hash values as counters, if already exists * * Add val to the value associated with key if key is already in the * hash. Returns true if the update was done, false otherwise. */ inline bool update_add(const key_type& key, mapped_type val) { key_type tmp_key; unsigned int carry_shift; return update_add(key, val, &carry_shift, tmp_key); } // Optimization. Use tmp_key as buffer. Avoids allocation if update_add is called repeatedly. bool update_add(const key_type& key, mapped_type val, unsigned int* carry_shift, key_type& tmp_key) { size_t id; word* w; const offset_t* o; *carry_shift = 0; if(get_key_id(key, &id, tmp_key, (const word**)&w, &o)) return add_rec_at(id, key, val, o, w, carry_shift); return false; } // Get the value, stored in *val, associated with key. If the key is // not found, false is returned, otherwise true is returned and *val // is updated. If carry_bit is true, then the first bit of the key // field indicates whether we should reprobe to get the complete // value. inline bool get_val_for_key(const key_type& key, mapped_type* val, bool carry_bit = false) const { key_type tmp_key; size_t id; return get_val_for_key(key, val, tmp_key, &id, carry_bit); } // Optimization version. A tmp_key buffer is passed and the id where // the key was found is return in *id. If get_val_for_key is called // many times consecutively, it may be faster to pass the same // tmp_key buffer instead of allocating it every time. bool get_val_for_key(const key_type& key, mapped_type* val, key_type& tmp_key, size_t* id, bool carry_bit = false) const { const word* w; const offset_t* o; if(!get_key_id(key, id, tmp_key, &w, &o)) return false; *val = get_val_at_id(*id, w, o, true, carry_bit); return true; } // Return true if the key is present in the hash inline bool has_key(const key_type& key) const { size_t id; return get_key_id(key, &id); } // Get the id of the key in the hash. Returns true if the key is // found in the hash, false otherwise. inline bool get_key_id(const key_type& key, size_t* id) const { key_type tmp_key; const word* w; const offset_t* o; return get_key_id(key, id, tmp_key, &w, &o); } // Optimization version where a tmp_key buffer is provided instead // of being allocated. May be faster if many calls to get_key_id are // made consecutively by passing the same tmp_key each time. inline bool get_key_id(const key_type& key, size_t* id, key_type& tmp_key) const { const word* w; const offset_t* o; return get_key_id(key, id, tmp_key, &w, &o); } protected: // Information and methods to manage the prefetched data. struct prefetch_info { size_t id; const word* w; const offset_t *o, *lo; }; typedef simple_circular_buffer::pre_alloc prefetch_buffer; void warm_up_cache(prefetch_buffer& buffer, size_t oid) const { buffer.clear(); for(int i = 0; i < buffer.capacity(); ++i) { buffer.push_back(); prefetch_info& info = buffer.back(); info.id = (oid + (i > 0 ? reprobes_[i] : 0)) & size_mask_; info.w = offsets_.word_offset(info.id, &info.o, &info.lo, data_); __builtin_prefetch(info.w + info.o->key.woff, 0, 1); __builtin_prefetch(info.o, 0, 3); } } void prefetch_next(prefetch_buffer& buffer, size_t oid, uint_t reprobe) const { buffer.pop_front(); // if(reprobe + buffer.capacity() <= reprobe_limit_.val()) { buffer.push_back(); prefetch_info& info = buffer.back(); info.id = (oid + reprobes_[reprobe + buffer.capacity() - 1]) & size_mask_; info.w = offsets_.word_offset(info.id, &info.o, &info.lo, data_); __builtin_prefetch(info.w + info.o->key.woff, 0, 1); __builtin_prefetch(info.o, 0, 3); // } } public: // Optimization version again. Also return the word and the offset // information where the key was found. These can be used later one // to fetch the value associated with the key. inline bool get_key_id(const key_type& key, size_t* id, key_type& tmp_key, const word** w, const offset_t** o) const { return get_key_id(key, id, tmp_key, w, o, hash_matrix_.times(key) & size_mask_); } // Find the actual id of the key in the hash, starting at oid. bool get_key_id(const key_type& key, size_t* id, key_type& tmp_key, const word** w, const offset_t** o, const size_t oid) const { // This static_assert makes clang++ happy static_assert(std::is_pod::value, "prefetch_info must be a POD"); prefetch_info info_ary[prefetch_buffer::capacityConstant]; prefetch_buffer buffer(info_ary); warm_up_cache(buffer, oid); for(uint_t reprobe = 0; reprobe <= reprobe_limit_.val(); ++reprobe) { prefetch_info& info = buffer.front(); key_status st = get_key_at_id(info.id, tmp_key, info.w, info.o); switch(st) { case EMPTY: return false; case FILLED: if(oid != tmp_key.get_bits(0, lsize_)) break; tmp_key.template set_bits(0, lsize_, key.get_bits(0, lsize_)); if(tmp_key != key) break; *id = info.id; *w = info.w; *o = info.o; return true; default: break; } prefetch_next(buffer, oid, reprobe + 1); } // for return false; } ////////////////////////////// // Iterator ////////////////////////////// const_iterator begin() { return const_iterator(this); } const_iterator begin() const { return const_iterator(this); } const_iterator end() { return const_iterator(); } const_iterator end() const { return const_iterator(); } /// Get a slice of an array as an iterator template Iterator iterator_slice(size_t index, size_t nb_slices) const { std::pair res = slice(index, nb_slices, size()); return Iterator(this, res.first, res.second); } template Iterator iterator_all() const { return iterator_slice(0, 1); } // See hash_counter.hpp for why we added this method. It should not // be needed, but I can't get the thing to compile without :(. eager_iterator eager_slice(size_t index, size_t nb_slices) const { return iterator_slice(index, nb_slices); } region_iterator region_slice(size_t index, size_t nb_slices) const { return iterator_slice(index, nb_slices); } // Claim a key with the large bit not set. I.e. first entry for a key. // // id is input/output. Equal to hash & size_maks on input. Equal to // actual id where key was set on output. key is already hash // shifted and masked to get higher bits. (>> lsize & key_mask) // is_new is set on output to true if key did not exists in hash // before. *ao points to the actual offsets object and w to the word // holding the value. bool claim_key(const key_type& key, bool* is_new, size_t* id, const offset_t** _ao, word** _w) { uint_t reprobe = 0; const offset_t *o, *lo; word *w, *kw, nkey; bool key_claimed = false; size_t cid = *id; // Akey contains first word of what to store in the key // field. I.e. part of the original key (the rest is encoded in // the original position) and the reprobe value to substract from // the actual position to get to the original position. // // MSB LSB // +--------------+-------------+ // | MSB of key | reprobe | // + -------------+-------------+ // raw_key_len reprobe_len // // Akey is updated at every operation to reflect the current // reprobe value. nkey is the temporary word containing the part // to be stored in the current word kw (+ some offset). word akey = 1; // start reprobe value == 0. Store reprobe value + 1 const int to_copy = std::min((uint16_t)(wsize - offsets_.reprobe_len()), raw_key_len_); const int implied_copy = std::min(key_len_, lsize_); akey |= key.get_bits(implied_copy, to_copy) << offsets_.reprobe_len(); const int abits_copied = implied_copy + to_copy; // Bits from original key already copied, explicitly or implicitly do { int bits_copied = abits_copied; w = offsets_.word_offset(cid, &o, &lo, data_); kw = w + o->key.woff; if(o->key.sb_mask1) { // key split on multiple words nkey = akey << o->key.boff; nkey |= o->key.sb_mask1; nkey &= o->key.mask1; key_claimed = set_key(kw, nkey, o->key.mask1, o->key.mask1, is_new); if(key_claimed) { nkey = akey >> o->key.shift; if(o->key.full_words) { // Copy full words. First one is special nkey |= key.get_bits(bits_copied, o->key.shift - 1) << (wsize - o->key.shift); bits_copied += o->key.shift - 1; nkey |= o->key.sb_mask1; // Set bit is MSB int copied_full_words = 1; key_claimed = set_key(kw + copied_full_words, nkey, fmask, fmask, is_new); // Copy more full words if needed while(bits_copied + wsize - 1 <= key_len_ && key_claimed) { nkey = key.get_bits(bits_copied, wsize - 1); bits_copied += wsize - 1; nkey |= o->key.sb_mask1; copied_full_words += 1; key_claimed = set_key(kw + copied_full_words, nkey, fmask, fmask, is_new); } assert(!key_claimed || (bits_copied < key_len_) == (o->key.sb_mask2 != 0)); if(o->key.sb_mask2 && key_claimed) { // Copy last word nkey = key.get_bits(bits_copied, key_len_ - bits_copied); nkey |= o->key.sb_mask2; copied_full_words += 1; key_claimed = set_key(kw + copied_full_words, nkey, o->key.mask2, o->key.mask2, is_new); } } else if(o->key.sb_mask2) { // if bits_copied + wsize - 1 < key_len // Copy last word, no full words copied nkey |= key.get_bits(bits_copied, key_len_ - bits_copied) << (wsize - o->key.shift); nkey |= o->key.sb_mask2; nkey &= o->key.mask2; key_claimed = set_key(kw + 1, nkey, o->key.mask2, o->key.mask2, is_new); } } // if(key_claimed) } else { // key on one word nkey = akey << o->key.boff; nkey &= o->key.mask1; key_claimed = set_key(kw, nkey, o->key.mask1, o->key.mask1, is_new); } if(!key_claimed) { // reprobe if(++reprobe > reprobe_limit_.val()) return false; cid = (*id + reprobes_[reprobe]) & size_mask_; akey = (akey & ~offsets_.reprobe_mask()) | (reprobe + 1); } } while(!key_claimed); *id = cid; *_w = w; *_ao = o; return true; } // Claim large key. Enter an entry for a key when it is not the // first entry. Only encode the number of reprobe hops back to the // first entry of the key in the hash table. It is simpler as can // takes less than one word in length. bool claim_large_key(size_t* id, const offset_t** _ao, word** _w) { uint_t reprobe = 0; size_t cid = *id; const offset_t *o, *lo; word *w, *kw, nkey; bool key_claimed = false; do { w = offsets_.word_offset(cid, &o, &lo, data_); kw = w + lo->key.woff; if(lo->key.sb_mask1) { // key split on multiple words nkey = (reprobe << lo->key.boff) | lo->key.sb_mask1 | lo->key.lb_mask; nkey &= lo->key.mask1; // Use o->key.mask1 and not lo->key.mask1 as the first one is // guaranteed to be bigger. The key needs to be free on its // longer mask to claim it! key_claimed = set_key(kw, nkey, o->key.mask1, lo->key.mask1); if(key_claimed) { nkey = (reprobe >> lo->key.shift) | lo->key.sb_mask2; nkey &= lo->key.mask2; key_claimed = set_key(kw + 1, nkey, o->key.full_words ? fmask : o->key.mask2, lo->key.mask2); } } else { // key on 1 word nkey = (reprobe << lo->key.boff) | lo->key.lb_mask; nkey &= lo->key.mask1; key_claimed = set_key(kw, nkey, o->key.mask1, lo->key.mask1); } if(!key_claimed) { //reprobe if(++reprobe > reprobe_limit_.val()) return false; cid = (*id + reprobes_[reprobe]) & size_mask_; } } while(!key_claimed); *id = cid; *_w = w; *_ao = lo; return true; } // Add val to key. id is the starting place (result of hash // computation). eid is set to the effective place in the // array. large is set to true is setting a large key (upon // recurrence if there is a carry). bool add_rec(size_t id, const key_type& key, word val, bool large, bool* is_new, size_t* eid, unsigned int* carry_shift) { const offset_t *ao = 0; word *w = 0; bool claimed = false; if(large) claimed = claim_large_key(&id, &ao, &w); else claimed = claim_key(key, is_new, &id, &ao, &w); if(!claimed) return false; *eid = id; return add_rec_at(id, key, val, ao, w, carry_shift); } bool add_rec_at(size_t id, const key_type& key, word val, const offset_t* ao, word* w, unsigned int* carry_shift) { // Increment value word *vw = w + ao->val.woff; word cary = add_val(vw, val, ao->val.boff, ao->val.mask1); cary >>= ao->val.shift; *carry_shift += ao->val.shift; if(cary && ao->val.mask2) { // value split on two words cary = add_val(vw + 1, cary, 0, ao->val.mask2); cary >>= ao->val.cshift; *carry_shift += ao->val.cshift; } if(!cary) return true; id = (id + reprobes_[0]) & size_mask_; size_t ignore_eid; bool ignore_is_new; return add_rec(id, key, cary, true, &ignore_is_new, &ignore_eid, carry_shift); // // Adding failed, table is full. Need to back-track and // // substract val. // std::cerr << "Failed to add large part of value -> return false\n"; // cary = add_val(vw, ((word)1 << offsets_.val_len()) - val, // ao->val.boff, ao->val.mask1); // cary >>= ao->val.shift; // if(cary && ao->val.mask2) { // // Can I ignore the cary here? Table is known to be full, so // // not much of a choice. But does it leave the table in a // // consistent state? // add_val(vw + 1, cary, 0, ao->val.mask2); // } // return false; } // Atomic methods to set the key. Attempt to set nkey in word w. All // bits matching free_mask must be unset and the bits matching // equal_mask must be equal for a success in setting the key. Set // is_new to true if the spot was previously empty. Otherwise, if // is_new is false but true is returned, the key was already present // at that spot. inline bool set_key(word *w, word nkey, word free_mask, word equal_mask, bool *is_new) { word ow = *w, nw, okey; okey = ow & free_mask; while(okey == 0) { // large bit not set && key is free nw = atomic_.cas(w, ow, ow | nkey); if(nw == ow) { *is_new = true; return true; } ow = nw; okey = ow & free_mask; } *is_new = false; return (ow & equal_mask) == nkey; } inline bool set_key(word *w, word nkey, word free_mask, word equal_mask) { bool is_new; return set_key(w, nkey, free_mask, equal_mask, &is_new); } // Add val the value in word w, with shift and mask giving the // particular part of the word in which the value is stored. The // return value is the carry. inline word add_val(word *w, word val, uint_t shift, word mask) { word now = *w, ow, nw, nval; do { ow = now; nval = ((ow & mask) >> shift) + val; nw = (ow & ~mask) | ((nval << shift) & mask); now = atomic_.cas(w, ow, nw); } while(now != ow); return nval & (~(mask >> shift)); } // Return the key and value at position id. If the slot at id is // empty or has the large bit set, returns false. Otherwise, returns // the key and the value is the sum of all the entries in the hash // table for that key. I.e., the table is search forward for entries // with large bit set pointing back to the key at id, and all those // values are summed up. key_status get_key_val_at_id(size_t id, key_type& key, word& val, const bool carry_bit = false) const { const word* w; const offset_t* o; key_status st = get_key_at_id(id, key, &w, &o); if(st != FILLED) return st; val = get_val_at_id(id, w, o, true, carry_bit); return FILLED; } // Get a the key at the given id. It also returns the word and // offset information in w and o. The return value is EMPTY (no key // at id), FILLED (there is a key at id), LBSET (the large bit is // set, hence the key is only a pointer back to the real key). // // The key returned contains the original id in the hash as its // lsize_ lsb bits. To obtain the full key, one needs to compute the // product with the inverse matrix to get the lsb bits. inline key_status get_key_at_id(size_t id, key_type& key, const word** w, const offset_t** o) const { const offset_t *lo; *w = offsets_.word_offset(id, o, &lo, data_); return get_key_at_id(id, key, *w, *o); } // Sam as above, but it assume that the word w and o for id have // already be computed (like already prefetched). key_status get_key_at_id(size_t id, key_type&key, const word* w, const offset_t* o) const { const word* kvw = w + o->key.woff; word key_word = *kvw; word kreprobe = 0; const key_offsets& key_o = o->key; if(key_word & key_o.lb_mask) return LBSET; const int implied_copy = std::min(lsize_, key_len_); int bits_copied = implied_copy; if(key_o.sb_mask1) { if((key_word & key_o.sb_mask1) == 0) return EMPTY; kreprobe = (key_word & key_o.mask1 & ~key_o.sb_mask1) >> key_o.boff; if(key_o.full_words) { // Copy full words. First one is special key_word = *(kvw + 1); if(offsets_.reprobe_len() < key_o.shift) { key.set_bits(bits_copied, key_o.shift - offsets_.reprobe_len(), kreprobe >> offsets_.reprobe_len()); bits_copied += key_o.shift - offsets_.reprobe_len(); kreprobe &= offsets_.reprobe_mask(); key.set_bits(bits_copied, wsize - 1, key_word & ~key_o.sb_mask1); bits_copied += wsize - 1; } else { int reprobe_left = offsets_.reprobe_len() - key_o.shift; kreprobe |= (key_word & (((word)1 << reprobe_left) - 1)) << key_o.shift; key.set_bits(bits_copied, wsize - 1 - reprobe_left, (key_word & ~key_o.sb_mask1) >> reprobe_left); bits_copied += wsize - 1 - reprobe_left; } int word_copied = 2; while(bits_copied + wsize - 1 <= key_len_) { key.set_bits(bits_copied, wsize - 1, *(kvw + word_copied++) & (fmask >> 1)); bits_copied += wsize - 1; } if(key_o.sb_mask2) key.set_bits(bits_copied, key_len_ - bits_copied, *(kvw + word_copied) & key_o.mask2 & ~key_o.sb_mask2); } else if(key_o.sb_mask2) { // if(bits_copied + wsize - 1 < key_len // Two words but no full words key_word = *(kvw + 1) & key_o.mask2 & ~key_o.sb_mask2; if(offsets_.reprobe_len() < key_o.shift) { key.set_bits(bits_copied, key_o.shift - offsets_.reprobe_len(), kreprobe >> offsets_.reprobe_len()); bits_copied += key_o.shift - offsets_.reprobe_len(); kreprobe &= offsets_.reprobe_mask(); key.set_bits(bits_copied, key_len_ - bits_copied, key_word); } else { int reprobe_left = offsets_.reprobe_len() - key_o.shift; kreprobe |= (key_word & (((word)1 << reprobe_left) - 1)) << key_o.shift; key.set_bits(bits_copied, key_len_ - bits_copied, key_word >> reprobe_left); } } } else { // if(key_o.sb_mask1 // Everything in 1 word key_word = (key_word & key_o.mask1) >> key_o.boff; if(key_word == 0) return EMPTY; kreprobe = key_word & offsets_.reprobe_mask(); key.set_bits(bits_copied, raw_key_len_, key_word >> offsets_.reprobe_len()); } // Compute missing oid so that the original key can be computed // back through the inverse matrix. Although the key may have a // length of key_len_, which may be less than lsize_, assume that // it still fit here as lsize_ is less than a word length. Need all lsize_. size_t oid = id; // Original id if(kreprobe > 1) oid -= reprobes_[kreprobe - 1]; oid &= size_mask_; // Can use more bits than mer size. That's OK, will fix it later // when computing the actual mers by computing the product with // the inverse matrix. key.template set_bits<0>(0, lsize_, oid); return FILLED; } word get_val_at_id(const size_t id, const word* w, const offset_t* o, const bool reprobe = true, const bool carry_bit = false) const { word val = 0; if(val_len() == 0) return val; // First part of value const word* kvw = w + o->val.woff; val = ((*kvw) & o->val.mask1) >> o->val.boff; if(o->val.mask2) val |= ((*(kvw+1)) & o->val.mask2) << o->val.shift; // Do we want to get the large value bool do_reprobe = reprobe; if(carry_bit && do_reprobe) { do_reprobe = do_reprobe && (val & 0x1); val >>= 1; } if(!do_reprobe) return val; return resolve_val_rec((id + reprobes_[0]) & size_mask_, val, carry_bit); } word resolve_val_rec(const size_t id, word val, const bool carry_bit, const uint_t overflows = 0) const { uint_t reprobe = 0; size_t cid = id; while(reprobe <= reprobe_limit_.val()) { const offset_t *o, *lo; const word* w = offsets_.word_offset(cid, &o, &lo, data_); const word* kw = w + o->key.woff; word nkey = *kw; const key_offsets& lkey = lo->key; if(nkey & lkey.lb_mask) { // If the large bit is set, the size of the key (reprobe_len) // is guaranteed to have a length of at most 1 word. if(lkey.sb_mask1) { nkey = (nkey & lkey.mask1 & ~lkey.sb_mask1) >> lkey.boff; nkey |= ((*(kw+1)) & lkey.mask2 & ~lkey.sb_mask2) << lkey.shift; } else { nkey = (nkey & lkey.mask1) >> lkey.boff; } if(nkey == reprobe) { const val_offsets& lval = lo->val; const word* vw = w + lval.woff; word nval = ((*vw) & lval.mask1) >> lval.boff; if(lval.mask2) nval |= ((*(vw+1)) & lval.mask2) << lval.shift; bool do_reprobe = true; if(carry_bit) { do_reprobe = nval & 0x1; nval >>= 1; } nval <<= offsets_.val_len(); nval <<= offsets_.lval_len() * overflows; val += nval; if(!do_reprobe) return val; return resolve_val_rec((cid + reprobes_[0]) & size_mask_, val, carry_bit, overflows + 1); } } else if((nkey & o->key.mask1) == 0) { break; } cid = (id + reprobes_[++reprobe]) & size_mask_; } return val; } }; // Large array. Memory managed by the mmap allocator. Do not check the // relation between the size of the array and key_len. template class unbounded_array : protected mem_block_t, public array_base > { typedef array_base > super; friend class array_base >; public: unbounded_array(size_t size, // Size of hash. To be rounded up to a power of 2 uint16_t key_len, // Size of key in bits uint16_t val_len, // Size of val in bits uint16_t reprobe_limit, // Maximum reprobe const size_t* reprobes = quadratic_reprobes) // Reprobing policy : super(size, key_len, val_len, reprobe_limit, RectangularBinaryMatrix(ceilLog2(size), key_len).randomize_pseudo_inverse(), reprobes) { } unbounded_array(size_t size, // Size of hash. To be rounded up to a power of 2 uint16_t key_len, // Size of key in bits uint16_t val_len, // Size of val in bits uint16_t reprobe_limit, // Maximum reprobe RectangularBinaryMatrix&& m, // Hashing matrix const size_t* reprobes = quadratic_reprobes) // Reprobing policy : super(size, key_len, val_len, reprobe_limit, m, reprobes) { } protected: word* alloc_data(size_t s) { mem_block_t::realloc(s); return (word*)mem_block_t::get_ptr(); } }; // Large array. Memory managed by the mmap allocator, bound the size // of the array if the key_len is small. template class array : public unbounded_array { typedef unbounded_array super; static size_t key_len_size(uint16_t key_len) { return key_len >= std::numeric_limits::digits ? std::numeric_limits::max() / 2 : (size_t)1 << key_len; } public: array(size_t size, // Size of hash. To be rounded up to a power of 2 uint16_t key_len, // Size of key in bits uint16_t val_len, // Size of val in bits uint16_t reprobe_limit, // Maximum reprobe const size_t* reprobes = quadratic_reprobes) : // Reprobing policy super(std::min(size, key_len_size(key_len)), key_len, val_len, reprobe_limit, (size < key_len_size(key_len)) ? RectangularBinaryMatrix(ceilLog2(size), key_len).randomize_pseudo_inverse() : RectangularBinaryMatrix::identity(key_len), reprobes) { // std::cerr << this->size() << ' ' << this->val_len() << '\n'; } }; struct ptr_info { void* ptr_; size_t bytes_; ptr_info(void* ptr, size_t bytes) : ptr_(ptr), bytes_(bytes) { } }; template class array_raw : protected ptr_info, public array_base > { typedef array_base > super; friend class array_base >; public: array_raw(void* ptr, size_t bytes, // Memory available at ptr size_t size, // Size of hash in number of entries. To be rounded up to a power of 2 uint16_t key_len, // Size of key in bits uint16_t val_len, // Size of val in bits uint16_t reprobe_limit, // Maximum reprobe RectangularBinaryMatrix m, const size_t* reprobes = quadratic_reprobes) : // Reprobing policy ptr_info(ptr, bytes), super(size, key_len, val_len, reprobe_limit, m, reprobes) { } protected: word* alloc_data(size_t s) { assert(bytes_ == s); return (word*)ptr_; } }; } } // namespace jellyfish { namespace large_hash_array #endif /* __JELLYFISH_LARGE_HASH_ARRAY_HPP__ */ Jellyfish-2.2.8/include/jellyfish/large_hash_iterator.hpp000066400000000000000000000175271323712541700236300ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __LARGE_HASH_ITERATOR_HPP__ #define __LARGE_HASH_ITERATOR_HPP__ #include #include /// Various iterators for the large hash array namespace jellyfish { namespace large_hash { /// Eager iterator. It computes the actual key and value when doing next. template class eager_iterator_base { public: typedef typename array::key_type key_type; typedef typename array::mapped_type mapped_type; typedef typename array::key_status key_status; protected: const array* ary_; size_t start_id_, id_, end_id_; key_type key_; mapped_type val_; public: eager_iterator_base(const array* ary, size_t start, size_t end) : ary_(ary), start_id_(start > ary->size() ? ary->size() : start), id_(start), end_id_(end > ary->size() ? ary->size() : end) {} uint64_t start() const { return start_id_; } uint64_t end() const { return end_id_; } const key_type& key() const { return key_; } const mapped_type& val() const { return val_; } size_t id() const { return id_ - 1; } size_t pos() const { return key_.get_bits(0, ary_->lsize()); } bool next() { key_status success = array::EMPTY; while(success != array::FILLED && id_ < end_id_) success = ary_->get_key_val_at_id(id_++, key_, val_); if(success == array::FILLED) key_.set_bits(0, ary_->lsize(), ary_->inverse_matrix().times(key_)); return success == array::FILLED; } }; /// Lazy iterator. The actual key and value are actually computed only /// when the key() and val() methods are called. template class lazy_iterator_base { public: typedef typename array::key_type key_type; typedef typename array::mapped_type mapped_type; typedef typename array::key_status key_status; typedef typename array::data_word word; typedef typename array::offset_t offset_t; protected: const array* ary_; size_t start_id_, id_, end_id_; const word* w_; const offset_t* o_; bool reversed_key_; key_type key_; public: lazy_iterator_base(const array *ary, size_t start, size_t end) : ary_(ary), start_id_(ary ? (start > ary->size() ? ary->size() : start) : 0), id_(start), end_id_(ary ? (end > ary->size() ? ary->size() : end) : 0), w_(0), o_(0), reversed_key_(false) {} uint64_t start() const { return start_id_; } uint64_t end() const { return end_id_; } const key_type& key() { if(!reversed_key_) { key_.set_bits(0, ary_->lsize(), ary_->inverse_matrix().times(key_)); reversed_key_ = true; } return key_; } mapped_type val() const { return ary_->get_val_at_id(id_ - 1, w_, o_, true, false); } size_t id() const { return id_ - 1; } size_t pos() const { return key_.get_bits(0, ary_->lsize()); } bool next() { reversed_key_ = false; key_status success = array::EMPTY; while(success != array::FILLED && id_ < end_id_) success = ary_->get_key_at_id(id_++, key_, &w_, &o_); return success == array::FILLED; } }; /// Region iterator. Iterate over elements whose original position /// (and not position after reprobing) falls inside the region /// [start_id, end_id) template class region_iterator_base { public: typedef typename array::key_type key_type; typedef typename array::mapped_type mapped_type; typedef typename array::key_status key_status; typedef typename array::data_word word; typedef typename array::offset_t offset_t; protected: const array* ary_; const uint64_t mask_; const size_t start_id_, end_id_, mid_; size_t oid_, id_; const word* w_; const offset_t* o_; bool reversed_key_; key_type* key_; bool own_key; public: region_iterator_base(const array *ary, size_t start, size_t end) : ary_(ary), mask_(ary ? ary->size() - 1 : 0), start_id_(ary ? std::min(start, ary->size()) : 0), end_id_(ary ? std::min(end, ary->size()) : 0), mid_(ary ? std::min(end_id_ - start_id_ + ary->max_reprobe_offset(), ary->size()) : 0), oid_(end_id_), id_(0), w_(0), o_(0), reversed_key_(false), key_(new key_type), own_key(true) {} region_iterator_base(const array *ary, size_t start, size_t end, key_type& key) : ary_(ary), mask_(ary ? ary->size() - 1 : 0), start_id_(ary ? std::min(start, ary->size()) : 0), end_id_(ary ? std::min(end, ary->size()) : 0), mid_(ary ? std::min(end_id_ - start_id_ + ary->max_reprobe_offset(), ary->size()) : 0), oid_(end_id_), id_(0), w_(0), o_(0), reversed_key_(false), key_(&key), own_key(false) { } ~region_iterator_base() { if(own_key) delete key_; } const key_type& key() { if(!reversed_key_) { key_->set_bits(0, ary_->lsize(), ary_->inverse_matrix().times(*key_)); reversed_key_ = true; } return *key_; } mapped_type val() const { return ary_->get_val_at_id(id(), w_, o_, true, false); } uint64_t pos() const{ return oid_; } size_t start() { return start_id_; } size_t end() { return end_id_; } /// Position where key is stored size_t id() const { return (start_id_ + id_ - 1) & mask_; } /// Original position (before reprobing). size_t oid() const { return oid_; } bool next() { reversed_key_ = false; bool found_oid = false; while(!found_oid && id_ < mid_) { if(ary_->get_key_at_id((start_id_ + id_++) & mask_, *key_, &w_, &o_) == array::FILLED) { oid_ = key_->get_bits(0, ary_->lsize()); found_oid = start_id_ <= oid_ && oid_ < end_id_; } } return found_oid; } }; /// STL like iterator on a large hash array. template class stl_iterator_base : public std::iterator, public array::lazy_iterator { public: typedef typename array::key_type key_type; typedef typename array::mapped_type mapped_type; typedef typename array::value_type value_type; protected: typedef typename array::lazy_iterator lit; typedef std::pair pair; pair val_; public: explicit stl_iterator_base(const array* ary, size_t start_id = 0) : lit(ary, start_id, ary->size()), val_(lit::key_, (mapped_type)0) { ++*this; } stl_iterator_base(const array* ary, size_t start_id, size_t end_id) : lit(ary, start_id, end_id), val_(lit::key_, (mapped_type)0) { ++*this; } explicit stl_iterator_base() : lit(0, 0, 0), val_(lit::key_, (mapped_type)0) { } stl_iterator_base(const stl_iterator_base& rhs) : lit(rhs), val_(lit::key_, rhs.val_.second) { } bool operator==(const stl_iterator_base& rhs) const { return lit::ary_ == rhs.ary_ && lit::id_ == rhs.id_; } bool operator!=(const stl_iterator_base& rhs) const { return !(*this == rhs); } const value_type& operator*() { lit::key(); val_.second = lit::val(); return val_; } const value_type* operator->() { return &this->operator*(); } stl_iterator_base& operator++() { if(!lit::next()) { lit::ary_ = 0; lit::id_ = 0; } return *this; } stl_iterator_base operator++(int) { stl_iterator_base res(*this); ++*this; return res; } }; } } // namespace jellyfish { namespace large_hash { #endif /* __LARGE_HASH_ITERATOR_HPP__ */ Jellyfish-2.2.8/include/jellyfish/locks_pthread.hpp000066400000000000000000000112631323712541700224330ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_LOCKS_PTHREAD_HPP__ #define __JELLYFISH_LOCKS_PTHREAD_HPP__ #include #include #include #ifdef HAVE_CONFIG_H #include #endif namespace jellyfish { namespace locks{ namespace pthread { class cond { pthread_mutex_t _mutex; pthread_cond_t _cond; public: cond() { pthread_mutex_init(&_mutex, NULL); pthread_cond_init(&_cond, NULL); } ~cond() { pthread_cond_destroy(&_cond); pthread_mutex_destroy(&_mutex); } inline void lock() { pthread_mutex_lock(&_mutex); } inline void unlock() { pthread_mutex_unlock(&_mutex); } inline void wait() { pthread_cond_wait(&_cond, &_mutex); } inline void signal() { pthread_cond_signal(&_cond); } inline void broadcast() { pthread_cond_broadcast(&_cond); } inline int timedwait(struct timespec *abstime) { return pthread_cond_timedwait(&_cond, &_mutex, abstime); } inline int timedwait(time_t seconds) { struct timespec curtime; #ifdef HAVE_CLOCK_GETTIME clock_gettime(CLOCK_REALTIME, &curtime); #else struct timeval timeofday; gettimeofday(&timeofday, 0); curtime.tv_sec = timeofday.tv_sec; curtime.tv_nsec = timeofday.tv_usec * 1000; #endif curtime.tv_sec += seconds; return timedwait(&curtime); } }; class mutex { pthread_mutex_t _mutex; public: mutex(int type = PTHREAD_MUTEX_DEFAULT) { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, type); pthread_mutex_init(&_mutex, &attr); } ~mutex() { pthread_mutex_destroy(&_mutex); } inline void lock() { pthread_mutex_lock(&_mutex); } inline void unlock() { pthread_mutex_unlock(&_mutex); } inline bool try_lock() { return !pthread_mutex_trylock(&_mutex); } }; class mutex_recursive : public mutex { public: mutex_recursive() : mutex(PTHREAD_MUTEX_RECURSIVE) { } }; class mutex_lock { mutex& m_; public: explicit mutex_lock(mutex& m) : m_(m) { m_.lock(); } ~mutex_lock() { m_.unlock(); } }; class Semaphore { int _value, _wakeups; cond _cv; public: explicit Semaphore(int value) : _value(value), _wakeups(0) { // nothing to do } ~Semaphore() {} inline void wait() { _cv.lock(); _value--; if (_value < 0) { do { _cv.wait(); } while(_wakeups < 1); _wakeups--; } _cv.unlock(); } inline void signal() { _cv.lock(); _value++; if(_value <= 0) { _wakeups++; _cv.signal(); } _cv.unlock(); } }; #if defined(_POSIX_BARRIERS) && (_POSIX_BARRIERS - 20012L) >= 0 class barrier { pthread_barrier_t _barrier; public: explicit barrier(unsigned count) { pthread_barrier_init(&_barrier, NULL, count); } ~barrier() { pthread_barrier_destroy(&_barrier); } /// Return true if serial thread. inline bool wait() { return pthread_barrier_wait(&_barrier) == PTHREAD_BARRIER_SERIAL_THREAD; } }; #else // # ifndef PTHREAD_BARRIER_SERIAL_THREAD // # define PTHREAD_BARRIER_SERIAL_THREAD 1 // # endif class barrier { int count; // required # of threads int current; // current # of threads that have passed thru mutex barlock; // protect current Semaphore barrier1; // implement the barrier Semaphore barrier2; public: explicit barrier(unsigned cnt) : count(cnt), current(0), barrier1(0), barrier2(0) { } ~barrier() {} inline bool wait() { bool ret = false; barlock.lock(); current += 1; if(current == count) { ret = true; for(int i=0; i. */ #ifndef __JELLYFISH_MAPPED_FILE_HPP__ #define __JELLYFISH_MAPPED_FILE_HPP__ #include #include #include #include #include #include #include #include #include namespace jellyfish { class mapped_file { protected: std::string _path; char *_base, *_end; size_t _length; void map_(int fd) { struct stat stat; if(fstat(fd, &stat) < 0) throw ErrorMMap(err::msg() << "Can't stat file '" << _path << "'" << err::no); _length = stat.st_size; _base = (char*)mmap(NULL, _length, PROT_READ, MAP_SHARED, fd, 0); if(_base == MAP_FAILED) { _base = 0; throw ErrorMMap(err::msg() << "Can't mmap file '" << _path << "'" << err::no); } _end = _base + _length; } void map_(const char *filename) { int fd = open(filename, O_RDONLY); if(fd < 0) throw ErrorMMap(err::msg() << "Can't open file '" << filename << "'" << err::no); map_(fd); close(fd); } public: define_error_class(ErrorMMap); mapped_file() : _path(), _base(0), _end(0), _length(0) { } explicit mapped_file(const char *filename) : _path(filename), _base(0), _end(0), _length(0) { map_(filename); } explicit mapped_file(int fd) : _path(), _base(0), _end(0), _length() { map_(fd); } mapped_file(mapped_file&& rhs) : _path(std::move(rhs._path)), _base(rhs._base), _end(rhs._end), _length(rhs._length) { rhs._base = 0; } ~mapped_file() { unmap(); } void map(const char* filename) { unmap(); map_(filename); } void map(int fd) { unmap(); map_(fd); } void unmap() { if(!_base) return; munmap(_base, _length); _path.clear(); _base = 0; _length = 0; } mapped_file& operator=(mapped_file&& rhs) { _path = std::move(rhs._path); _base = rhs._base; rhs._base = 0; _end = rhs._end; _length = rhs._length; return *this; } void swap(mapped_file& rhs) { std::swap(_path, rhs._path); std::swap(_base, rhs._base); std::swap(_end, rhs._end); std::swap(_length, rhs._length); } char *base() const { return _base; } char *end() const { return _end; } size_t length() const { return _length; } std::string path() const { return _path; } // No error checking here. Should I throw something? const mapped_file & will_need() const { madvise(_base, _length, MADV_WILLNEED); return *this; } const mapped_file & sequential() const { madvise(_base, _length, MADV_SEQUENTIAL); return *this; } const mapped_file & random() const { madvise(_base, _length, MADV_RANDOM); return *this; } const mapped_file & lock() const { if(mlock(_base, _length) < 0) throw ErrorMMap(err::msg() << "Can't lock map in memory" << err::no); return *this; } char load() const { const long sz = sysconf(_SC_PAGESIZE); // Do not optimize. Side effect is that every page is accessed and // should now be in cache. volatile char unused = 0; for(const char *w = _base; w < _base + _length; w += sz) unused ^= *w; return unused; } }; inline void swap(mapped_file& a, mapped_file& b) { a.swap(b); } // class mapped_files_t : public std::vector { // public: // mapped_files_t(int nb_files, char *argv[]) { // for(int j = 0; j < nb_files; j++) // push_back(mapped_file(argv[j])); // } // mapped_files_t(int nb_files, char *argv[], bool sequential) { // for(int j = 0; j < nb_files; j++) { // push_back(mapped_file(argv[j])); // if(sequential) // end()->sequential(); // } // } // }; // // File mapped on demand. // class lazy_mapped_file_t : public mapped_file { // std::string _path; // volatile bool done; // volatile long used_counter; // public: // explicit lazy_mapped_file_t(const char *path) : // mapped_file((char *)0, (size_t)0), // _path(path), done(false), used_counter(0) {} // void map() { // used_counter = 1; // done = false; // mapped_file::map(_path.c_str()); // } // void unmap() { // done = true; // dec(); // } // void inc() { // atomic::gcc::fetch_add(&used_counter, (long)1); // } // void dec() { // long val = atomic::gcc::add_fetch(&used_counter, (long)-1); // if(done && val == 0) // mapped_file::unmap(); // } // }; // class lazy_mapped_files_t : public std::vector { // public: // lazy_mapped_files_t(int nb_files, char *argv[]) { // for(int j = 0; j < nb_files; j++) // push_back(lazy_mapped_file_t(argv[j])); // } // lazy_mapped_files_t(int nb_files, char *argv[], bool sequential) { // for(int j = 0; j < nb_files; j++) { // push_back(lazy_mapped_file_t(argv[j])); // if(sequential) // end()->sequential(); // } // } // }; } #endif Jellyfish-2.2.8/include/jellyfish/mer_dna.hpp000066400000000000000000000573521323712541700212270ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_MER_DNA_HPP__ #define __JELLYFISH_MER_DNA_HPP__ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_INT128 #include #endif namespace jellyfish { namespace mer_dna_ns { #define R -1 #define I -2 #define O -3 #define A 0 #define C 1 #define G 2 #define T 3 static const int codes[256] = { O, O, O, O, O, O, O, O, O, O, I, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, R, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, A, R, C, R, O, O, G, R, O, O, R, O, R, R, O, O, O, R, R, T, O, R, R, R, R, O, O, O, O, O, O, O, A, R, C, R, O, O, G, R, O, O, R, O, R, R, O, O, O, R, R, T, O, R, R, R, R, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O }; #undef R #undef I #undef O #undef A #undef C #undef G #undef T static const char rev_codes[4] = { 'A', 'C', 'G', 'T' }; extern const char* const error_different_k; extern const char* const error_short_string; // Checkered mask. cmask is every other bit on // (0x55). cmask is two bits one, two bits off (0x33). Etc. template struct cmask { static const U v = (cmask::v << (2 * len)) | (((U)1 << len) - 1); }; template struct cmask { static const U v = 0; }; // Fast reverse complement of one word through bit tweedling. inline uint32_t word_reverse_complement(uint32_t w) { typedef uint64_t U; w = ((w >> 2) & cmask::v) | ((w & cmask::v) << 2); w = ((w >> 4) & cmask::v) | ((w & cmask::v) << 4); w = ((w >> 8) & cmask::v) | ((w & cmask::v) << 8); w = ( w >> 16 ) | ( w << 16); return ((U)-1) - w; } inline uint64_t word_reverse_complement(uint64_t w) { typedef uint64_t U; w = ((w >> 2) & cmask::v) | ((w & cmask::v) << 2); w = ((w >> 4) & cmask::v) | ((w & cmask::v) << 4); w = ((w >> 8) & cmask::v) | ((w & cmask::v) << 8); w = ((w >> 16) & cmask::v) | ((w & cmask::v) << 16); w = ( w >> 32 ) | ( w << 32); return ((U)-1) - w; } #ifdef HAVE_INT128 inline unsigned __int128 word_reverse_complement(unsigned __int128 w) { typedef unsigned __int128 U; w = ((w >> 2) & cmask::v) | ((w & cmask::v) << 2); w = ((w >> 4) & cmask::v) | ((w & cmask::v) << 4); w = ((w >> 8) & cmask::v) | ((w & cmask::v) << 8); w = ((w >> 16) & cmask::v) | ((w & cmask::v) << 16); w = ((w >> 32) & cmask::v) | ((w & cmask::v) << 32); w = ( w >> 64 ) | ( w << 64); return ((U)-1) - w; } #endif template class base_proxy { public: typedef T base_type; base_proxy(base_type* w, unsigned int i) : word_(w), i_(i) { } base_proxy& operator=(char base) { return this->operator=(codes[(int)(unsigned char)base]); } base_proxy& operator=(int code) { base_type mask = (base_type)0x3 << i_; *word_ = (*word_ & ~mask) | ((base_type)code << i_); return *this; } int code() const { return (*word_ >> i_) & (base_type)0x3; } operator char() const { return rev_codes[code()]; } private: base_type* const word_; unsigned int i_; }; // enum { CODE_A, CODE_C, CODE_G, CODE_T, // CODE_RESET = -1, CODE_IGNORE = -2, CODE_COMMENT = -3 }; template struct mer_dna_traits { }; template class mer_base { public: typedef typename mer_dna_traits::base_type base_type; enum { CODE_A, CODE_C, CODE_G, CODE_T, CODE_RESET = -1, CODE_IGNORE = -2, CODE_COMMENT = -3 }; explicit mer_base(unsigned int k) : _data(new base_type[derived::nb_words(k)]) { memset(_data, '\0', nb_words(k) * sizeof(base_type)); } mer_base(const mer_base &m) : _data(new base_type[nb_words(static_cast(&m)->k())]) { memcpy(_data, m._data, nb_words(static_cast(&m)->k()) * sizeof(base_type)); } template mer_base(const unsigned int k, const U& rhs) : _data(new base_type[nb_words(k)]) { for(unsigned int i = 0; i < k; ++i) _data[i] = rhs[i]; clean_msw(); } ~mer_base() { delete [] _data; } operator derived() { return *static_cast(this); } operator const derived() const { return *static_cast(this); } unsigned int k() const { return static_cast(this)->k(); } /// Direct access to data. No bound or consistency check. Use with /// caution! // base_type operator[](unsigned int i) { return _data[i]; } base_type word(unsigned int i) const { return _data[i]; } base_type operator[](unsigned int i) const { return _data[i]; } /// Direct access to the data array. const base_type* data() const { return _data; } /// Same as above, but can modify directly content. Use at your own /// risk! base_type& word__(unsigned int i) { return _data[i]; } base_type* data__() { return _data; } template void read(std::istream& is) { const unsigned int k = static_cast(this)->k(); const unsigned int l = k / (4 * alignment) + (k % (4 * alignment) != 0); is.read((char*)_data, l); } bool operator==(const mer_base& rhs) const { unsigned int i = nb_words() - 1; bool res = (_data[i] & msw()) == (rhs._data[i] & msw()); while(res && i > 7) { i -= 8; res = res && (_data[i+7] == rhs._data[i+7]); res = res && (_data[i+6] == rhs._data[i+6]); res = res && (_data[i+5] == rhs._data[i+5]); res = res && (_data[i+4] == rhs._data[i+4]); res = res && (_data[i+3] == rhs._data[i+3]); res = res && (_data[i+2] == rhs._data[i+2]); res = res && (_data[i+1] == rhs._data[i+1]); res = res && (_data[i] == rhs._data[i] ); } switch(i) { case 7: res = res && (_data[6] == rhs._data[6]); case 6: res = res && (_data[5] == rhs._data[5]); case 5: res = res && (_data[4] == rhs._data[4]); case 4: res = res && (_data[3] == rhs._data[3]); case 3: res = res && (_data[2] == rhs._data[2]); case 2: res = res && (_data[1] == rhs._data[1]); case 1: res = res && (_data[0] == rhs._data[0]); } return res; } bool operator!=(const mer_base& rhs) const { return !this->operator==(rhs); } bool operator<(const mer_base& rhs) const { unsigned int i = nb_words(); while(i >= 8) { i -= 8; if(_data[i+7] != rhs._data[i+7]) return _data[i+7] < rhs._data[i+7]; if(_data[i+6] != rhs._data[i+6]) return _data[i+6] < rhs._data[i+6]; if(_data[i+5] != rhs._data[i+5]) return _data[i+5] < rhs._data[i+5]; if(_data[i+4] != rhs._data[i+4]) return _data[i+4] < rhs._data[i+4]; if(_data[i+3] != rhs._data[i+3]) return _data[i+3] < rhs._data[i+3]; if(_data[i+2] != rhs._data[i+2]) return _data[i+2] < rhs._data[i+2]; if(_data[i+1] != rhs._data[i+1]) return _data[i+1] < rhs._data[i+1]; if(_data[i] != rhs._data[i]) return _data[i] < rhs._data[i]; } switch(i) { case 7: if(_data[6] != rhs._data[6]) return _data[6] < rhs._data[6]; case 6: if(_data[5] != rhs._data[5]) return _data[5] < rhs._data[5]; case 5: if(_data[4] != rhs._data[4]) return _data[4] < rhs._data[4]; case 4: if(_data[3] != rhs._data[3]) return _data[3] < rhs._data[3]; case 3: if(_data[2] != rhs._data[2]) return _data[2] < rhs._data[2]; case 2: if(_data[1] != rhs._data[1]) return _data[1] < rhs._data[1]; case 1: if(_data[0] != rhs._data[0]) return _data[0] < rhs._data[0]; } return false; } bool operator<=(const mer_base& rhs) const { return *this < rhs || *this == rhs; } bool operator>(const mer_base& rhs) const { return !(*this <= rhs); } bool operator>=(const mer_base& rhs) const { return !(*this < rhs); } base_proxy base(unsigned int i) { return base_proxy(_data + i / wbases, 2 * (i % wbases)); } const base_proxy base(unsigned int i) const { return base_proxy(_data + i / wbases, 2 * (i % wbases)); } // Make current k-mer all As. void polyA() { memset(_data, 0x00, sizeof(base_type) * nb_words()); clean_msw(); } void polyC() { memset(_data, 0x55, sizeof(base_type) * nb_words()); clean_msw(); } void polyG() { memset(_data, 0xaa, sizeof(base_type) * nb_words()); clean_msw(); } void polyT() { memset(_data, 0xff, sizeof(base_type) * nb_words()); clean_msw(); } void randomize() { for(unsigned int i = 0; i < nb_words(); ++i) _data[i] = random_bits(wbits); clean_msw(); } bool is_homopolymer() const { const base_type base = _data[0] & c3; const unsigned int barrier = nb_words(); unsigned int i = 0; for( ; i + 5 < barrier; i += 4) { if(_data[i ] != ((_data[i ] << 2) | base)) return false; if(_data[i + 1] != ((_data[i + 1] << 2) | base)) return false; if(_data[i + 2] != ((_data[i + 2] << 2) | base)) return false; if(_data[i + 3] != ((_data[i + 3] << 2) | base)) return false; } switch(nb_words() - i) { case 5: if(_data[i] != ((_data[i] << 2) | base) ) return false; ++i; case 4: if(_data[i] != ((_data[i] << 2) | base) ) return false; ++i; case 3: if(_data[i] != ((_data[i] << 2) | base) ) return false; ++i; case 2: if(_data[i] != ((_data[i] << 2) | base) ) return false; ++i; case 1: if(_data[i] != (((_data[i] << 2) | base) & msw())) return false; } return true; } derived& operator=(const mer_base& rhs) { memcpy(_data, rhs._data, nb_words() * sizeof(base_type)); return *static_cast(this); } derived& operator=(const char* s) { if(strlen(s) < static_cast(this)->k()) throw std::length_error(error_short_string); from_chars(s); return *static_cast(this); } derived& operator=(const std::string& s) { if(s.size() < static_cast(this)->k()) throw std::length_error(error_short_string); from_chars(s.c_str()); return *static_cast(this); } // Shift the k-mer by 1 base, left or right. The char version take // a base 'A', 'C', 'G', or 'T'. The base_type version takes a code // in [0, 3] (not check of validity of argument, taken modulo // 4). The return value is the base that was pushed off the side // ('N' if the input character is not a valid base). base_type shift_left(int c) { const base_type r = (_data[nb_words()-1] >> lshift()) & c3; const unsigned int barrier = nb_words() & (~c3); base_type c2; // c2 and c1: carries base_type c1 = (base_type)c & c3; unsigned int i = 0; for( ; i < barrier; i += 4) { c2 = _data[i] >> wshift; _data[i] = (_data[i] << 2) | c1; c1 = _data[i+1] >> wshift; _data[i+1] = (_data[i+1] << 2) | c2; c2 = _data[i+2] >> wshift; _data[i+2] = (_data[i+2] << 2) | c1; c1 = _data[i+3] >> wshift; _data[i+3] = (_data[i+3] << 2) | c2; } c2 = c1; switch(nb_words() - i) { case 3: c2 = _data[i] >> wshift; _data[i] = (_data[i] << 2) | c1; ++i; case 2: c1 = _data[i] >> wshift; _data[i] = (_data[i] << 2) | c2; ++i; case 1: _data[i] = (_data[i] << 2) | c1; } clean_msw(); return r; } base_type shift_right(int c) { const base_type r = _data[0] & c3; if(nb_words() > 1){ const unsigned int barrier = (nb_words() - 1) & (~c3); unsigned int i = 0; for( ; i < barrier; i += 4) { _data[i] = (_data[i] >> 2) | (_data[i+1] << wshift); _data[i+1] = (_data[i+1] >> 2) | (_data[i+2] << wshift); _data[i+2] = (_data[i+2] >> 2) | (_data[i+3] << wshift); _data[i+3] = (_data[i+3] >> 2) | (_data[i+4] << wshift); } switch(nb_words() - 1 - i) { case 3: _data[i] = (_data[i] >> 2) | (_data[i+1] << wshift); ++i; case 2: _data[i] = (_data[i] >> 2) | (_data[i+1] << wshift); ++i; case 1: _data[i] = (_data[i] >> 2) | (_data[i+1] << wshift); } } _data[nb_words() - 1] = ((_data[nb_words() - 1] & msw()) >> 2) | (((base_type)c & c3) << lshift()); return r; } // Non DNA codes are negative inline static bool not_dna(int c) { return c < 0; } inline static int code(char c) { return codes[(int)(unsigned char)c]; } inline static char rev_code(int x) { return rev_codes[x]; } static int complement(int x) { return (base_type)3 - x; } static char complement(char c) { switch(c) { case 'A': case 'a': return 'T'; case 'C': case 'c': return 'G'; case 'G': case 'g': return 'C'; case 'T': case 't': return 'A'; } return 'N'; } char shift_left(char c) { int x = code(c); if(x == -1) return 'N'; return rev_code(shift_left(x)); } char shift_right(char c) { int x = code(c); if(x == -1) return 'N'; return rev_code(shift_right(x)); } void reverse_complement() { base_type *low = _data; base_type *high = _data + nb_words() - 1; for( ; low < high; ++low, --high) { base_type tmp = word_reverse_complement(*low); *low = word_reverse_complement(*high); *high = tmp; } if(low == high) *low = word_reverse_complement(*low); unsigned int rs = wbits - nb_msb(); if(rs > 0) large_shift_right(rs); } void canonicalize() { derived rc = this->get_reverse_complement(); if(rc < *this) *this = rc; } derived get_reverse_complement() const { derived res(*this); res.reverse_complement(); return res; } derived get_canonical() const { derived rc = this->get_reverse_complement(); return rc < *this ? rc : *this; } // Transfomr the k-mer into a C++ string. std::string to_str() const { std::string res(static_cast(this)->k(), '\0'); to_chars(res.begin()); return res; } // Transform the k-mer into a string. For the char * version, // assume that the buffer is large enough to receive k+1 // characters (space for '\0' at end of string). void to_str(char* s) const { s = to_chars(s); *s = '\0'; } // Copy bases as char to the output iterator it. No '\0' is added // or check made that there is enough space. The iterator pointed // after the last base is returned. template OutputIterator to_chars(OutputIterator it) const { int shift = lshift(); // Number of bits to shift to get base for(int j = nb_words() - 1; j >= 0; --j) { base_type w = _data[j]; for( ; shift >= 0; shift -= 2, ++it) *it = rev_code((w >> shift) & c3); shift = wshift; } return it; } // Get bits [start, start+len). start must be < 2k, len <= // sizeof(base_type) and start+len < 2k. No checks // performed. start and len are in bits, not bases. base_type get_bits(unsigned int start, unsigned int len) const { unsigned int q = start / wbits; unsigned int r = start % wbits; base_type res = _data[q] >> r; if(len > wbits - r) res |= _data[q + 1] << (wbits - r); return len < (unsigned int)wbits ? res & (((base_type)1 << len) - 1) : res; } // Set bits [start, start+len). Same restriction as get_bits. In // some rare cases, the value written can be larger than the bits // occupied by the mer itself. The mer is then not valid if some MSB // are set to 1. template void set_bits(unsigned int start, unsigned int len, base_type v) { unsigned int q = start / wbits; unsigned int r = start % wbits; unsigned int left = wbits - r; base_type mask; if(len > left) { mask = ((base_type)1 << r) - 1; _data[q] = (_data[q] & mask) | (v << r); mask = ((base_type)1 << (len - left)) - 1; _data[q + 1] = (_data[q + 1] & ~mask) | (v >> (left)); } else { mask = (len < (unsigned int)wbits ? (((base_type)1 << len) - 1) : (base_type)-1) << r; _data[q] = (_data[q] & ~mask) | (v << r); } if(zero_msw) clean_msw(); } // Internal stuff // Number of words in _data inline static unsigned int nb_words(unsigned int k) { return (k / wbases) + (k % wbases != 0); } inline unsigned int nb_words() const { return nb_words(static_cast(this)->k()); } // Mask of highest word inline base_type msw() const { const base_type m = std::numeric_limits::max(); return m >> (wbits - nb_msb()); } // Nb of bits used in highest word inline unsigned int nb_msb() const { base_type nb = (static_cast(this)->k() % wbases) * 2; return nb ? nb : wbits; } // How much to shift last base in last word of _data inline unsigned int lshift() const { return nb_msb() - 2; } // Make sure the highest bits are all zero inline void clean_msw() { _data[nb_words() - 1] &= msw(); } template bool from_chars(InputIterator it) { int shift = lshift(); clean_msw(); for(int j = nb_words() - 1; j >= 0; --j) { base_type& w = _data[j]; w = 0; for( ; shift >= 0; shift -= 2, ++it) { int c = code(*it); if(not_dna(c)) return false; w |= (base_type)c << shift; } shift = wshift; } return true; } protected: static const base_type c3 = (base_type)0x3; static const int wshift = sizeof(base_type) * 8 - 2; // left shift in 1 word static const int wbases = 4 * sizeof(base_type); // bases in a word static const int wbits = 8 * sizeof(base_type); // bits in a word base_type * _data; // Shift to the right by rs bits (Note bits, not bases) void large_shift_right(unsigned int rs) { if(nb_words() > 1) { const unsigned int barrier = (nb_words() - 1) & (~c3); const unsigned int ls = wbits - rs; unsigned int i = 0; for( ; i < barrier; i += 4) { _data[i] = (_data[i] >> rs) | (_data[i+1] << ls); _data[i+1] = (_data[i+1] >> rs) | (_data[i+2] << ls); _data[i+2] = (_data[i+2] >> rs) | (_data[i+3] << ls); _data[i+3] = (_data[i+3] >> rs) | (_data[i+4] << ls); } switch(nb_words() - 1 - i) { case 3: _data[i] = (_data[i] >> rs) | (_data[i+1] << ls); ++i; case 2: _data[i] = (_data[i] >> rs) | (_data[i+1] << ls); ++i; case 1: _data[i] = (_data[i] >> rs) | (_data[i+1] << ls); } } _data[nb_words() - 1] >>= rs; clean_msw(); } }; // Mer type where the length is kept in each mer object: allows to // manipulate mers of different size within the same application. template class mer_base_dynamic : public mer_base > { public: typedef T base_type; typedef mer_base > super; explicit mer_base_dynamic(unsigned int k) : super(k), k_(k) { } mer_base_dynamic(const mer_base_dynamic& rhs) : super(rhs), k_(rhs.k()) { } mer_base_dynamic(unsigned int k, const char* s) : super(k), k_(k) { super::from_chars(s); } explicit mer_base_dynamic(const char* s) : super(strlen(s)), k_(strlen(s)) { super::from_chars(s); } explicit mer_base_dynamic(const std::string& s) : super(s.size()), k_(s.size()) { super::from_chars(s.begin()); } template explicit mer_base_dynamic(unsigned int k, const U& rhs) : super(k, rhs), k_(k) { } ~mer_base_dynamic() { } mer_base_dynamic& operator=(const mer_base_dynamic rhs) { if(k_ != rhs.k_) throw std::length_error(error_different_k); super::operator=(rhs); return *this; } unsigned int k() const { return k_; } static unsigned int k(unsigned int k) { return k; } private: const unsigned int k_; }; template struct mer_dna_traits > { typedef T base_type; }; // Mer type where the length is a static variable: the mer size is // fixed for all k-mers in the application. // // The CI (Class Index) template parameter allows to have more than one such // class with different length in the same application. Each class has // its own static variable associated with it. template class mer_base_static : public mer_base > { public: typedef T base_type; typedef mer_base > super; static const int class_index = CI; mer_base_static() : super(k_) { } explicit mer_base_static(unsigned int k) : super(k_) { if(k != k_) throw std::length_error(error_different_k); } mer_base_static(const mer_base_static& rhs) : super(rhs) { } mer_base_static(unsigned int k, const char* s) : super(k_) { super::from_chars(s); } explicit mer_base_static(const char* s) : super(k_) { super::from_chars(s); } explicit mer_base_static(const std::string& s) : super(k_) { super::from_chars(s.begin()); } template mer_base_static(unsigned int k, const U& rhs) : super(k_, rhs) { if(k != k_) throw std::length_error(error_different_k); } mer_base_static& operator=(const char* s) { return super::operator=(s); } mer_base_static& operator=(const std::string& s) { return super::operator=(s); } ~mer_base_static() { } static unsigned int k(); // { return k_; } static unsigned int k(unsigned int k) { std::swap(k, k_); return k; } private: static unsigned int k_; }; template unsigned int mer_base_static::k_ = 22; template unsigned int mer_base_static::k() { return k_; } template const int mer_base_static::class_index; template struct mer_dna_traits > { typedef T base_type; }; typedef std::ostream_iterator ostream_char_iterator; template inline std::ostream& operator<<(std::ostream& os, const mer_base& mer) { // char s[static_cast(mer).k() + 1]; char s[mer.k() + 1]; mer.to_str(s); return os << s; } typedef std::istream_iterator istream_char_iterator; template inline std::istream& operator>>(std::istream& is, mer_base& mer) { if(is.flags() & std::ios::skipws) { while(isspace(is.peek())) { is.ignore(1); } } char buffer[mer.k() + 1]; is.read(buffer, mer.k()); if(is.gcount() != mer.k()) goto error; buffer[mer.k()] = '\0'; if(!mer.from_chars(buffer)) goto error; return is; error: is.setstate(std::ios::failbit); return is; } } // namespace mer_dna_ns typedef mer_dna_ns::mer_base_static mer_dna32; typedef mer_dna_ns::mer_base_static mer_dna64; #ifdef HAVE_INT128 typedef mer_dna_ns::mer_base_static mer_dna128; #endif typedef mer_dna64 mer_dna; } // namespace jellyfish #endif Jellyfish-2.2.8/include/jellyfish/mer_dna_bloom_counter.hpp000066400000000000000000000033331323712541700241440ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_MER_DNA_BLOOM_COUNTER_HPP_ #define __JELLYFISH_MER_DNA_BLOOM_COUNTER_HPP_ #include #include #include #include #include namespace jellyfish { template<> struct hash_pair { RectangularBinaryMatrix m1, m2; hash_pair() : m1(8 * sizeof(uint64_t), mer_dna::k() * 2), m2(8 * sizeof(uint64_t), mer_dna::k() * 2) { m1.randomize(random_bits); m2.randomize(random_bits); } hash_pair(RectangularBinaryMatrix&& m1_, RectangularBinaryMatrix&& m2_) : m1(m1_), m2(m2_) { } void operator()(const mer_dna& k, uint64_t* hashes) const { hashes[0] = m1.times(k); hashes[1] = m2.times(k); } }; typedef bloom_counter2 mer_dna_bloom_counter; typedef bloom_counter2_file mer_dna_bloom_counter_file; typedef bloom_filter mer_dna_bloom_filter; typedef bloom_filter_file mer_dna_bloom_filter_file; } #endif /* __JELLYFISH_MER_DNA_BLOOM_COUNTER_HPP_ */ Jellyfish-2.2.8/include/jellyfish/mer_heap.hpp000066400000000000000000000067171323712541700214010ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_HEAP_HPP__ #define __JELLYFISH_HEAP_HPP__ #include #include namespace jellyfish { namespace mer_heap { template struct heap_item { Key key_; uint64_t val_; uint64_t pos_; Iterator* it_; heap_item() : it_(0) { } heap_item(Iterator& iter) : key_(iter.key()), val_(iter.val()), pos_(iter.pos()), it_(&iter) { } bool operator>(const heap_item& other) const { if(pos_ == other.pos_) return key_ > other.key_; return pos_ > other.pos_; } }; // STL make_heap creates a max heap. We want a min heap, so // we use the > operator template struct heap_item_comp { bool operator()(const heap_item* i1, const heap_item* i2) { return *i1 > *i2; } }; template class heap { heap_item* storage_; // Storage of the elements heap_item** elts_; // Pointers to storage. Create a heap of pointers size_t capacity_; // Actual capacity size_t h_; // Head pointer heap_item_comp comp_; public: typedef const heap_item *const_item_t; heap() : storage_(0), elts_(0), capacity_(0), h_(0) { } explicit heap(size_t capacity) { initialize(capacity); } ~heap() { delete[] storage_; delete[] elts_; } void initialize(size_t capacity) { capacity_ = capacity; h_ = 0; storage_ = new heap_item[capacity_]; elts_ = new heap_item*[capacity_]; for(size_t h1 = 0; h1 < capacity_; ++h1) elts_[h1] = &storage_[h1]; } void fill(Iterator &it) { for(h_ = 0; h_ < capacity_; ++h_) { if(!it.next()) break; storage_[h_] = it; elts_[h_] = &storage_[h_]; } std::make_heap(elts_, elts_ + h_, comp_); } // template // void fill(ForwardIterator first, ForwardIterator last) { // h_ = 0; // while(h_ < capacity_ && first != last) { // if(!first->next()) // break; // storage_[h_].initialize(*first++); // elts_[h_] = &storage_[h_]; // h_++; // } // std::make_heap(elts_, elts_ + h_, compare); // } bool is_empty() const { return h_ == 0; } bool is_not_empty() const { return h_ > 0; } size_t size() const { return h_; } size_t capacity() const { return capacity_; } // The following 3 should only be used after fill has been called const_item_t head() const { return elts_[0]; } void pop() { std::pop_heap(elts_, elts_ + h_--, comp_); } void push(Iterator &item) { *elts_[h_] = item; std::push_heap(elts_, elts_ + ++h_, comp_); } }; } } // namespace jellyfish { namespace mer_heap { #endif // __HEAP_HPP__ Jellyfish-2.2.8/include/jellyfish/mer_iterator.hpp000066400000000000000000000057471323712541700223170ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __MER_ITERATOR_HPP__ #define __MER_ITERATOR_HPP__ #include #include namespace jellyfish { template class mer_iterator : public std::iterator { typename SequencePool::job* job_; const char* cseq_; MerType m_; // mer MerType rcm_; // reverse complement mer unsigned int filled_; const bool canonical_; public: typedef MerType mer_type; typedef SequencePool sequence_parser_type; mer_iterator(SequencePool& seq, bool canonical = false) : job_(new typename SequencePool::job(seq)), cseq_(0), filled_(0), canonical_(canonical) { if(job_->is_empty()) { delete job_; job_ = 0; } else { cseq_ = (*job_)->start; this->operator++(); } } mer_iterator() : job_(0), cseq_(0), filled_(0), canonical_(false) { } // mer_iterator(const mer_iterator& rhs) : job_(rhs.job_), cseq_(rhs.cseq_), m_(rhs.m_), filled_(rhs.filled_) { } ~mer_iterator() { delete job_; } bool operator==(const mer_iterator& rhs) const { return job_ == rhs.job_; } bool operator!=(const mer_iterator& rhs) const { return job_ != rhs.job_; } operator void*() const { return (void*)job_; } const mer_type& operator*() const { return !canonical_ || m_ < rcm_ ? m_ : rcm_; } const mer_type* operator->() const { return &this->operator*(); } mer_iterator& operator++() { while(true) { while(cseq_ == (*job_)->end) { job_->next(); if(job_->is_empty()) { delete job_; job_ = 0; cseq_ = 0; return *this; } cseq_ = (*job_)->start; filled_ = 0; } do { int code = m_.code(*cseq_++); if(code >= 0) { m_.shift_left(code); if(canonical_) rcm_.shift_right(rcm_.complement(code)); filled_ = std::min(filled_ + 1, mer_dna::k()); } else filled_ = 0; } while(filled_ < m_.k() && cseq_ < (*job_)->end); if(filled_ >= m_.k()) break; } return *this; } mer_iterator operator++(int) { mer_iterator res(*this); ++*this; return res; } }; } // namespace jellyfish { #endif /* __MER_ITERATOR_HPP__ */ Jellyfish-2.2.8/include/jellyfish/mer_overlap_sequence_parser.hpp000066400000000000000000000222161323712541700253700ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_MER_OVELAP_SEQUENCE_PARSER_H_ #define __JELLYFISH_MER_OVELAP_SEQUENCE_PARSER_H_ #include #include #include #include #include #include namespace jellyfish { struct sequence_ptr { char* start; char* end; }; template class mer_overlap_sequence_parser : public jellyfish::cooperative_pool2, sequence_ptr> { typedef jellyfish::cooperative_pool2, sequence_ptr> super; struct stream_status { char* seam; size_t seq_len; bool have_seam; file_type type; stream_type stream; stream_status() : seam(0), seq_len(0), have_seam(false), type(DONE_TYPE) { } }; uint16_t mer_len_; size_t buf_size_; char* buffer; char* seam_buffer; locks::pthread::mutex streams_mutex; char* data; cpp_array streams_; StreamIterator& streams_iterator_; size_t files_read_; // nb of files read size_t reads_read_; // nb of reads read public: /// Max_producers is the maximum number of concurrent threads than /// can produce data simultaneously. Size is the number of buffer to /// keep around. It should be larger than the number of thread /// expected to read from this class. buf_size is the size of each /// buffer. A StreamIterator is expected to have a next() method, /// which is thread safe, and which returns (move) a /// std::unique object. mer_overlap_sequence_parser(uint16_t mer_len, uint32_t max_producers, uint32_t size, size_t buf_size, StreamIterator& streams) : super(max_producers, size), mer_len_(mer_len), buf_size_(buf_size), buffer(new char[size * buf_size]), seam_buffer(new char[max_producers * (mer_len - 1)]), streams_(max_producers), streams_iterator_(streams), files_read_(0), reads_read_(0) { for(sequence_ptr* it = super::element_begin(); it != super::element_end(); ++it) it->start = it->end = buffer + (it - super::element_begin()) * buf_size; for(uint32_t i = 0; i < max_producers; ++i) { streams_.init(i); streams_[i].seam = seam_buffer + i * (mer_len - 1); open_next_file(streams_[i]); } } ~mer_overlap_sequence_parser() { delete [] buffer; delete [] seam_buffer; } // file_type get_type() const { return type; } inline bool produce(uint32_t i, sequence_ptr& buff) { stream_status& st = streams_[i]; switch(st.type) { case FASTA_TYPE: read_fasta(st, buff); break; case FASTQ_TYPE: read_fastq(st, buff); break; #ifdef HAVE_HTSLIB case SAM_TYPE: read_sam(st, buff); break; #endif case DONE_TYPE: return true; } if(st.stream.good()) return false; // Reach the end of file, close current and try to open the next one st.have_seam = false; open_next_file(st); return false; } size_t nb_files() const { return files_read_; } size_t nb_reads() const { return reads_read_; } protected: bool open_next_file(stream_status& st) { // The stream must be released, with .reset(), before calling // .next() on the streams_iterator_, to ensure that the // streams_iterator_ noticed that we closed that stream before // requesting a new one. st.stream.reset(); st.stream = std::move(streams_iterator_.next()); if(!st.stream.good()) { st.type = DONE_TYPE; return false; } ++files_read_; if(st.stream.standard) { switch(st.stream.standard->peek()) { case EOF: return open_next_file(st); case '>': st.type = FASTA_TYPE; ignore_line(*st.stream.standard); // Pass header ++reads_read_; break; case '@': st.type = FASTQ_TYPE; ignore_line(*st.stream.standard); // Pass header ++reads_read_; break; default: throw std::runtime_error("Unsupported format"); // Better error management } } #ifdef HAVE_HTSLIB else if(st.stream.sam) { st.type = SAM_TYPE; } #endif else { st.type = DONE_TYPE; } return true; } void read_fasta(stream_status& st, sequence_ptr& buff) { auto& stream = *st.stream.standard; size_t read = 0; if(st.have_seam) { memcpy(buff.start, st.seam, mer_len_ - 1); read = mer_len_ - 1; } // Here, the current stream is assumed to always point to some // sequence (or EOF). Never at header. while(stream.good() && read < buf_size_ - mer_len_ - 1) { read += read_sequence(stream, read, buff.start, '>'); if(stream.peek() == '>') { if(read > 0) *(buff.start + read++) = 'N'; // Add N between reads ignore_line(stream); // Skip to next sequence (skip headers, quals, ...) ++reads_read_; } } buff.end = buff.start + read; st.have_seam = read >= (size_t)(mer_len_ - 1); if(st.have_seam) memcpy(st.seam, buff.end - mer_len_ + 1, mer_len_ - 1); } void read_fastq(stream_status& st, sequence_ptr& buff) { auto& stream = *st.stream.standard; size_t read = 0; if(st.have_seam) { memcpy(buff.start, st.seam, mer_len_ - 1); read = mer_len_ - 1; } // Here, the st.stream is assumed to always point to some // sequence (or EOF). Never at header. while(stream.good() && read < buf_size_ - mer_len_ - 1) { size_t nread = read_sequence(stream, read, buff.start, '+'); read += nread; st.seq_len += nread; if(stream.peek() == '+') { skip_quals(stream, st.seq_len); if(stream.good()) { *(buff.start + read++) = 'N'; // Add N between reads ignore_line(stream); // Skip sequence header ++reads_read_; } st.seq_len = 0; } } buff.end = buff.start + read; st.have_seam = read >= (size_t)(mer_len_ - 1); if(st.have_seam) memcpy(st.seam, buff.end - mer_len_ + 1, mer_len_ - 1); } #ifdef HAVE_HTSLIB void read_sam(stream_status& st, sequence_ptr& buff) { auto& stream = *st.stream.sam; size_t read = 0; if(st.have_seam) { memcpy(buff.start, st.seam, mer_len_ - 1); read = mer_len_ - 1; } // std.seq_len is the amount of sequence left in the stream buffer // to read. When st.seq_len==0, we need to get the next sequence // from the stream. auto seq = buff.start; while(read < buf_size_ - mer_len_ - 1) { if(st.seq_len == 0) { if(stream.next() < 0) break; st.seq_len = stream.seq_len(); if(read > 0) seq[read++] = 'N'; ++reads_read_; } const size_t start = stream.seq_len() - st.seq_len; const size_t limit = std::min(st.seq_len, buf_size_ - 1 - read) + start; for(size_t i = start; i < limit; ++i, ++read) seq[read] = stream.base(i); st.seq_len -= (limit - start); } buff.end = buff.start + read; st.have_seam = read >= (size_t)(mer_len_ - 1); if(st.have_seam) memcpy(st.seam, buff.end - mer_len_ + 1, mer_len_ - 1); } #endif size_t read_sequence(std::istream& is, const size_t read, char* const start, const char stop) { size_t nread = read; skip_newlines(is); // Skip new lines -> get below doesn't like them while(is && nread < buf_size_ - 1 && is.peek() != stop) { is.get(start + nread, buf_size_ - nread); nread += is.gcount(); skip_newlines(is); } return nread - read; } inline void ignore_line(std::istream& is) { is.ignore(std::numeric_limits::max(), '\n'); } inline void skip_newlines(std::istream& is) { while(is.peek() == '\n') is.get(); } // Skip quals header and qual values (read_len) of them. void skip_quals(std::istream& is, size_t read_len) { ignore_line(is); size_t quals = 0; skip_newlines(is); while(is.good() && quals < read_len) { is.ignore(read_len - quals + 1, '\n'); quals += is.gcount(); if(is) ++read_len; skip_newlines(is); } skip_newlines(is); if(quals == read_len && (is.peek() == '@' || is.peek() == EOF)) return; throw std::runtime_error("Invalid fastq sequence"); } char peek(std::istream& is) { return is.peek(); } }; } #endif /* __JELLYFISH_MER_OVELAP_SEQUENCE_PARSER_H_ */ Jellyfish-2.2.8/include/jellyfish/mer_qual_iterator.hpp000066400000000000000000000071721323712541700233330ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __MER_QUAL_ITERATOR_HPP__ #define __MER_QUAL_ITERATOR_HPP__ #include #include namespace jellyfish { template class mer_qual_iterator : public std::iterator { typename SequencePool::job* job_; std::string::const_iterator cseq_, eseq_; std::string::const_iterator cqual_, equal_; MerType m_; // mer MerType rcm_; // reverse complement mer unsigned int filled_; const char min_qual_; const bool canonical_; size_t index_; public: typedef MerType mer_type; typedef SequencePool sequence_parser_type; mer_qual_iterator(SequencePool& seq, char min_qual, bool canonical = false) : job_(new typename SequencePool::job(seq)), filled_(0), min_qual_(min_qual), canonical_(canonical), index_(0) { if(job_->is_empty()) { delete job_; job_ = 0; } else { init_from_job(); this->operator++(); } } mer_qual_iterator() : job_(0), filled_(0), canonical_(false), index_(0) { } // mer_iterator(const mer_iterator& rhs) : job_(rhs.job_), cseq_(rhs.cseq_), m_(rhs.m_), filled_(rhs.filled_) { } ~mer_qual_iterator() { delete job_; } bool operator==(const mer_qual_iterator& rhs) const { return job_ == rhs.job_; } bool operator!=(const mer_qual_iterator& rhs) const { return job_ != rhs.job_; } operator void*() const { return (void*)job_; } const mer_type& operator*() const { return !canonical_ || m_ < rcm_ ? m_ : rcm_; } const mer_type* operator->() const { return &this->operator*(); } mer_qual_iterator& operator++() { while(true) { while(cseq_ == eseq_) { ++index_; while(index_ >= (*job_)->nb_filled) { index_ = 0; job_->next(); if(job_->is_empty()) { delete job_; job_ = 0; return *this; } } init_from_job(); filled_ = 0; } do { const int code = m_.code(*cseq_++); const char qual = cqual_ < equal_ ? *cqual_++ : std::numeric_limits::max(); if(code >= 0 && qual >= min_qual_) { m_.shift_left(code); if(canonical_) rcm_.shift_right(rcm_.complement(code)); filled_ = std::min(filled_ + 1, mer_dna::k()); } else filled_ = 0; } while(filled_ < m_.k() && cseq_ < eseq_); if(filled_ >= m_.k()) break; } return *this; } mer_qual_iterator operator++(int) { mer_qual_iterator res(*this); ++*this; return res; } private: void init_from_job() { std::string& seq = (*job_)->data[index_].seq; cseq_ = seq.begin(); eseq_ = seq.end(); std::string& quals = (*job_)->data[index_].qual; cqual_ = quals.begin(); equal_ = quals.end(); } }; } // namespace jellyfish { #endif /* __MER_QUAL_ITERATOR_HPP__ */ Jellyfish-2.2.8/include/jellyfish/misc.hpp000066400000000000000000000205151323712541700205440ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_MISC_HPP__ #define __JELLYFISH_MISC_HPP__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace jellyfish { #define bsizeof(v) (8 * sizeof(v)) typedef uint_fast64_t uint_t; //#define UINT_C(x) #define PRIUINTu PRIuFAST64 #define PRIUINTx PRIxFAST64 inline int leading_zeroes(int x) { return __builtin_clz(x); } // CLK inline int leading_zeroes(unsigned int x) { return __builtin_clz(x); } inline int leading_zeroes(unsigned long x) { return __builtin_clzl(x); } inline int leading_zeroes(unsigned long long x) { return __builtin_clzll(x); } /// The floor of the log base two of n. Undefined if n == 0 template uint16_t floorLog2(T n) { return sizeof(T) * 8 - 1 - leading_zeroes(n); } /// The ceiling of the log base two of n. Undefined if n == 0 template uint16_t ceilLog2(T n) { uint16_t r = floorLog2(n); return n > (((T)1) << r) ? r + 1 : r; } /// The ceiling of the quotient of the division of a by b. I.e. if b /// divides a, then div_ceil(a, b) == a / b. Otherwise, div_ceil(a, b) /// == a / b + 1 template T div_ceil(T a, T b) { T q = a / b; return a % b == 0 ? q : q + 1; } /// Number of bits necessary to encode number n. Undefined if n == /// 0. The following should be true: 2^bitsize(n) - 1 >= n > /// 2^(bitsize(n) - 1) template uint16_t bitsize(T n) { return floorLog2(n) + 1; } inline uint32_t reverse_bits(uint32_t v) { // swap odd and even bits v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); // swap consecutive pairs v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); // swap nibbles ... v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); // swap bytes v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); // swap 2-byte long pairs v = ( v >> 16 ) | ( v << 16); return v; } inline uint64_t reverse_bits(uint64_t v) { v = ((v >> 1) & 0x5555555555555555UL) | ((v & 0x5555555555555555UL) << 1); v = ((v >> 2) & 0x3333333333333333UL) | ((v & 0x3333333333333333UL) << 2); v = ((v >> 4) & 0x0F0F0F0F0F0F0F0FUL) | ((v & 0x0F0F0F0F0F0F0F0FUL) << 4); v = ((v >> 8) & 0x00FF00FF00FF00FFUL) | ((v & 0x00FF00FF00FF00FFUL) << 8); v = ((v >> 16) & 0x0000FFFF0000FFFFUL) | ((v & 0x0000FFFF0000FFFFUL) << 16); v = ( v >> 32 ) | ( v << 32); return v; } uint64_t bogus_sum(void *data, size_t len); template size_t bits_to_bytes(T bits) { return (size_t)((bits / 8) + (bits % 8 != 0)); } template union Tptr { void *v; T *t; }; template T *calloc_align(size_t nmemb, size_t alignment) { Tptr ptr; if(posix_memalign(&ptr.v, alignment, sizeof(T) * nmemb) < 0) throw std::bad_alloc(); return ptr.t; } /* Be pedantic about memory access. Any misaligned access will * generate a BUS error. */ void disabled_misaligned_mem_access(); /* Raison d'etre of this version of mem_copy: It seems we have slow * down due to misaligned cache accesses. glibc memcpy does unaligned * memory accesses and crashes when they are disabled. This version * does only aligned memory access (see above). */ template void mem_copy(char *dest, const char *src, const T &len) { // dumb copying char by char for(T i = (T)0; i < len; ++i) *dest++ = *src++; } /* Slice a large number (total) in almost equal parts. return [start, end) corresponding to the ith part (0 <= i < number_of_slices) */ template std::pair slice(T i, T number_of_slices, T total) { const T slice_size = total / number_of_slices; const T slice_remain = total % number_of_slices; const T start = std::max((T)0, std::min(total, i * slice_size + (i > 0 ? slice_remain : 0))); const T end = std::max((T)0, std::min(total, (i + 1) * slice_size + slice_remain)); return std::make_pair(start, end); } uint64_t random_bits(int length); inline uint64_t random_bits() { return random_bits(64); } // Quote string that could contain shell special characters std::string quote_arg(const std::string& arg); std::streamoff get_file_size(std::istream& is); /// Find the first element for which the predicate p is false. The /// input range [first, last) is assumed to be sorted according to the /// predicate p: p(x) is false and p(y) is true implies x comes after /// y in the input range. (I.e., the elements for which p(x) is true /// come first followed by the elements for which p(x) is false). template ForwardIterator binary_search_first_false(ForwardIterator first, ForwardIterator last, Predicate p) { ForwardIterator it; typename std::iterator_traits::difference_type count, step; count = std::distance(first,last); while(count>0) { it = first; step = count / 2; std::advance(it,step); if(p(*it)) { first = ++it; count -= step + 1; } else count=step; } return first; } /// An integer type which behaves like a random pointer to /// itself. Meaning, with `it(5)`, then `*it == 5` and `*++it == /// 6`. In other words, it is a pointer to an array `a` initialized /// with `a[i] = i`, except the array is not instantiated and does not /// have a fixed size. template class pointer_integer : public std::iterator { T x_; typedef typename std::iterator super; public: typedef T value_type; typedef typename super::difference_type difference_type; typedef typename super::pointer pointer; typedef typename super::reference reference; typedef typename super::iterator_category iterator_category; pointer_integer() : x_(0) { } explicit pointer_integer(T x) : x_(x) { } pointer_integer(const pointer_integer& rhs) : x_(rhs.x_) { } pointer_integer& operator=(const pointer_integer& rhs) { x_ = rhs.x_; return *this; } pointer_integer& operator++() { ++x_; return *this; } pointer_integer operator++(int) { pointer_integer res(*this); ++x_; return res; } pointer_integer& operator--() { --x_; return *this; } pointer_integer operator--(int) { pointer_integer res(*this); --x_; return res; } bool operator==(const pointer_integer& rhs) const { return x_ == rhs.x_; } bool operator!=(const pointer_integer& rhs) const { return x_ != rhs.x_; } bool operator<(const pointer_integer& rhs) const { return x_ < rhs.x_; } bool operator>(const pointer_integer& rhs) const { return x_ > rhs.x_; } bool operator<=(const pointer_integer& rhs) const { return x_ <= rhs.x_; } bool operator>=(const pointer_integer& rhs) const { return x_ >= rhs.x_; } reference operator*() { return x_; } pointer operator->() { return &x_; } // Probably useless difference_type operator-(pointer_integer& rhs) { return x_ - rhs.x_; } pointer_integer operator+(T x) const { return pointer_integer(x_ + x); } pointer_integer operator-(T x) const { return pointer_integer(x_ - x); } pointer_integer& operator+=(T x) { x_ += x; return *this; } pointer_integer& operator-=(T x) { x_ -= x; return *this; } value_type operator[](T i) const { return x_ + i; } }; template pointer_integer operator+(T x, pointer_integer& p) { return pointer_integer(x + *p); } template pointer_integer operator-(T x, pointer_integer& p) { return pointer_integer(x - *p); } } // namespace jellyfish #endif // __MISC_HPP__ Jellyfish-2.2.8/include/jellyfish/offsets_key_value.hpp000066400000000000000000000243331323712541700233300ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_OFFSETS_KEY_VALUE_HPP__ #define __JELLYFISH_OFFSETS_KEY_VALUE_HPP__ #include #include #include #include #include namespace jellyfish { /* A word is whatever aligned type used for atomic operations * (CAS). Typically, a uint64_t. We store pairs of (key, value), in a * bit packed fashion. The key and value can have abritrary size as * long as they each fit in one word. A block is the largest number of * (key, value) pair such that the first key, and only the first, * starts at an aligned word. * * The key 0x0 is not valid. A key which fits completely within one * word is not protected by a "set" bit. A key which straddle the * boundary between two aligned words has a set bit in each parts. * * A value field can have any value and is initialized to 0x0. It has * no "set" bit ever. * * A key is prefixed with a "large" bit. If this bit is 0, the key * field is length key_len (not counting the possible set bits) and * the value field has length val_len. If the large bit has value 1, * the key field is just long enough to encode the number of * reprobing hops to go backward to find the actual key. The * remainder bits is used for the value field. In this scheme, we * assume the length needed to encode the number of reprobes is much * less than the length needed to encode the key. * * The size of the value field, for the normal and large field, is * capped at 64. If there is more bits available, they are wasted. */ /* Offsets holds all the possible offset for a given combination of * key length, value length and reprobe limit. */ template class Offsets { public: // woff: offset in words from beginning of block // boff: offset in bits within that word. Paste large bit. // shift: number of bits stored in first word, or shift to get to beginning of second word // cshift: number of bits stored in last word // mask1: includes the large bit and the set bit if any. // mask2: mask in last word. Contains large and set bit if any. 0 if last word is full // sb_mask[12]: mask for set bit in words 1 to last-1 and in last word, if any. set bit is the // last usable bit of the field. // lb_mask: mask for the large bit. It is the first bit of the key field. // full words: need to copy full words typedef struct { struct key { unsigned int woff, boff, shift, cshift; word mask1, mask2, sb_mask1, sb_mask2, lb_mask; bool full_words; }; struct key key; struct val { unsigned int woff, boff, shift, cshift; word mask1, mask2; }; struct val val; } offset_t; typedef struct { offset_t normal; offset_t large; } offset_pair_t; struct block_info { unsigned int len; unsigned int word_len; }; // Offsets() {} Offsets(unsigned int _key_len, unsigned int _val_len, unsigned int _reprobe_limit) : key_len_(_key_len), val_len_(_val_len), reprobe_limit_(_reprobe_limit), reprobe_len_(bitsize(reprobe_limit_)), lval_len_(std::min(key_len_ + val_len_ - reprobe_len_, (unsigned int)bsizeof(word))), block(compute_offsets()), bld(block.len) { if(reprobe_len_ > bsizeof(word)) { std::ostringstream err; err << "The reprobe_limit (" << reprobe_limit_ << ", " << reprobe_len_ << ") must be encoded in at most one word (" << bsizeof(word) << ")"; throw std::length_error(err.str()); } if(val_len_ > bsizeof(word)) throw std::length_error("Val length must be less than the word size"); if(key_len_ < reprobe_len_) throw std::length_error("Key length must be at least as large as to encode the reprobe_limit"); } ~Offsets() {} unsigned int block_len() const { return block.len; } unsigned int block_word_len() const { return block.word_len; } unsigned int reprobe_len() const { return reprobe_len_; } unsigned int reprobe_limit() const { return reprobe_limit_; } word reprobe_mask() const { return mask(reprobe_len_, 0); } unsigned int key_len() const { return key_len_; } unsigned int val_len() const { return val_len_; } unsigned int lval_len() const { return lval_len_; } word get_max_val(bool large) const { return (((uint64_t)1) << (large ? lval_len_ : val_len_)) - 1; } /// Number of blocks that fit in a given amount of memory. Given an /// amount of memory mem, it returns the number of blocks that fit /// into mem and the actual memory this many block use. std::pair blocks_for_records(size_t nb_records) const { size_t blocks = nb_records / bld; return std::make_pair(blocks, blocks * block.len); } word *word_offset(size_t id, const offset_t **o, const offset_t **lo, word * const base) const { uint64_t q, r; bld.division(id, q, r); word *w = base + (block.word_len * q); *o = &offsets[r].normal; *lo = &offsets[r].large; return w; } private: const unsigned int key_len_, val_len_; const unsigned int reprobe_limit_, reprobe_len_, lval_len_; const block_info block; const jflib::divisor64 bld; // Fast divisor by block.len offset_pair_t offsets[bsizeof(word)]; block_info compute_offsets(); bool add_key_offsets(unsigned int &cword, unsigned int &cboff, unsigned int add, bool& full_words); bool add_val_offsets(unsigned int &cword, unsigned int &cboff, unsigned int add); void set_key_offsets(Offsets::offset_t& key, unsigned int& cword, unsigned int& cboff, unsigned int len); void set_val_offsets(Offsets::offset_t& val, unsigned int& cword, unsigned int& cboff, unsigned int len); word mask(unsigned int length, unsigned int shift) const; }; template bool Offsets::add_key_offsets(unsigned int &cword, unsigned int &cboff, unsigned int add, bool& full_words) { if(cboff + add <= bsizeof(word)) { // Not spilling over next word cboff = (cboff + add) % bsizeof(word); cword += (cboff == 0); return false; } // Span multiple words. Take into account the extra set bit, one in each word size_t wcap = bsizeof(word) - 1; // Word capacity withouth set bit add -= wcap - cboff; // Substract bits stored in first partial word including set bit full_words = add >= wcap; cword += 1 + add / wcap; // Add first word plus any extra complete word cboff = add % wcap; // Extra bits in last word cboff += cboff > 0; // Add set bit in last word if use partial word return true; } template bool Offsets::add_val_offsets(unsigned int &cword, unsigned int &cboff, unsigned int add) { unsigned int ocword = cword; cboff += add; cword += cboff / bsizeof(word); cboff = cboff % bsizeof(word); return cword > ocword && cboff > 0; } template word Offsets::mask(unsigned int length, unsigned int shift) const { if(length) return (((word)-1) >> (bsizeof(word) - length)) << shift; return (word)0; } template void Offsets::set_key_offsets(Offsets::offset_t& offset, unsigned int& cword, unsigned int& cboff, unsigned int len) { unsigned int ocboff; bool full_words; offset.key.woff = cword; ocboff = cboff; offset.key.boff = cboff + 1; offset.key.lb_mask = mask(1, cboff); if(add_key_offsets(cword, cboff, len + 1, full_words)) { // Extra bits in last extra word offset.key.mask1 = mask(bsizeof(word) - ocboff, ocboff); offset.key.mask2 = mask(cboff, 0); offset.key.shift = bsizeof(word) - 1 - ocboff - 1; // -1 for large bit, -1 for set bit offset.key.cshift = cboff ? cboff - 1 : 0; offset.key.sb_mask1 = mask(1, bsizeof(word) - 1); offset.key.sb_mask2 = cboff ? mask(1, cboff - 1) : 0; offset.key.full_words = full_words; } else { offset.key.mask1 = mask(len + 1, ocboff); offset.key.mask2 = 0; offset.key.shift = 0; offset.key.cshift = 0; offset.key.sb_mask1 = 0; offset.key.sb_mask2 = 0; offset.key.full_words = false; } } template void Offsets::set_val_offsets(Offsets::offset_t& offset, unsigned int& cword, unsigned int& cboff, unsigned int len) { unsigned int ocboff; offset.val.woff = cword; offset.val.boff = cboff; ocboff = cboff; if(add_val_offsets(cword, cboff, len)) { offset.val.mask1 = mask(bsizeof(uint64_t) - ocboff, ocboff); offset.val.mask2 = mask(cboff, 0); offset.val.shift = len - cboff; offset.val.cshift = cboff; } else { offset.val.mask1 = mask(len, ocboff); offset.val.mask2 = 0; offset.val.shift = len; offset.val.cshift = 0; } } template typename Offsets::block_info Offsets::compute_offsets() { offset_pair_t *offset = offsets; unsigned int cword = 0; // current word in block unsigned int cboff = 0; // current offset in word unsigned int lcword; // idem for large fields unsigned int lcboff; memset(offsets, '\0', sizeof(offsets)); do { // Save current offsets as starting point for large key lcword = cword; lcboff = cboff; set_key_offsets(offset->normal, cword, cboff, key_len_); set_val_offsets(offset->normal, cword, cboff, val_len_); set_key_offsets(offset->large, lcword, lcboff, reprobe_len_); set_val_offsets(offset->large, lcword, lcboff, lval_len_); offset++; } while(cboff != 0 && cboff < bsizeof(word) - 2); block_info res = { static_cast(offset - offsets), cword + (cboff == 0 ? 0 : 1) }; return res; } } // namespace jellyfish #endif // __OFFSETS_KEY_VALUE_HPP__ Jellyfish-2.2.8/include/jellyfish/parser_common.hpp000066400000000000000000000026131323712541700224540ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_PARSER_COMMON_H__ #define __JELLYFISH_PARSER_COMMON_H__ #ifdef HAVE_CONFIG_H #include #endif #include #include namespace jellyfish { enum file_type { DONE_TYPE , FASTA_TYPE , FASTQ_TYPE #ifdef HAVE_HTSLIB , SAM_TYPE #endif }; struct stream_type { std::unique_ptr standard; #ifdef HAVE_HTSLIB std::unique_ptr sam; #endif bool good() { return (standard && standard->good()) #ifdef HAVE_HTSLIB || (sam && sam->good()) #endif ; } void reset() { standard.reset(); #ifdef HAVE_HTSLIB sam.reset(); #endif } }; } #endif // __JELLYFISH_PARSER_COMMON_H__ Jellyfish-2.2.8/include/jellyfish/rectangular_binary_matrix.hpp000066400000000000000000000310621323712541700250470ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_RECTANGULAR_BINARY_MATRIX_HPP__ #define __JELLYFISH_RECTANGULAR_BINARY_MATRIX_HPP__ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif // Column major representation // // Rectangular matrices on Z/2Z of size _r x _c where 1<=_r<=64 (_c is // not limited) and _r <= _c. I.e., the matrix can be stored as an // array of 64 bit word, each representing a column (the highest 64-_r // bits of each word are set to 0). // // Multiplication between a matrix and vector of size _c x 1 gives a // vector of size _r x 1 stored as one 64 bit word. A matrix with a // NULL _columns pointer behaves like the identity. namespace jellyfish { class RectangularBinaryMatrix { explicit RectangularBinaryMatrix(unsigned int c) : _columns(NULL) , _r(c) , _c(c) { } public: RectangularBinaryMatrix(unsigned int r, unsigned c) : _columns(alloc(r, c)), _r(r), _c(c) { } RectangularBinaryMatrix(const RectangularBinaryMatrix &rhs) : _columns(rhs._columns ? alloc(rhs._r, rhs._c) : NULL) , _r(rhs._r) , _c(rhs._c) { if(_columns) memcpy(_columns, rhs._columns, sizeof(uint64_t) * _c); } RectangularBinaryMatrix(RectangularBinaryMatrix&& rhs) : _columns(rhs._columns) , _r(rhs._r) , _c(rhs._c) { rhs._columns = 0; } // Initialize from raw data. raw must contain at least c words. template RectangularBinaryMatrix(const T &raw, unsigned int r, unsigned c) : _columns(alloc(r, c)), _r(r), _c(c) { for(unsigned int i = 0; i < _c; ++i) _columns[i] = raw[i] & cmask(); } ~RectangularBinaryMatrix() { free(_columns); } static RectangularBinaryMatrix identity(unsigned c) { return RectangularBinaryMatrix(c); } static RectangularBinaryMatrix identity(unsigned r, unsigned c) { RectangularBinaryMatrix res(r, c); res.init_low_identity(); return res; } RectangularBinaryMatrix &operator=(const RectangularBinaryMatrix &rhs) { if(_r != rhs._r || _c != rhs._c) throw std::invalid_argument("RHS matrix dimensions do not match"); memcpy(_columns, rhs._columns, sizeof(uint64_t) * _c); return *this; } RectangularBinaryMatrix& operator=(RectangularBinaryMatrix&& rhs) { if(_r != rhs._r || _c != rhs._c) throw std::invalid_argument("RHS matrix dimensions do not match"); std::swap(_columns, rhs._columns); return *this; } bool operator==(const RectangularBinaryMatrix &rhs) const { if(_r != rhs._r || _c != rhs._c) return false; return !memcmp(_columns, rhs._columns, sizeof(uint64_t) * _c); } bool operator!=(const RectangularBinaryMatrix &rhs) const { return !(*this == rhs); } // Get i-th column. No check on range uint64_t operator[](unsigned int i) const { return _columns ? _columns[i] : ((uint64_t)1 << i); } unsigned int r() const { return _r; } unsigned int c() const { return _c; } // True if every column is zero bool is_zero() const { uint64_t *p = _columns; while(*p == 0 && p < _columns + _c) ++p; return (p - _columns) == _c; } // Randomize the content of the matrix void randomize(uint64_t (*rng)()) { for(unsigned int i = 0; i < _c; ++i) _columns[i] = rng() & cmask(); } //void randomize() { randomize(rng); } // Make and check that the matrix the lower right corner of the // identity. void init_low_identity(bool simplify = true); bool is_low_identity() const; // Left matrix vector multiplication. Type T supports the operator // v[i] to return the i-th 64 bit word of v. template uint64_t times_loop(const T &v) const; #ifdef HAVE_SSE // This SSE implementation only works if the number of columns is // even. template uint64_t times_sse(const T &v) const; #endif #ifdef HAVE_INT128 // Implementation using __int128 template uint64_t times_128(const T& v) const; #endif template inline uint64_t times(const T& v) const { #ifdef HAVE_SSE return times_sse(v); #elif HAVE_INT128 return times_128(v); #else return times_loop(v); #endif } // Return a matrix which is the "pseudo inverse" of this matrix. It // is assumed that there is above this square matrix an identity // block and a zero so as to make the matrix squared. Raise an // exception std::domain_error if the matrix is singular. RectangularBinaryMatrix pseudo_inverse() const; // Return the multiplication of this and rhs. As in pseudo_inverse, // the two matrices are viewed as being squared, padded above by the // identity. RectangularBinaryMatrix pseudo_multiplication(const RectangularBinaryMatrix &rhs) const; // Initialize the object with a pseudo-invertible matrix and return its pseudo-inverse RectangularBinaryMatrix randomize_pseudo_inverse(uint64_t (*rng)()); RectangularBinaryMatrix randomize_pseudo_inverse() { return randomize_pseudo_inverse(random_bits); } // Return the rank of the matrix. The matrix is assumed to be // squared, padded above by the identity. unsigned int pseudo_rank() const; // Display matrix void print(std::ostream &os) const; template void print_vector(std::ostream &os, const T &v) const; // Nb words in vector for multiplication uint64_t nb_words() const { return (_c >> 6) + ((_c & 0x3f) != 0); } // Mask of most significant bit in most significant word of a vector // with _c rows. uint64_t msb() const { int shift = _c & 0x3f; if(shift == 0) shift = sizeof(uint64_t) * 8; return (uint64_t)1 << (shift - 1); } private: // Store column by column. A column may use one word. By // convention, the "unused" bits (most significant bits) of each // column are set to 0. uint64_t * _columns; const unsigned int _r, _c; static uint64_t *alloc(unsigned int r, unsigned int c) __attribute__((malloc)); // Mask for column word (zero msb) uint64_t cmask() const { return std::numeric_limits::max() >> (std::numeric_limits::digits - _r); } // Mask of highest word of a vector with _c rows (Most Significant // Word) uint64_t msw() const { return (msb() << 1) - 1; } // Nb of bits used in highest word of vector with _c rows. uint64_t nb_msb() const { uint64_t nb = _c & 0x3f; return nb ? nb : sizeof(uint64_t) * 8; } // Allow to change the matrix vectors. No check on i. uint64_t & get(unsigned int i) { return _columns[i]; } }; template uint64_t RectangularBinaryMatrix::times_loop(const T &v) const { if(!_columns) return v[0] & cmask(); uint64_t *p = _columns + _c - 1; uint64_t res = 0, x = 0, j = 0; const uint64_t one = (uint64_t)1; for(unsigned int i = 0; i < nb_words(); ++i) { j = sizeof(uint64_t) * 8; x = v[i]; if(i == nb_words() - 1) { x &= msw(); j = nb_msb(); } for( ; j > 7; j -= 8, p -= 8) { res ^= (-(x & one)) & p[0]; x >>= 1; res ^= (-(x & one)) & p[-1]; x >>= 1; res ^= (-(x & one)) & p[-2]; x >>= 1; res ^= (-(x & one)) & p[-3]; x >>= 1; res ^= (-(x & one)) & p[-4]; x >>= 1; res ^= (-(x & one)) & p[-5]; x >>= 1; res ^= (-(x & one)) & p[-6]; x >>= 1; res ^= (-(x & one)) & p[-7]; x >>= 1; } } // Finish the loop switch(j) { case 7: res ^= (-(x & one)) & *p--; x >>= 1; case 6: res ^= (-(x & one)) & *p--; x >>= 1; case 5: res ^= (-(x & one)) & *p--; x >>= 1; case 4: res ^= (-(x & one)) & *p--; x >>= 1; case 3: res ^= (-(x & one)) & *p--; x >>= 1; case 2: res ^= (-(x & one)) & *p--; x >>= 1; case 1: res ^= (-(x & one)) & *p; } return res; } #ifdef HAVE_SSE template uint64_t RectangularBinaryMatrix::times_sse(const T &v) const { if(!_columns) return v[0] & cmask(); #define FFs ((uint64_t)-1) static const uint64_t smear[8] asm("smear") __attribute__ ((aligned(16),used)) = {0, 0, 0, FFs, FFs, 0, FFs, FFs}; typedef uint64_t xmm_t __attribute__((vector_size(16))); uint64_t *p = _columns + _c - 8; // //#ifdef __ICC // register xmm_t acc; // register xmm_t load; // memset(&acc, '\0', 16); // memset(&load, '\0', 16); // #else #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wuninitialized" #endif xmm_t acc = acc ^ acc; // Set acc to 0 xmm_t load = load ^ load; #ifdef __clang__ #pragma clang diagnostic pop #endif // #endif // // Zero out acc // #pragma GCC diagnostic push // #pragma GCC diagnostic ignored "-Wuninitialized" // asm("pxor %0,%0\n\t" : "=x"(acc) : "0"(acc)); // asm("pxor %0,%0\n\t" : "=x"(load) : "0"(load)); // #pragma GCC diagnostic pop // i is the lower 2 bits of x, and an index into the smear array. Compute res ^= smear[i] & p[j]. #define AND_XOR(off) \ asm("movdqa (%[s],%[i]), %[load]\n\t" \ "pand " off "(%[p]),%[load]\n\t" \ "pxor %[load],%[acc]\n\t" \ : [acc]"=&x"(acc) \ : "[acc]"(acc), [i]"r"(i), [p]"r"(p), [s]"r"(smear), [load]"x"(load)) uint64_t i, j = 0, x = 0; for(unsigned int w = 0; w < nb_words(); ++w) { x = v[w]; j = sizeof(uint64_t) * 8; if(w == nb_words() - 1) { x &= msw(); j = nb_msb(); } for( ; j > 7; j -= 8, p -= 8) { i = (x & (uint64_t)0x3) << 4; AND_XOR("0x30"); x >>= 2; i = (x & (uint64_t)0x3) << 4; AND_XOR("0x20"); x >>= 2; i = (x & (uint64_t)0x3) << 4; AND_XOR("0x10"); x >>= 2; i = (x & (uint64_t)0x3) << 4; AND_XOR(""); x >>= 2; } } // Finish loop p = _columns; switch(j) { case 6: i = (x & (uint64_t)0x3) << 4; AND_XOR("0x20"); x >>= 2; case 4: i = (x & (uint64_t)0x3) << 4; AND_XOR("0x10"); x >>= 2; case 2: i = (x & (uint64_t)0x3) << 4; AND_XOR(""); } // Get result out uint64_t res1, res2; asm("movd %[acc], %[res1]\n\t" "psrldq $8, %[acc]\n\t" "movd %[acc], %[res2]\n\t" : [res1]"=r"(res1), [res2]"=r"(res2) : [acc]"x"(acc)); return res1 ^ res2; } #endif // HAVE_SSE #ifdef HAVE_INT128 template uint64_t RectangularBinaryMatrix::times_128(const T &v) const { if(!_columns) return v[0] & cmask(); typedef unsigned __int128 u128; static const u128 smear[4] = { (u128)0, (((u128)1 << 64) - 1) << 64, ((u128)1 << 64) - 1, (u128)-1 }; u128* p = (u128*)(_columns + _c - 2); u128 res = 0; // u128 res = res ^ res; uint64_t j = 0, x = 0; for(unsigned int w = 0; w < nb_words(); ++w) { x = v[w]; j = sizeof(uint64_t) * 8; if(w == nb_words() - 1) { x &= msw(); j = nb_msb(); } for( ; j > 7; j -= 8, p -= 4) { res ^= smear[x & (uint64_t)0x3] & p[ 0]; x >>= 2; res ^= smear[x & (uint64_t)0x3] & p[-1]; x >>= 2; res ^= smear[x & (uint64_t)0x3] & p[-2]; x >>= 2; res ^= smear[x & (uint64_t)0x3] & p[-3]; x >>= 2; } } switch(j) { case 6: res ^= smear[x & (uint64_t)0x3] & *p--; x >>=2; case 4: res ^= smear[x & (uint64_t)0x3] & *p--; x >>=2; case 2: res ^= smear[x & (uint64_t)0x3] & *p; } return (res ^ (res >> 64)) & smear[2]; } #endif // HAVE_INT128 } #endif Jellyfish-2.2.8/include/jellyfish/sam_format.hpp000066400000000000000000000053221323712541700217400ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELYFISH_SAM_FORMAT_H__ #define __JELYFISH_SAM_FORMAT_H__ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_HTSLIB #include namespace jellyfish { // Manage a sam_stream class sam_wrapper { protected: htsFile* m_fd; bam_hdr_t* m_header; bam1_t* m_record; uint8_t* m_seq; uint8_t* m_qual; bool m_eof; public: sam_wrapper() : m_fd(nullptr) , m_header(nullptr) , m_record(nullptr) , m_eof(false) { } sam_wrapper(const char* path) : m_fd(sam_open(path, "r")) , m_header(m_fd ? sam_hdr_read(m_fd) : nullptr) , m_record(m_header ? bam_init1() : nullptr) , m_eof() { } bool fail() const { return !m_fd || !m_header || !m_record; } // True if stream is good bool good() const { return !fail() && !m_eof; } operator bool() const { return !fail(); } // Read next record. Return >= 0 if successful. <0 otherwise. int next() { const auto res = sam_read1(m_fd, m_header, m_record); if(res >= 0) { m_seq = bam_get_seq(m_record); m_qual = bam_get_qual(m_record); } else { m_eof = true; } return res; } // Query the content of the record. Valid only after a successful // next() const bam1_t* record() { return m_record; } ssize_t seq_len() const { return m_record->core.l_qseq; } inline static char decode(int x) { switch(x) { case 1: return 'A'; case 2: return 'C'; case 4: return 'G'; case 8: return 'T'; default: return 'N'; } } char base(ssize_t i) const { return decode(bam_seqi(m_seq, i)); } char qual(ssize_t i) const { return m_qual[i]; } char* qname_str() const { return bam_get_qname(m_record); } size_t qname_length() const { return m_record->core.l_qname; } std::string qname() const { return std::string(qname_str(), qname_length()); } virtual ~sam_wrapper() { if(m_record) bam_destroy1(m_record); if(m_header) bam_hdr_destroy(m_header); if(m_fd) sam_close(m_fd); } }; } // jellyfish #endif // HAVE_HTSLIB #endif // __JELYFISH_SAM_FORMAT_H__ Jellyfish-2.2.8/include/jellyfish/simple_circular_buffer.hpp000066400000000000000000000076511323712541700243250ustar00rootroot00000000000000/* Jellyfish * Copyright (C) 2012 Genome group at University of Maryland. * * 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 . */ #ifndef __SIMPLE_CIRCULAR_BUFFER_H__ #define __SIMPLE_CIRCULAR_BUFFER_H__ #include namespace jellyfish { namespace simple_circular_buffer { // T: type of element in container. D: type of derived class for // CRTP. A: allocator type. template class base { public: explicit base(T* data) : data_(data), front_(0), back_(0), full_(false) { } // Return true if empty bool empty() const { return front_ == back_ && !full(); } // Return true if full bool full() const { return full_; } void clear() { front_ = back_; full_ = false; } // Valid only if empty() is false T& front() { return data_[front_]; } // Valid only if empty() is false T& back() { return data_[prev_index(back_)]; } // Unlike the corresponding method on list or deqeue, push_back may // fail if full() is true. Then false is returned. bool push_back(const T& x) { if(full()) return false; data_[back_] = x; back_ = next_index(back_); full_ = back_ == front_; return true; } bool push_back() { if(full()) return false; back_ = next_index(back_); full_ = back_ == front_; return true; } // Pop an element from the front. It has no effect if empty() is true void pop_front() { if(empty()) return; front_ = next_index(front_); full_ = false; } int size() const { if(full()) return static_cast(this)->capacity(); int s = back_ - front_; return s < 0 ? s + static_cast(this)->capacity() : s; } protected: int next_index(int i) const { return (i + 1) % static_cast(this)->capacity(); } int prev_index(int i) const { return i ? i - 1 : static_cast(this)->capacity() - 1; } T* data() const { return data_; } T* data_; int front_, back_; bool full_; }; template class pre_alloc : public base > { typedef base > super; public: static const int capacityConstant = capa; explicit pre_alloc(T* data) : super(data) { } static int capacity() { return capa; } }; // template > // class fixed : public base, A> { // typedef base, A> super; // public: // explicit fixed(const T v = T()) : super(capa, v) { } // // fixed(const int ignored_size, const T v = T()) : super(capa, v) { } // int capacity() const { return capa; } // }; // template > // class dyn : public base, A> { // typedef base, A> super; // public: // explicit dyn(int size, const T v = T()) : super(size, v), capa_(size) { } // int capacity() const { return capa_; } // int capa_; // }; } } #endif /* __SIMPLE_CIRCULAR_BUFFER_H__ */ Jellyfish-2.2.8/include/jellyfish/sorted_dumper.hpp000066400000000000000000000074051323712541700224700ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_SORTED_DUMPER_HPP__ #define __JELLYFISH_SORTED_DUMPER_HPP__ #include #include #include #include #include #include #include #include #include namespace jellyfish { /// Sorted dumper. Write mers according to the hash order. It /// implements the CRTP to effectively write the k-mer/value pair. template class sorted_dumper : public dumper_t, public thread_exec { protected: typedef typename storage_t::key_type key_type; typedef typename storage_t::region_iterator iterator; typedef typename mer_heap::heap heap_type; typedef typename heap_type::const_item_t heap_item; typedef jellyfish::token_ring token_ring; typedef typename token_ring::token token_type; int nb_threads_; token_ring ring_; const char* file_prefix_; storage_t* ary_; file_header* header_; bool zero_array_; std::ofstream out_; std::pair block_info; // { nb blocks, nb records } public: sorted_dumper(int nb_threads, const char* file_prefix, file_header* header = 0) : nb_threads_(nb_threads), ring_(nb_threads), file_prefix_(file_prefix), header_(header), zero_array_(true) { } bool zero_array() const { return zero_array_; } void zero_array(bool v) { zero_array_ = v; } virtual void _dump(storage_t* ary) { ary_ = ary; block_info = ary_->blocks_for_records(5 * ary_->max_reprobe_offset()); this->open_next_file(file_prefix_, out_); if(header_) header_->write(out_); ring_.reset(); exec_join(nb_threads_); out_.close(); if(zero_array_) ary_->zero_blocks(0, block_info.first); // zero out last group of blocks } virtual void start(const int i) { std::ostringstream buffer; heap_type heap(ary_->max_reprobe_offset()); token_type& token = ring_[i]; size_t count = 0; typename storage_t::key_type key; for(size_t id = i; id * block_info.second < ary_->size(); id += nb_threads_) { // Fill buffer iterator it(ary_, id * block_info.second, (id + 1) * block_info.second, key); heap.fill(it); while(heap.is_not_empty()) { heap_item item = heap.head(); if(item->val_ >= this->min() && item->val_ <= this->max()) static_cast(this)->write_key_value_pair(buffer, item); ++count; heap.pop(); if(it.next()) heap.push(it); } // Write buffer token.wait(); out_.write(buffer.str().data(), buffer.tellp()); token.pass(); buffer.seekp(0); if(id > 0 && zero_array_) ary_->zero_blocks(id * block_info.first, block_info.first); } } }; } // namespace jellyfish { #endif /* __JELLYFISH_SORTED_DUMPER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/stdio_filebuf.hpp000066400000000000000000000126301323712541700224260ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_STDIO_FILEBUF_HPP__ #define __JELLYFISH_STDIO_FILEBUF_HPP__ #include #include #include #include #include #include // Attempt to be (mostly) compatible with GCC ext/stdio_filebuf.h // class. Contains code from stdio_filbuf.hpp and // http://www.mr-edd.co.uk/blog/beginners_guide_streambuf. It is only // meant as a quick replacement when stdio_filebuf is not available. namespace jellyfish { template > class stdio_filebuf : public std::basic_streambuf<_CharT, _Traits> { const int fd_; FILE* const file_; const std::ios_base::openmode mode_; const size_t put_back_; std::vector<_CharT> buffer_; public: // Types: typedef _CharT char_type; typedef _Traits traits_type; typedef typename traits_type::int_type int_type; typedef typename traits_type::pos_type pos_type; typedef typename traits_type::off_type off_type; // typedef std::size_t size_t; /** * @param __fd An open file descriptor. * @param __mode Same meaning as in a standard filebuf. * @param __size Optimal or preferred size of internal buffer, * in chars. * * This constructor associates a file stream buffer with an open * POSIX file descriptor. The file descriptor will be automatically * closed when the stdio_filebuf is closed/destroyed. */ stdio_filebuf(int __fd, std::ios_base::openmode __mode, size_t __size = static_cast(BUFSIZ), size_t put_back = 1) : fd_(__fd), file_(0), mode_(__mode), put_back_(std::max(put_back, (size_t)1)), buffer_(std::max(__size, put_back_) + put_back_) { _CharT* end = buffer_.data() + buffer_.size(); this->setg(end, end, end); } /** * @param __f An open @c FILE*. * @param __mode Same meaning as in a standard filebuf. * @param __size Optimal or preferred size of internal buffer, * in chars. Defaults to system's @c BUFSIZ. * * This constructor associates a file stream buffer with an open * C @c FILE*. The @c FILE* will not be automatically closed when the * stdio_filebuf is closed/destroyed. */ stdio_filebuf(FILE* __f, std::ios_base::openmode __mode, size_t __size = static_cast(BUFSIZ), size_t put_back = 1) : fd_(-1), file_(__f), mode_(__mode), put_back_(std::max(put_back, (size_t)1)), buffer_(std::max(__size, put_back_) + put_back_) { _CharT* end = buffer_.data() + buffer_.size(); this->setg(end, end, end); } /** * Closes the external data stream if the file descriptor constructor * was used. */ virtual ~stdio_filebuf() { if(fd_ != -1) close(fd_); } /** * @return The underlying file descriptor. * * Once associated with an external data stream, this function can be * used to access the underlying POSIX file descriptor. Note that * there is no way for the library to track what you do with the * descriptor, so be careful. */ int fd() { return fd_ != -1 ? fd_ : fileno(file_); } /** * @return The underlying FILE*. * * This function can be used to access the underlying "C" file pointer. * Note that there is no way for the library to track what you do * with the file, so be careful. */ FILE* file() { if(file_) return file_; const char* str_mode; if(mode_ & std::ios_base::app) { str_mode = "a+"; } else if(mode_ & std::ios_base::ate) { str_mode = "a"; } else if(mode_ & std::ios_base::in) { str_mode = (mode_ & std::ios_base::out) ? "r+" : "r"; } else if(mode_ & std::ios_base::out) { str_mode = "w"; } return fdopen(fd_, str_mode); } private: int_type underflow() { if(this->gptr() >= this->egptr()) { _CharT *base = buffer_.data(); _CharT *start = base; if (this->eback() == base) { // Make arrangements for putback characters std::memcpy(base, this->egptr() - put_back_, put_back_ * sizeof(_CharT)); start += put_back_; } // start is now the start of the buffer, proper. // Read from fptr_ in to the provided buffer const ssize_t n = (fd_ != -1) ? read(fd_, start, (buffer_.size() - (start - base)) * sizeof(_CharT)) : std::fread(start, sizeof(_CharT), buffer_.size() - (start - base), file_); if (n <= 0) return _Traits::eof(); // Set buffer pointers this->setg(base, start, start + n); } return _Traits::to_int_type(*this->gptr()); } }; } // namespace jellyfish { #endif // __JELLYFISH_STDIO_FILEBUF_HPP__ Jellyfish-2.2.8/include/jellyfish/storage.hpp000066400000000000000000000020451323712541700212530ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_STORAGE_HPP__ #define __JELLYFISH_STORAGE_HPP__ #include #include #include namespace jellyfish { class storage_t { public: storage_t() {} virtual ~storage_t() {} }; // Entry 0 is used only when switching to a large field extern const size_t *quadratic_reprobes; } #endif // __STORAGE_HPP__ Jellyfish-2.2.8/include/jellyfish/stream_iterator.hpp000066400000000000000000000046771323712541700230300ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __STREAM_ITERATOR_HPP__ #define __STREAM_ITERATOR_HPP__ #include #include #include #include #include #include #include namespace jellyfish { /// Transform an iterator of paths (c string: const char*) into an /// iterator of std::ifstream. Every file is opened and closed in /// turn. The object instantiated with no argument is the end marker. template class stream_iterator : public std::iterator { PathIterator begin_, end_; std::ifstream* stream_; public: stream_iterator(PathIterator begin, PathIterator end) : begin_(begin), end_(end), stream_(0) { if(begin_ != end_) { stream_ = new std::ifstream; open_file(); } } stream_iterator(const stream_iterator& rhs) : begin_(rhs.begin_), end_(rhs.end_), stream_(rhs.stream_) { } stream_iterator() : begin_(), end_(), stream_() { } bool operator==(const stream_iterator& rhs) const { return stream_ == rhs.stream_; } bool operator!=(const stream_iterator& rhs) const { return stream_ != rhs.stream_; } std::ifstream& operator*() { return *stream_; } std::ifstream* operator->() { return stream_; } stream_iterator& operator++() { stream_->close(); if(++begin_ != end_) { open_file(); } else { delete stream_; stream_ = 0; } return *this; } stream_iterator operator++(int) { stream_iterator res(*this); ++*this; return res; } protected: void open_file() { stream_->open(*begin_); if(stream_->fail()) throw std::runtime_error(err::msg() << "Failed to open file '" << *begin_ << "'"); } }; } #endif /* __STREAM_ITERATOR_HPP__ */ Jellyfish-2.2.8/include/jellyfish/stream_manager.hpp000066400000000000000000000151711323712541700226000ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include namespace jellyfish { template class stream_manager { /// A wrapper around an ifstream for a standard file. Standard in /// opposition to a pipe_stream below, but the file may be a regular /// file or a pipe. The file is opened once and notifies the manager /// that it is closed upon destruction. class file_stream : public std::ifstream { stream_manager& manager_; public: file_stream(const char* path, stream_manager& manager) : std::ifstream(path), manager_(manager) { manager_.take_file(); } virtual ~file_stream() { manager_.release_file(); } }; friend class file_stream; /// A wrapper around an ifstream for a "multi pipe". The multi pipe /// are connected to generators (external commands generating /// sequence). They are opened repeatedly, until they are unlinked /// from the file system. class pipe_stream : public std::ifstream { const char* path_; stream_manager& manager_; public: pipe_stream(const char* path, stream_manager& manager) : std::ifstream(path), path_(path), manager_(manager) { } virtual ~pipe_stream() { manager_.release_pipe(path_); } }; friend class pipe_stream; #ifdef HAVE_HTSLIB /// A wrapper around a SAM file wrapper. class sam_stream : public sam_wrapper { const char* path_; stream_manager& manager_; public: sam_stream(const char* path, stream_manager& manager) : sam_wrapper(path) , path_(path) , manager_(manager) { manager_.take_file(); } virtual ~sam_stream() { manager_.release_file(); } }; friend class sam_stream; #endif PathIterator paths_cur_, paths_end_; #ifdef HAVE_HTSLIB PathIterator sams_cur_, sams_end_; #endif int files_open_; const int concurrent_files_; std::list free_pipes_; std::set busy_pipes_; locks::pthread::mutex_recursive mutex_; public: define_error_class(Error); explicit stream_manager(int concurrent_files = 1) : paths_cur_(PathIterator()), paths_end_(PathIterator()) #ifdef HAVE_HTSLIB , sams_cur_(PathIterator()), sams_end_(PathIterator()) #endif , files_open_(0) , concurrent_files_(concurrent_files) { } stream_manager(PathIterator paths_begin, PathIterator paths_end, int concurrent_files = 1) : paths_cur_(paths_begin), paths_end_(paths_end) #ifdef HAVE_HTSLIB , sams_cur_(PathIterator()), sams_end_(PathIterator()) #endif , files_open_(0) , concurrent_files_(concurrent_files) { } stream_manager(PathIterator paths_begin, PathIterator paths_end, PathIterator pipe_begin, PathIterator pipe_end, int concurrent_files = 1) : paths_cur_(paths_begin), paths_end_(paths_end) #ifdef HAVE_HTSLIB , sams_cur_(PathIterator()), sams_end_(PathIterator()) #endif , files_open_(0) , concurrent_files_(concurrent_files) , free_pipes_(pipe_begin, pipe_end) { } void paths(PathIterator paths_begin, PathIterator paths_end) { paths_cur_ = paths_begin; paths_end_ = paths_end; } void pipes(PathIterator pipe_begin, PathIterator pipe_end) { free_pipes_.assign(pipe_begin, pipe_end); } #ifdef HAVE_HTSLIB void sams(PathIterator sam_begin, PathIterator sam_end) { sams_cur_ = sam_begin; sams_end_ = sam_end; } #endif stream_type next() { locks::pthread::mutex_lock lock(mutex_); stream_type res; open_next_file(res); if(res.standard) return res; open_next_pipe(res); if(res.standard) return res; #ifdef HAVE_HTSLIB open_next_sam(res); #endif return res; } int concurrent_files() const { return concurrent_files_; } // Number of pipes available. Not thread safe int concurrent_pipes() const { return free_pipes_.size() + busy_pipes_.size(); } // Number of streams available. Not thread safe int nb_streams() const { return concurrent_files() + concurrent_pipes(); } protected: void open_next_file(stream_type& res) { if(files_open_ >= concurrent_files_) return; while(paths_cur_ != paths_end_) { std::string path = *paths_cur_; ++paths_cur_; res.standard.reset(new file_stream(path.c_str(), *this)); if(res.standard->good()) return; res.standard.reset(); throw std::runtime_error(err::msg() << "Can't open file '" << path << "'"); } } #ifdef HAVE_HTSLIB void open_next_sam(stream_type& res) { if(files_open_ >= concurrent_files_) return; while(sams_cur_ != sams_end_) { std::string path = *sams_cur_; ++sams_cur_; res.sam.reset(new sam_stream(path.c_str(), *this)); if(res.sam->good()) return; res.sam.reset(); throw std::runtime_error(err::msg() << "Can't open SAM file '" << path << '\''); } } #endif void open_next_pipe(stream_type& res) { while(!free_pipes_.empty()) { const char* path = free_pipes_.front(); free_pipes_.pop_front(); res.standard.reset(new pipe_stream(path, *this)); if(res.standard->good()) { busy_pipes_.insert(path); return; } // The pipe failed to open, so it is not marked as busy. This // reset will make us forget about this path. res.standard.reset(); } } void take_file() { locks::pthread::mutex_lock lock(mutex_); ++files_open_; } void release_file() { locks::pthread::mutex_lock lock(mutex_); --files_open_; } // void take_pipe(const char* path) { // locks::pthread::mutex_lock lock(mutex_); // } void release_pipe(const char* path) { locks::pthread::mutex_lock lock(mutex_); if(busy_pipes_.erase(path) == 0) return; // Nothing erased. We forget about that path free_pipes_.push_back(path); } }; } // namespace jellyfish Jellyfish-2.2.8/include/jellyfish/text_dumper.hpp000066400000000000000000000047321323712541700221540ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_TEXT_DUMPER_HPP__ #define __JELLYFISH_TEXT_DUMPER_HPP__ #include namespace jellyfish { template class text_writer { public: void write(std::ostream& out, const Key& key, const Val val) { out << key << " " << val << "\n"; } }; template class text_dumper : public sorted_dumper, storage_t> { typedef sorted_dumper, storage_t> super; text_writer writer; public: static const char* format; text_dumper(int nb_threads, const char* file_prefix, file_header* header = 0) : super(nb_threads, file_prefix, header) { } virtual void _dump(storage_t* ary) { if(super::header_) { super::header_->update_from_ary(*ary); super::header_->format(format); } super::_dump(ary); } void write_key_value_pair(std::ostream& out, typename super::heap_item item) { writer.write(out, item->key_, item->val_); } }; template const char* jellyfish::text_dumper::format = "text/sorted"; template class text_reader { std::istream& is_; char* buffer_; Key key_; Val val_; const RectangularBinaryMatrix m_; const size_t size_mask_; public: text_reader(std::istream& is, file_header* header) : is_(is), buffer_(new char[header->key_len() / 2 + 1]), key_(header->key_len() / 2), m_(header->matrix()), size_mask_(header->size() - 1) { } const Key& key() const { return key_; } const Val& val() const { return val_; } size_t pos() const { return m_.times(key()) & size_mask_; } bool next() { is_ >> key_ >> val_; return is_.good(); } }; } #endif /* __JELLYFISH_TEXT_DUMPER_HPP__ */ Jellyfish-2.2.8/include/jellyfish/thread_exec.hpp000066400000000000000000000026551323712541700220710ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_THREAD_EXEC_HPP__ #define __JELLYFISH_THREAD_EXEC_HPP__ #include #include #include #include #include #include #include #include namespace jellyfish { class thread_exec { struct thread_info { int id; pthread_t thid; thread_exec *self; }; static void *start_routine(void *); std::vector infos; public: define_error_class(Error); thread_exec() {} virtual ~thread_exec() {} virtual void start(int id) = 0; void exec(int nb_threads); void join(); void exec_join(int nb_threads) { exec(nb_threads); join(); } }; } // namespace jellyfish { #endif // __THREAD_EXEC_HPP__ Jellyfish-2.2.8/include/jellyfish/time.hpp000066400000000000000000000044471323712541700205550ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_TIME_HPP__ #define __JELLYFISH_TIME_HPP__ #include #include #include #include class Time { static const suseconds_t max_useconds = 1000000UL; struct timeval tv; public: static const Time zero; explicit Time(bool init = true) { if(init) now(); } Time(time_t sec, suseconds_t usec) { tv.tv_sec = sec; tv.tv_usec = usec; } Time &operator=(const Time &o) { if(&o != this) { tv.tv_sec = o.tv.tv_sec; tv.tv_usec = o.tv.tv_usec; } return *this; } Time & operator-=(const Time &o) { tv.tv_sec -= o.tv.tv_sec; if(o.tv.tv_usec > tv.tv_usec) { tv.tv_usec = (max_useconds + tv.tv_usec) - o.tv.tv_usec; --tv.tv_sec; } else { tv.tv_usec -= o.tv.tv_usec; } return *this; } const Time operator-(const Time &o) const { return Time(*this) -= o; } Time & operator+=(const Time &o) { tv.tv_sec += o.tv.tv_sec; tv.tv_usec += o.tv.tv_usec; if(tv.tv_usec >= max_useconds) { ++tv.tv_sec; tv.tv_usec -= max_useconds; } return *this; } const Time operator+(const Time &o) const { return Time(*this) += o; } bool operator<(const Time& o) const { return tv.tv_sec < o.tv.tv_sec || (tv.tv_sec == o.tv.tv_sec && tv.tv_usec < o.tv.tv_usec); } void now() { gettimeofday(&tv, NULL); } Time elapsed() const { return Time() - *this; } std::string str() const { std::ostringstream res; res << tv.tv_sec << "." << std::setfill('0') << std::setw(6) << std::right << tv.tv_usec; return res.str(); } }; #endif // __TIME_HPP__ Jellyfish-2.2.8/include/jellyfish/token_ring.hpp000066400000000000000000000040121323712541700217420ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_TOKEN_RING_HPP__ #define __JELLYFISH_TOKEN_RING_HPP__ #include #include namespace jellyfish { template class token_ring { public: class token { bool val; cond_t cond; token* next; friend class token_ring; public: void wait() { cond.lock(); while(!val) { cond.wait(); } cond.unlock(); } void pass() { next->cond.lock(); val = false; next->val = true; next->cond.signal(); next->cond.unlock(); } }; protected: typedef std::vector token_list; typedef typename token_list::iterator token_iterator; token_list tokens; void initialize() { if(tokens.size() == 0) return; tokens.front().val = true; tokens.back().next = &tokens.front(); for(size_t i = 1; i < tokens.size(); ++i) { tokens[i].val = false; tokens[i-1].next = &tokens[i]; } } public: token_ring(int nb_tokens) : tokens(nb_tokens) { initialize(); } ~token_ring() { } token& operator[](int i) { return tokens[i]; } void reset() { if(tokens.size() == 0) return; token_iterator it = tokens.begin(); it->val = true; for(++it; it != tokens.end(); ++it) it->val = false; } }; } // namespace jellyfish { #endif Jellyfish-2.2.8/include/jellyfish/whole_sequence_parser.hpp000066400000000000000000000146111323712541700241730ustar00rootroot00000000000000#ifndef __JELLYFISH_WHOLE_SEQUENCE_PARSER_HPP__ #define __JELLYFISH_WHOLE_SEQUENCE_PARSER_HPP__ #include #include #include #include #include #include namespace jellyfish { struct header_sequence_qual { std::string header; std::string seq; std::string qual; }; struct sequence_list { size_t nb_filled; std::vector data; }; template class whole_sequence_parser : public jellyfish::cooperative_pool2, sequence_list> { typedef jellyfish::cooperative_pool2, sequence_list> super; struct stream_status { file_type type; std::string buffer; stream_type stream; stream_status() : type(DONE_TYPE) { } }; cpp_array streams_; StreamIterator& streams_iterator_; size_t files_read_; // nb of files read size_t reads_read_; // nb of reads read public: /// Size is the number of buffers to keep around. It should be /// larger than the number of thread expected to read from this /// class. nb_sequences is the number of sequences to read into a /// buffer. 'begin' and 'end' are iterators to a range of istream. whole_sequence_parser(uint32_t size, uint32_t nb_sequences, uint32_t max_producers, StreamIterator& streams) : super(max_producers, size), streams_(max_producers), streams_iterator_(streams), files_read_(0), reads_read_(0) { for(auto it = super::element_begin(); it != super::element_end(); ++it) { it->nb_filled = 0; it->data.resize(nb_sequences); } for(uint32_t i = 0; i < max_producers; ++i) { streams_.init(i); open_next_file(streams_[i]); } } inline bool produce(uint32_t i, sequence_list& buff) { stream_status& st = streams_[i]; switch(st.type) { case FASTA_TYPE: read_fasta(st, buff); break; case FASTQ_TYPE: read_fastq(st, buff); break; #ifdef HAVE_HTSLIB case SAM_TYPE: read_sam(st, buff); break; #endif case DONE_TYPE: return true; } if(st.stream.good()) return false; // Reach the end of file, close current and try to open the next one open_next_file(st); return false; } size_t nb_files() const { return files_read_; } size_t nb_reads() const { return reads_read_; } protected: void open_next_file(stream_status& st) { st.stream.reset(); st.stream = std::move(streams_iterator_.next()); if(!st.stream.good()) { st.type = DONE_TYPE; return; } ++files_read_; // Update the type of the current file and move past first header // to beginning of sequence. if(st.stream.standard) { switch(st.stream.standard->peek()) { case EOF: return open_next_file(st); case '>': st.type = FASTA_TYPE; break; case '@': st.type = FASTQ_TYPE; break; default: throw std::runtime_error("Unsupported format"); // Better error management } } #ifdef HAVE_HTSLIB else if(st.stream.sam) { st.type = SAM_TYPE; } #endif else { st.type = DONE_TYPE; } } void read_fasta(stream_status& st, sequence_list& buff) { size_t& nb_filled = buff.nb_filled; const size_t data_size = buff.data.size(); auto& stream = *st.stream.standard; for(nb_filled = 0; nb_filled < data_size && stream.peek() != EOF; ++nb_filled) { ++reads_read_; header_sequence_qual& fill_buff = buff.data[nb_filled]; stream.get(); // Skip '>' std::getline(stream, fill_buff.header); fill_buff.seq.clear(); for(int c = stream.peek(); c != '>' && c != EOF; c = stream.peek()) { std::getline(stream, st.buffer); // Wish there was an easy way to combine the fill_buff.seq.append(st.buffer); // two lines avoiding copying } } } void read_fastq(stream_status& st, sequence_list& buff) { size_t& nb_filled = buff.nb_filled; const size_t data_size = buff.data.size(); auto& stream = *st.stream.standard; for(nb_filled = 0; nb_filled < data_size && stream.peek() != EOF; ++nb_filled) { ++reads_read_; header_sequence_qual& fill_buff = buff.data[nb_filled]; stream.get(); // Skip '@' std::getline(stream, fill_buff.header); if(stream.peek() != '+') std::getline(stream, fill_buff.seq); else fill_buff.seq.clear(); while(stream.peek() != '+' && stream.peek() != EOF) { std::getline(stream, st.buffer); // Wish there was an easy way to combine the fill_buff.seq.append(st.buffer); // two lines avoiding copying } if(!stream.good()) throw std::runtime_error("Truncated fastq file"); stream.ignore(std::numeric_limits::max(), '\n'); if(stream.peek() != '+') std::getline(stream, fill_buff.qual); else fill_buff.qual.clear(); while(fill_buff.qual.size() < fill_buff.seq.size() && stream.good()) { std::getline(stream, st.buffer); fill_buff.qual.append(st.buffer); } if(fill_buff.qual.size() != fill_buff.seq.size()) throw std::runtime_error("Invalid fastq file: wrong number of quals"); if(stream.peek() != EOF && stream.peek() != '@') throw std::runtime_error("Invalid fastq file: header missing"); // std::cerr << nb_filled << ": " << fill_buff.seq << '\n' // << nb_filled << ": " << fill_buff.qual << '\n'; } } #ifdef HAVE_HTSLIB void read_sam(stream_status& st, sequence_list& buff) { size_t& nb_filled = buff.nb_filled; const size_t data_size = buff.data.size(); auto& stream = *st.stream.sam; for(nb_filled = 0; nb_filled < data_size && stream.next() >= 0; ++nb_filled) { ++reads_read_; header_sequence_qual& fill_buff = buff.data[nb_filled]; fill_buff.header = stream.qname(); auto& seq = fill_buff.seq; auto& qual = fill_buff.qual; seq.resize(stream.seq_len()); qual.resize(stream.seq_len()); for(ssize_t i = 0; i < stream.seq_len(); ++i) { seq[i] = stream.base(i); qual[i] = stream.qual(i) + '!'; } } } #endif }; } // namespace jellyfish #endif /* __JELLYFISH_WHOLE_SEQUENCE_PARSER_HPP__ */ Jellyfish-2.2.8/jellyfish-2.0.pc.in000066400000000000000000000004261323712541700167020ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Jellyfish Description: A multi-threaded hash based k-mer counter. Version: @PACKAGE_VERSION@ Libs: -L${libdir} -ljellyfish-2.0 -lpthread Cflags: -I${includedir}/jellyfish-@PACKAGE_VERSION@ Jellyfish-2.2.8/jellyfish.spec.in000066400000000000000000000036021323712541700167340ustar00rootroot00000000000000Name: jellyfish Version: @PACKAGE_VERSION@ Release: 1%{?dist} Summary: A fast multi-threaded k-mer counter Group: Applications/Engineering License: GNU GPL URL: http://www.genome.umd.edu/jellyfish Source0: %{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) #BuildRequires: Requires: %{name}-lib = %{version}-%{release} %description Jellyfish is a tool for fast, memory-efficient counting of k-mers in DNA. A k-mer is a substring of length k, and counting the occurrences of all such substrings is a central step in many analyses of DNA sequence. JELLYFISH can count k-mers quickly by using an efficient encoding of a hash table and by exploiting the "compare-and-swap" CPU instruction to increase parallelism. %package lib Summary: Library for %{name} Group: System Environment/Libraries # Requires: %{name}%{?_isa} = %{version}-%{release} %description lib The %{name}-lib package contains libraries required to run %{name} or software using the %{name} library. %package devel Summary: Development files for %{name} Group: Development/Libraries Requires: %{name}-lib%{?_isa} = %{version}-%{release} %description devel The %{name}-devel package contains libraries and header files for developing applications that use %{name}. %prep %setup -q %build %configure --disable-static make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-,root,root,-) %{_bindir}/* %files lib %defattr(-,root,root,-) %doc %{_libdir}/*.so.* %files devel %defattr(-,root,root,-) %doc %{_includedir}/* %{_libdir}/*.so %changelog * Initial version Jellyfish-2.2.8/jellyfish/000077500000000000000000000000001323712541700154525ustar00rootroot00000000000000Jellyfish-2.2.8/jellyfish/backtrace.cc000066400000000000000000000016461323712541700177070ustar00rootroot00000000000000#include #ifndef HAVE_EXECINFO_H void show_backtrace() {} #else #include #include #include #include #include #include void print_backtrace() { void *trace_elems[20]; int trace_elem_count(backtrace(trace_elems, 20)); backtrace_symbols_fd(trace_elems, trace_elem_count, 2); } static void handler() { // Display message of last thrown exception if any try { throw; } catch(const std::exception& e) { int status; size_t n = 0; char *name = abi::__cxa_demangle(typeid(e).name(), 0, &n, &status); std::cerr << "terminate called after throwing an instance of '" << (status < 0 ? "UNKNOWN" : name) << "'\n what(): " << e.what() << "\n"; if(n) free(name); } catch(...) {} print_backtrace(); abort(); } void show_backtrace() { std::set_terminate(handler); } #endif Jellyfish-2.2.8/jellyfish/dbg.cc000066400000000000000000000032701323712541700165170ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_SYS_SYSCALL_H #include #endif namespace dbg { pthread_mutex_t print_t::_lock = PTHREAD_MUTEX_INITIALIZER; volatile pid_t print_t::_print_tid = 0; #ifdef DEBUG Time _tic_time; #endif void tic() { #ifdef DEBUG _tic_time.now(); #endif } Time toc() { #ifdef DEBUG Time t; return t - _tic_time; #else return Time::zero; #endif } #ifdef SYS_gettid pid_t gettid() { return (pid_t)syscall(SYS_gettid); } #else pid_t gettid() { return getpid(); } #endif int print_t::set_signal(int signum) { struct sigaction act; memset(&act, '\0', sizeof(act)); act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; return sigaction(signum, &act, 0); } void print_t::signal_handler(int signum, siginfo_t *info, void *context) { #ifdef HAVE_SI_INT if(info->si_code != SI_QUEUE) return; _print_tid = info->si_int; #endif } } Jellyfish-2.2.8/jellyfish/dbg.hpp000066400000000000000000000076371323712541700167340ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __DBG_HPP__ #define __DBG_HPP__ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace dbg { pid_t gettid(); class stringbuf : public std::stringbuf { public: stringbuf() : std::stringbuf(std::ios_base::out) { } explicit stringbuf(const std::string &str) : std::stringbuf(str, std::ios_base::out) { } bool end_is_space() { if(pptr() == pbase()) return true; return isspace(*(pptr() - 1)); } friend class print_t; }; class str { const char *_s; const size_t _l; public: str(const char *s, size_t len) : _s(s), _l(len) {} friend class print_t; }; class xspace { }; class no_flush { }; class print_t { static pthread_mutex_t _lock; static volatile pid_t _print_tid; stringbuf _strbuf; std::ostream _buf; bool _flush; public: print_t(const char *file, const char *function, int line) : _buf(&_strbuf), _flush(true) { const char *file_basename = strrchr(file, '/'); if(!file_basename) file_basename = file; _buf << pthread_self() << "/" << gettid() << ":" << file_basename << ":" << function << ":" << line << ": "; } ~print_t() { if(_print_tid == 0 || gettid() == _print_tid) { pthread_mutex_lock(&_lock); std::cerr.write(_strbuf.pbase(), _strbuf.pptr() - _strbuf.pbase()); if(_flush) std::cerr << std::endl; else std::cerr << "\n"; pthread_mutex_unlock(&_lock); } } static int set_signal(int signum = SIGUSR1); static void signal_handler(int signum, siginfo_t *info, void *context); static pid_t print_tid() { return _print_tid; } static void print_tid(pid_t new_tid) { _print_tid = new_tid; } print_t & operator<<(const char *a[]) { for(int i = 0; a[i]; i++) _buf << (i ? "\n" : "") << a[i]; return *this; } print_t & operator<<(const std::exception &e) { _buf << e.what(); return *this; } print_t & operator<<(const str &ss) { _buf.write(ss._s, ss._l); return *this; } print_t & operator<<(const xspace &xs) { if(!_strbuf.end_is_space()) _buf << " "; return *this; } print_t &operator<<(const no_flush &nf) { _flush = false; return *this; } print_t & operator<<(const Time &t) { _buf << t.str(); return *this; } template print_t & operator<<(const T &x) { _buf << x; return *this; } }; class no_print_t { public: no_print_t() {} template no_print_t & operator<<(const T &x) { return *this; } }; void tic(); Time toc(); } #ifdef DEBUG #define DBG if(1) dbg::print_t(__FILE__, __FUNCTION__, __LINE__) #define NFDBG if(1) dbg::print_t(__FILE__, __FUNCTION__, __LINE__) << dbg::no_flush() #define V(v) dbg::xspace() << #v ":" << v #else #define DBG if(1) dbg::no_print_t() #define NFDBG if(1) dbg::no_print_t() #define V(v) v #endif #endif /* __DBG_HPP__ */ Jellyfish-2.2.8/jellyfish/fastq2sam.cc000066400000000000000000000027411323712541700176660ustar00rootroot00000000000000#include #include #include #include int main(int argc, char* argv[]) { const std::string ext(".fastq"); const std::string out_ext(".sam"); fastq2sam_cmdline args(argc, argv); for(const auto& path : args.fastq_arg) { if(path.size() < ext.size() || path.substr(path.size() - ext.size()) != ext) fastq2sam_cmdline::error() << "Input must have '" << ext << "' extension"; const std::string out_path = path.substr(0, path.size() - ext.size()) + out_ext; std::ifstream is(path); if(!is.good()) fastq2sam_cmdline::error() << "Failed to open '" << path << '\''; std::ofstream os(out_path); if(!os.good()) fastq2sam_cmdline::error() << "Failed to open '" << out_path << '\''; // os << "@PG\tID:fastq2sam\tPN:fastq2sam\n"; std::string name, seq, quals; char c = is.get(); while(c == '@') { std::getline(is, name); std::getline(is, seq); if((c = is.get()) != '+') break; is.ignore(std::numeric_limits::max(), '\n'); std::getline(is, quals); os << name << "\t4\t*\t0\t0\t*\t*\t0\t0\t" << seq << '\t' << quals << '\n'; c = is.get(); } if(c != EOF) fastq2sam_cmdline::error() << "Input fastq file badly formatted. Unexpected characters '" << c << "' at position " << is.tellg(); if(!os.good()) fastq2sam_cmdline::error() << "Error while writing to file '" << out_path << '\''; } return 0; } Jellyfish-2.2.8/jellyfish/fastq2sam_cmdline.yaggo000066400000000000000000000002251323712541700220750ustar00rootroot00000000000000purpose "Convert a fastq file to a bare SAM file" package "fastq2sam" arg("fastq") { description "Fastq files" string; multiple; at_least 1 } Jellyfish-2.2.8/jellyfish/fstream_default.hpp000066400000000000000000000047231323712541700213360ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_FSTREAM_WITH_DEFAULT_HPP__ #define __JELLYFISH_FSTREAM_WITH_DEFAULT_HPP__ #include #include template class fstream_default : public Base { typedef Base super; static std::streambuf* open_file(const char* str, std::ios_base::openmode mode) { std::filebuf* fb = new std::filebuf; return fb->open(str, mode); } static std::streambuf* get_streambuf(const char* str, Base& def, std::ios_base::openmode mode) { return (str != 0) ? open_file(str, mode) : def.rdbuf(); } static std::streambuf* get_streambuf(const char* str, std::streambuf* buf, std::ios_base::openmode mode) { return (str != 0) ? open_file(str, mode) : buf; } bool do_close; public: fstream_default(const char* str, Base& def, std::ios_base::openmode mode = def_mode) : Base(get_streambuf(str, def, mode)), do_close(str != 0) { if(Base::rdbuf() == 0) Base::setstate(std::ios_base::badbit); } fstream_default(const char* str, std::streambuf* def, std::ios_base::openmode mode = def_mode) : Base(get_streambuf(str, def, mode)), do_close(str != 0) { if(Base::rdbuf() == 0) Base::setstate(std::ios_base::badbit); } ~fstream_default() { if(do_close) { delete Base::rdbuf(0); do_close = false; } } // Close is a noop at this point as GCC 4.4 has a problem with // Base::rdbuf in methods (breaks strict aliasing). Beats me! I // think it is a false positive. void close() {} }; typedef fstream_default ofstream_default; typedef fstream_default ifstream_default; #endif // __JELLYFISH_FSTREAM_WITH_DEFAULT_HPP__ Jellyfish-2.2.8/jellyfish/generate_sequence.cc000066400000000000000000000131231323712541700214430ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include namespace err = jellyfish::err; class rDNAg_t { public: rDNAg_t(CRandomMersenne *_rng) : rng(_rng), i(15), buff(0) {} char letter() { i = (i+1) % 16; if(i == 0) buff = rng->BRandom(); char res = letters[buff & 0x3]; buff >>= 2; return res; } char qual_Illumina() { return rng->IRandom(66, 104); } private: CRandomMersenne *rng; int i; uint32_t buff; static const char letters[4]; }; const char rDNAg_t::letters[4] = { 'A', 'C', 'G', 'T' }; // Output matrix // Generate matrices // uint64_t lines[64]; // for(unsigned int j = 0; j < args.mer_arg.size(); j++) { // if(args.mer_arg[j] <= 0 || args.mer_arg[j] > 31) // die << "Mer size (" << args.mer_arg[j] << ") must be between 1 and 31."; // int matrix_size = args.mer_arg[j] << 1; // SquareBinaryMatrix mat(matrix_size), inv(matrix_size); // while(true) { // for(int i = 0; i < matrix_size; i++) // lines[i] = (uint64_t)rng.BRandom() | ((uint64_t)rng.BRandom() << 32); // mat = SquareBinaryMatrix(lines, matrix_size); // try { // inv = mat.inverse(); // break; // } catch(SquareBinaryMatrix::SingularMatrix &e) {} // } // char path[4096]; // int len = snprintf(path, sizeof(path), "%s_matrix_%d", args.output_arg, // args.mer_arg[j]); // if(len < 0) // die << "Error creating the matrix file '" << path << "'" << err::no; // if((unsigned int)len >= sizeof(path)) // die << "Output prefix too long '" << args.output_arg << "'"; // std::ofstream fd(path); // if(!fd.good()) // die << "Can't open matrix file '" << path << "'" << err::no; // if(args.verbose_flag) // std::cout << "Creating matrix file '" << path << "'\n"; // mat.dump(&fd); // if(!fd.good()) // die << "Error while writing matrix '" << path << "'" << err::no; // fd.close(); // } void create_path(char *path, unsigned int path_size, const char *ext, bool many, int i, const char *output_arg) { int len; if(many) len = snprintf(path, path_size, "%s_%d.%s", output_arg, i, ext); else len = snprintf(path, path_size, "%s.%s", output_arg, ext); if(len < 0) die(err::msg() << "Error creating the fasta file '" << path << "': " << err::no); if((unsigned int)len >= path_size) die(err::msg() << "Output prefix too long '" << output_arg << "'"); } generate_sequence_args args; void output_fastq(size_t length, const char* path, CRandomMersenne& rng) { rDNAg_t rDNAg(&rng); std::ofstream fd(path); if(!fd.good()) die(err::msg() << "Can't open fasta file '" << path << "': " << jellyfish::err::no); if(args.verbose_flag) std::cout << "Creating fastq file '" << path << "'\n"; size_t total_len = 0; unsigned long read_id = 0; while(total_len < length) { fd << "@read_" << (read_id++) << "\n"; int base; for(base = 0; base < 70 && total_len < length; base++, total_len++) fd << rDNAg.letter(); fd << "\n+\n"; for(int j = 0; j < base; j++) fd << rDNAg.qual_Illumina(); fd << "\n"; } if(!fd.good()) die(err::msg() << "Error while writing fasta file '" << path << "': " << jellyfish::err::no); fd.close(); } void output_fasta(size_t length, const char* path, CRandomMersenne& rng) { rDNAg_t rDNAg(&rng); std::ofstream fd(path); if(!fd.good()) die(err::msg() << "Can't open fasta file '" << path << "': " << jellyfish::err::no); if(args.verbose_flag) std::cout << "Creating fasta file '" << path << "'\n"; size_t read_length = args.read_length_given ? args.read_length_arg : length; size_t total_len = 0; size_t read = 0; long rid = 0; fd << ">read" << ++rid << "\n"; while(total_len < length) { for(int base = 0; base < 70 && total_len < length && read < read_length; base++) { fd << rDNAg.letter(); total_len++; read++; } fd << "\n"; if(read >= read_length) { fd << ">read" << ++rid << "\n"; read = 0; } } if(!fd.good()) die(err::msg() << "Error while writing fasta file '" << path << "': " << jellyfish::err::no); fd.close(); } int main(int argc, char *argv[]) { args.parse(argc, argv); if(args.verbose_flag) std::cout << "Seed: " << args.seed_arg << "\n"; CRandomMersenne rng(args.seed_arg); // Output sequence char path[4096]; bool many = args.length_arg.size() > 1; for(unsigned int i = 0; i < args.length_arg.size(); ++i) { if(args.fastq_flag) { create_path(path, sizeof(path), "fq", many, i, args.output_arg); output_fastq(args.length_arg[i], path, rng); } else { create_path(path, sizeof(path), "fa", many, i, args.output_arg); output_fasta(args.length_arg[i], path, rng); } } return 0; } Jellyfish-2.2.8/jellyfish/generate_sequence_cmdline.yaggo000066400000000000000000000013561323712541700236640ustar00rootroot00000000000000purpose "Generate randome sequence of given lengths." package "generate_sequence" output "generate_sequence_cmdline.hpp" name "generate_sequence_args" option("seed", "s") { description "Seed" long; required } option("mer", "m") { description "Mer length. Generate matrix of size 2*length" uint32; multiple } option("output", "o") { description "Output prefix" c_string; default "output" } option("fastq", "q") { description "Generate fastq file" flag; off } option("read-length", "r") { description "Read length for fasta format (default=size of sequence)" uint32 } option("verbose", "v") { description "Be verbose" flag; off } arg("length") { description "Length of sequence to generate" uint64; multiple; at_least 1 } Jellyfish-2.2.8/jellyfish/merge_files.cc000066400000000000000000000121711323712541700202440ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include namespace err = jellyfish::err; using jellyfish::file_header; using jellyfish::RectangularBinaryMatrix; using jellyfish::mer_dna; using jellyfish::cpp_array; typedef std::unique_ptr binary_reader_ptr; typedef std::unique_ptr text_reader_ptr; struct file_info { std::ifstream is; file_header header; file_info(const char* path) : is(path), header(is) { } }; typedef std::unique_ptr matrix_ptr; template void do_merge(cpp_array& files, std::ostream& out, writer_type& writer, uint64_t min, uint64_t max) { cpp_array readers(files.size()); typedef jellyfish::mer_heap::heap heap_type; typedef typename heap_type::const_item_t heap_item; heap_type heap(files.size()); for(size_t i = 0; i < files.size(); ++i) { readers.init(i, files[i].is, &files[i].header); if(readers[i].next()) heap.push(readers[i]); } heap_item head = heap.head(); mer_dna key; while(heap.is_not_empty()) { key = head->key_; uint64_t sum = 0; do { sum += head->val_; heap.pop(); if(head->it_->next()) heap.push(*head->it_); head = heap.head(); } while(head->key_ == key && heap.is_not_empty()); if(sum >= min && sum <= max) writer.write(out, key, sum); } } // Merge files. Throws an error if unsuccessful. void merge_files(std::vector input_files, const char* out_file, file_header& out_header, uint64_t min, uint64_t max) { unsigned int key_len = 0; size_t max_reprobe_offset = 0; size_t size = 0; unsigned int out_counter_len = std::numeric_limits::max(); std::string format; matrix_ptr matrix; cpp_array files(input_files.size()); // create an iterator for each hash file for(size_t i = 0; i < files.size(); i++) { files.init(i, input_files[i]); if(!files[i].is.good()) throw MergeError(err::msg() << "Failed to open input file '" << input_files[i] << "'"); file_header& h = files[i].header; if(i == 0) { key_len = h.key_len(); max_reprobe_offset = h.max_reprobe_offset(); size = h.size(); matrix.reset(new RectangularBinaryMatrix(h.matrix())); out_header.size(size); out_header.key_len(key_len); format = h.format(); out_header.matrix(*matrix); out_header.max_reprobe(h.max_reprobe()); size_t reprobes[h.max_reprobe() + 1]; h.get_reprobes(reprobes); out_header.set_reprobes(reprobes); out_counter_len = std::min(out_counter_len, h.counter_len()); } else { if(format != h.format()) throw MergeError(err::msg() << "Can't merge files with different formats (" << format << ", " << h.format() << ")"); if(h.key_len() != key_len) throw MergeError(err::msg() << "Can't merge hashes of different key lengths (" << key_len << ", " << h.key_len() << ")"); if(h.max_reprobe_offset() != max_reprobe_offset) throw MergeError("Can't merge hashes with different reprobing strategies"); if(h.size() != size) throw MergeError(err::msg() << "Can't merge hash with different size (" << size << ", " << h.size() << ")"); if(h.matrix() != *matrix) throw MergeError("Can't merge hash with different hash function"); } } mer_dna::k(key_len / 2); std::ofstream out(out_file); if(!out.good()) throw MergeError(err::msg() << "Can't open out file '" << out_file << "'"); out_header.format(format); if(!format.compare(binary_dumper::format)) { out_header.counter_len(out_counter_len); out_header.write(out); binary_writer writer(out_counter_len, key_len); do_merge(files, out, writer, min, max); } else if(!format.compare(text_dumper::format)) { out_header.write(out); text_writer writer; do_merge(files, out, writer, min, max); } else { throw MergeError(err::msg() << "Unknown format '" << format << "'"); } out.close(); } Jellyfish-2.2.8/jellyfish/merge_files.hpp000066400000000000000000000021471323712541700204500ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifndef __JELLYFISH_MERGE_FILES_HPP__ #define __JELLYFISH_MERGE_FILES_HPP__ #include #include #include define_error_class(MergeError); /// Merge files. Throw a MergeError in case of error. void merge_files(std::vector input_files, const char* out_file, jellyfish::file_header& h, uint64_t min, uint64_t max); #endif /* __JELLYFISH_MERGE_FILES_HPP__ */ Jellyfish-2.2.8/jellyfish/mersenne.cpp000066400000000000000000000141511323712541700177740ustar00rootroot00000000000000/************************** mersenne.cpp ********************************** * Author: Agner Fog * Date created: 2001 * Last modified: 2008-11-16 * Project: randomc.h * Platform: Any C++ * Description: * Random Number generator of type 'Mersenne Twister' * * This random number generator is described in the article by * M. Matsumoto & T. Nishimura, in: * ACM Transactions on Modeling and Computer Simulation, * vol. 8, no. 1, 1998, pp. 3-30. * Details on the initialization scheme can be found at * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html * * Further documentation: * The file ran-instructions.pdf contains further documentation and * instructions. * * Copyright 2001-2008 by Agner Fog. * GNU General Public License http://www.gnu.org/licenses/gpl.html *******************************************************************************/ #include void CRandomMersenne::Init0(int seed) { // Seed generator const uint32_t factor = 1812433253UL; mt[0]= seed; for (mti=1; mti < MERS_N; mti++) { mt[mti] = (factor * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); } } void CRandomMersenne::RandomInit(int seed) { // Initialize and seed Init0(seed); // Randomize some more for (int i = 0; i < 37; i++) BRandom(); } void CRandomMersenne::RandomInitByArray(int const seeds[], int NumSeeds) { // Seed by more than 32 bits int i, j, k; // Initialize Init0(19650218); if (NumSeeds <= 0) return; // Randomize mt[] using whole seeds[] array i = 1; j = 0; k = (MERS_N > NumSeeds ? MERS_N : NumSeeds); for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + (uint32_t)seeds[j] + j; i++; j++; if (i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;} if (j >= NumSeeds) j=0;} for (k = MERS_N-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i; if (++i >= MERS_N) {mt[0] = mt[MERS_N-1]; i=1;}} mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array // Randomize some more mti = 0; for (int i = 0; i <= MERS_N; i++) BRandom(); } uint32_t CRandomMersenne::BRandom() { // Generate 32 random bits uint32_t y; if (mti >= MERS_N) { // Generate MERS_N words at one time const uint32_t LOWER_MASK = (1LU << MERS_R) - 1; // Lower MERS_R bits const uint32_t UPPER_MASK = 0xFFFFFFFF << MERS_R; // Upper (32 - MERS_R) bits static const uint32_t mag01[2] = {0, MERS_A}; int kk; for (kk=0; kk < MERS_N-MERS_M; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+MERS_M] ^ (y >> 1) ^ mag01[y & 1];} for (; kk < MERS_N-1; kk++) { y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK); mt[kk] = mt[kk+(MERS_M-MERS_N)] ^ (y >> 1) ^ mag01[y & 1];} y = (mt[MERS_N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK); mt[MERS_N-1] = mt[MERS_M-1] ^ (y >> 1) ^ mag01[y & 1]; mti = 0; } y = mt[mti++]; // Tempering (May be omitted): y ^= y >> MERS_U; y ^= (y << MERS_S) & MERS_B; y ^= (y << MERS_T) & MERS_C; y ^= y >> MERS_L; return y; } double CRandomMersenne::Random() { // Output random float number in the interval 0 <= x < 1 // Multiply by 2^(-32) return (double)BRandom() * (1./(65536.*65536.)); } int CRandomMersenne::IRandom(int min, int max) { // Output random integer in the interval min <= x <= max // Relative error on frequencies < 2^-32 if (max <= min) { if (max == min) return min; else return 0x80000000; } // Multiply interval with random and truncate int r = int((double)(uint32_t)(max - min + 1) * Random() + min); if (r > max) r = max; return r; } int CRandomMersenne::IRandomX(int min, int max) { // Output random integer in the interval min <= x <= max // Each output value has exactly the same probability. // This is obtained by rejecting certain bit values so that the number // of possible bit values is divisible by the interval length if (max <= min) { if (max == min) return min; else return 0x80000000; } #ifdef INT64_SUPPORTED // 64 bit integers available. Use multiply and shift method uint32_t interval; // Length of interval uint64_t longran; // Random bits * interval uint32_t iran; // Longran / 2^32 uint32_t remainder; // Longran % 2^32 interval = uint32_t(max - min + 1); if (interval != LastInterval) { // Interval length has changed. Must calculate rejection limit // Reject when remainder >= 2^32 / interval * interval // RLimit will be 0 if interval is a power of 2. No rejection then RLimit = uint32_t(((uint64_t)1 << 32) / interval) * interval - 1; LastInterval = interval; } do { // Rejection loop longran = (uint64_t)BRandom() * interval; iran = (uint32_t)(longran >> 32); remainder = (uint32_t)longran; } while (remainder > RLimit); // Convert back to signed and return result return (int32_t)iran + min; #else // 64 bit integers not available. Use modulo method uint32_t interval; // Length of interval uint32_t bran; // Random bits uint32_t iran; // bran / interval uint32_t remainder; // bran % interval interval = uint32_t(max - min + 1); if (interval != LastInterval) { // Interval length has changed. Must calculate rejection limit // Reject when iran = 2^32 / interval // We can't make 2^32 so we use 2^32-1 and correct afterwards RLimit = (uint32_t)0xFFFFFFFF / interval; if ((uint32_t)0xFFFFFFFF % interval == interval - 1) RLimit++; } do { // Rejection loop bran = BRandom(); iran = bran / interval; remainder = bran % interval; } while (iran >= RLimit); // Convert back to signed and return result return (int32_t)remainder + min; #endif } Jellyfish-2.2.8/jellyfish/randomc.h000066400000000000000000000165641323712541700172620ustar00rootroot00000000000000/***************************** randomc.h ********************************** * Author: Agner Fog * Date created: 1997 * Last modified: 2008-11-16 * Project: randomc.h * Source URL: www.agner.org/random * * Description: * This header file contains class declarations and other definitions for the * randomc class library of uniform random number generators in C++ language. * * Overview of classes: * ==================== * * class CRandomMersenne: * Random number generator of type Mersenne twister. * Source file mersenne.cpp * * class CRandomMother: * Random number generator of type Mother-of-All (Multiply with carry). * Source file mother.cpp * * class CRandomSFMT: * Random number generator of type SIMD-oriented Fast Mersenne Twister. * The class definition is not included here because it is not * portable to all platforms. See sfmt.h and sfmt.cpp for details. * * Member functions (methods): * =========================== * * All these classes have identical member functions: * * Constructor(int seed): * The seed can be any integer. The time may be used as seed. * Executing a program twice with the same seed will give the same sequence * of random numbers. A different seed will give a different sequence. * * void RandomInit(int seed); * Re-initializes the random number generator with a new seed. * * void RandomInitByArray(int const seeds[], int NumSeeds); * In CRandomMersenne and CRandomSFMT only: Use this function if you want * to initialize with a seed with more than 32 bits. All bits in the seeds[] * array will influence the sequence of random numbers generated. NumSeeds * is the number of entries in the seeds[] array. * * double Random(); * Gives a floating point random number in the interval 0 <= x < 1. * The resolution is 32 bits in CRandomMother and CRandomMersenne, and * 52 bits in CRandomSFMT. * * int IRandom(int min, int max); * Gives an integer random number in the interval min <= x <= max. * (max-min < MAXINT). * The precision is 2^-32 (defined as the difference in frequency between * possible output values). The frequencies are exact if max-min+1 is a * power of 2. * * int IRandomX(int min, int max); * Same as IRandom, but exact. In CRandomMersenne and CRandomSFMT only. * The frequencies of all output values are exactly the same for an * infinitely long sequence. (Only relevant for extremely long sequences). * * uint32_t BRandom(); * Gives 32 random bits. * * * Example: * ======== * The file EX-RAN.CPP contains an example of how to generate random numbers. * * * Library version: * ================ * Optimized versions of these random number generators are provided as function * libraries in randoma.zip. These function libraries are coded in assembly * language and support only x86 platforms, including 32-bit and 64-bit * Windows, Linux, BSD, Mac OS-X (Intel based). Use randoma.h from randoma.zip * * * Non-uniform random number generators: * ===================================== * Random number generators with various non-uniform distributions are * available in stocc.zip (www.agner.org/random). * * * Further documentation: * ====================== * The file ran-instructions.pdf contains further documentation and * instructions for these random number generators. * * Copyright 1997-2008 by Agner Fog. * GNU General Public License http://www.gnu.org/licenses/gpl.html *******************************************************************************/ #ifndef RANDOMC_H #define RANDOMC_H // Define integer types with known size: int32_t, uint32_t, int64_t, uint64_t. // If this doesn't work then insert compiler-specific definitions here: #if defined(__GNUC__) // Compilers supporting C99 or C++0x have inttypes.h defining these integer types #include #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers #elif defined(_WIN16) || defined(__MSDOS__) || defined(_MSDOS) // 16 bit systems use long int for 32 bit integer typedef signed long int int32_t; typedef unsigned long int uint32_t; #elif defined(_MSC_VER) // Microsoft have their own definition typedef signed __int32 int32_t; typedef unsigned __int32 uint32_t; typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers #else // This works with most compilers typedef signed int int32_t; typedef unsigned int uint32_t; typedef long long int64_t; typedef unsigned long long uint64_t; #define INT64_SUPPORTED // Remove this if the compiler doesn't support 64-bit integers #endif /*********************************************************************** System-specific user interface functions ***********************************************************************/ void EndOfProgram(void); // System-specific exit code (userintf.cpp) void FatalError(const char *ErrorText);// System-specific error reporting (userintf.cpp) #if defined(__cplusplus) // class definitions only in C++ /*********************************************************************** Define random number generator classes ***********************************************************************/ class CRandomMersenne { // Encapsulate random number generator // Choose which version of Mersenne Twister you want: #if 0 // Define constants for type MT11213A: #define MERS_N 351 #define MERS_M 175 #define MERS_R 19 #define MERS_U 11 #define MERS_S 7 #define MERS_T 15 #define MERS_L 17 #define MERS_A 0xE4BD75F5 #define MERS_B 0x655E5280 #define MERS_C 0xFFD58000 #else // or constants for type MT19937: #define MERS_N 624 #define MERS_M 397 #define MERS_R 31 #define MERS_U 11 #define MERS_S 7 #define MERS_T 15 #define MERS_L 18 #define MERS_A 0x9908B0DF #define MERS_B 0x9D2C5680 #define MERS_C 0xEFC60000 #endif public: CRandomMersenne(int seed) { // Constructor RandomInit(seed); LastInterval = 0;} void RandomInit(int seed); // Re-seed void RandomInitByArray(int const seeds[], int NumSeeds); // Seed by more than 32 bits int IRandom (int min, int max); // Output random integer int IRandomX(int min, int max); // Output random integer, exact double Random(); // Output random float uint32_t BRandom(); // Output random bits private: void Init0(int seed); // Basic initialization procedure uint32_t mt[MERS_N]; // State vector int mti; // Index into mt uint32_t LastInterval; // Last interval length for IRandomX uint32_t RLimit; // Rejection limit used by IRandomX }; class CRandomMother { // Encapsulate random number generator public: void RandomInit(int seed); // Initialization int IRandom(int min, int max); // Get integer random number in desired interval double Random(); // Get floating point random number uint32_t BRandom(); // Output random bits CRandomMother(int seed) { // Constructor RandomInit(seed);} protected: uint32_t x[5]; // History buffer }; #endif // __cplusplus #endif // RANDOMC_H Jellyfish-2.2.8/lib/000077500000000000000000000000001323712541700142275ustar00rootroot00000000000000Jellyfish-2.2.8/lib/allocators_mmap.cc000066400000000000000000000061431323712541700177170ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif #ifdef HAVE_VALGRIND #include // TODO: this should really come from the valgrind switch // --redzone-size. Don't know how to get access to that yet! static size_t redzone_size = 128; #endif void *allocators::mmap::realloc(size_t new_size) { void *new_ptr = MAP_FAILED; const size_t asize = new_size #ifdef HAVE_VALGRIND + 2 * redzone_size #endif ; if(ptr_ == MAP_FAILED) { new_ptr = ::mmap(NULL, asize, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); } // mremap is Linux specific // TODO: We must do something if it is not supported #ifdef MREMAP_MAYMOVE else { new_ptr = ::mremap(ptr_, size_, new_size, MREMAP_MAYMOVE); } #endif if(new_ptr == MAP_FAILED) return NULL; #ifdef HAVE_VALGRIND new_ptr = (char*)new_ptr + redzone_size; if(ptr_ == MAP_FAILED) VALGRIND_MALLOCLIKE_BLOCK(new_ptr, new_size, redzone_size, 1); // TODO: resize not yet supported #endif size_ = new_size; ptr_ = new_ptr; fast_zero(); return ptr_; } size_t allocators::mmap::round_to_page(size_t _size) { static const long pg_size = sysconf(_SC_PAGESIZE); return (_size / pg_size + (_size % pg_size != 0)) * pg_size; } void allocators::mmap::fast_zero() { tinfo info[nb_threads]; size_t pgsize = round_to_page(1); size_t nb_pages = size_ / pgsize + (size_ % pgsize != 0); int total_threads = 0; for(size_t i = 0; i < (size_t)nb_threads; ++i, ++total_threads) { info[i].start = (char *)ptr_ + pgsize * ((i * nb_pages) / nb_threads); info[i].end = (char *)ptr_ + std::min(pgsize * (((i + 1) * nb_pages) / nb_threads), size_); info[i].pgsize = pgsize; if(pthread_create(&info[i].thid, NULL, _fast_zero, &info[i])) break; } for(int i = 0; i < total_threads; i++) pthread_join(info[i].thid, NULL); } void * allocators::mmap::_fast_zero(void *_info) { tinfo *info = (tinfo *)_info; for(char *cptr = info->start; cptr < info->end; cptr += info->pgsize) { *cptr = 0; } return NULL; } void allocators::mmap::free() { if(ptr_ == MAP_FAILED) return; #ifdef HAVE_VALGRIND VALGRIND_FREELIKE_BLOCK(ptr_, redzone_size); ptr_ = (char*)ptr_ - redzone_size; size_ += 2 * redzone_size; #endif assert(::munmap(ptr_, size_) == 0); ptr_ = MAP_FAILED; size_ = 0; } Jellyfish-2.2.8/lib/err.cc000066400000000000000000000017161323712541700153330ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include namespace jellyfish { namespace err { std::ostream &operator<<(std::ostream &os, const substr &ss) { os.write(ss._s, ss._l); return os; } std::ostream &operator<<(std::ostream &os, const no_t &x) { x.write(os, errno); return os; } } } Jellyfish-2.2.8/lib/generator_manager.cc000066400000000000000000000172101323712541700202170ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace jellyfish { int open_cloexec(const char* path, int flags) { #ifdef O_CLOEXEC int fd = open(path, flags|O_CLOEXEC); #else int fd = open(path, flags); if(fd != -1) fcntl(fd, F_SETFD, FD_CLOEXEC); #endif return fd; } std::string tmp_pipes::create_tmp_dir() { std::vector prefixes; const char* tmpdir = getenv("TMPDIR"); if(tmpdir) prefixes.push_back(tmpdir); #ifdef P_tmpdir prefixes.push_back(P_tmpdir); #endif prefixes.push_back("."); for(auto it = prefixes.begin(); it != prefixes.end(); ++it) { size_t len = strlen(*it) + 6 + 1; std::unique_ptr tmppath(new char[len]); sprintf(tmppath.get(), "%sXXXXXX", *it); const char* res = mkdtemp(tmppath.get()); if(res) return std::string(res); } throw std::runtime_error(err::msg() << "Failed to create a temporary directory for the pipes. Set the variable TMPDIR properly: " << err::no); return ""; } std::vector tmp_pipes::create_pipes(const std::string& tmpdir, int nb_pipes) { std::vector pipes; for(int i = 0; i < nb_pipes; ++i) { std::ostringstream path; path << tmpdir << "/fifo" << i; if(mkfifo(path.str().c_str(), S_IRUSR|S_IWUSR) == -1) throw std::runtime_error(err::msg() << "Failed to create named fifos: " << err::no); pipes.push_back(path.str()); } return pipes; } void tmp_pipes::discard(int i) { if(pipes_[i].empty()) return; // First rename the fifo so no new reader will open it, then open // the fifo (with its new name for writing, in non-blocking mode. If // we get a valid file descriptor, some readers are blocked reading // on the fifo: we close the fifo and free the readers. Otherwise, // no readers is blocked and no action is required. Finally we // unlink the fifo for good. std::string discarded_name(pipes_[i]); discarded_name += "_discarded"; if(rename(pipes_[i].c_str(), discarded_name.c_str()) == -1) return; pipes_[i].clear(); pipes_paths_[i] = 0; int fd = open(discarded_name.c_str(), O_WRONLY|O_NONBLOCK); if(fd != -1) close(fd); unlink(discarded_name.c_str()); } void tmp_pipes::cleanup() { for(size_t i = 0; i < pipes_.size(); ++i) { discard(i); } rmdir(tmpdir_.c_str()); } void generator_manager_base::start() { if(manager_pid_ != -1) return; manager_pid_ = fork(); switch(manager_pid_) { case -1: throw std::runtime_error(err::msg() << "Failed to start manager process: " << err::no); break; case 0: manager_pid_ = -1; break; default: parent_cleanup(); return; } // In child if(setup_signal_handlers() == -1) exit(EXIT_FAILURE); start_commands(); // child start commands int signal = kill_signal_; if(signal == 0) exit(EXIT_SUCCESS); // Got killed. Kill all children, cleanup and kill myself with the // same signal (and die from it this time :). We do not wait on the // dead children as we are going to die soon as well, and we don't // care about the return value at that point. Let init take care of // that for us... cleanup(); unset_signal_handlers(); kill(getpid(), signal); // kill myself exit(EXIT_FAILURE); // Should not be reached } static generator_manager_base* manager = 0; void generator_manager_base::signal_handler(int signal) { manager->kill_signal_ = signal; } int generator_manager_base::setup_signal_handlers() { struct sigaction act; memset(&act, '\0', sizeof(act)); act.sa_handler = signal_handler; return sigaction(SIGTERM, &act, 0); // Should we redefine other signals as well? Like SIGINT, SIGQUIT? } void generator_manager_base::unset_signal_handlers() { struct sigaction act; memset(&act, '\0', sizeof(act)); act.sa_handler = SIG_DFL; sigaction(SIGTERM, &act, 0); } bool generator_manager_base::wait() { if(manager_pid_ == -1) return false; pid_t pid = manager_pid_; manager_pid_ = -1; int status; if(pid != waitpid(pid, &status, 0)) return false; return WIFEXITED(status) && (WEXITSTATUS(status) == 0); } void generator_manager_base::cleanup() { for(auto it = pid2pipe_.begin(); it != pid2pipe_.end(); ++it) { kill(it->first, SIGTERM); pipes_.discard(it->second.pipe); } pipes_.cleanup(); } void generator_manager_base::start_one_command(const std::string& command, int pipe) { cmd_info_type info = { command, pipe }; pid_t child = fork(); switch(child) { case -1: std::cerr << "Failed to fork. Command '" << command << "' not run" << std::endl; return; case 0: break; default: pid2pipe_[child] = info; return; } // In child int dev_null = open_cloexec("/dev/null", O_RDONLY); if(dev_null != -1) dup2(dev_null, 0); int pipe_fd = open_cloexec(pipes_[pipe], O_WRONLY); if(pipe_fd == -1) { std::cerr << "Failed to open output pipe. Command '" << command << "' not run" << std::endl; exit(EXIT_FAILURE); } if(dup2(pipe_fd, 1) == -1) { std::cerr << "Failed to dup pipe to stdout. Command '" << command << "' not run" << std::endl; exit(EXIT_FAILURE); } execl(shell_, shell_, "-c", command.c_str(), (char*)0); std::cerr << "Failed to exec. Command '" << command << "' not run" << std::endl; exit(EXIT_FAILURE); } std::string generator_manager::get_cmd() { std::string command; while(std::getline(cmds_, command)) { size_t pos = command.find_first_not_of(" \t\n\v\f\r"); if(pos != std::string::npos && command[pos] != '#') break; command.clear(); } return command; } void generator_manager_base::start_commands() { std::string command; size_t i; for(i = 0; i < pipes_.size(); ++i) { command = get_cmd(); if(command.empty()) break; start_one_command(command, i); } for( ; i < pipes_.size(); ++i) pipes_.discard(i); while(!pid2pipe_.empty()) { int status; int res = ::wait(&status); if(res == -1) { if(errno == EINTR) continue; break; } cmd_info_type info = pid2pipe_[res]; pid2pipe_.erase(info.pipe); command = get_cmd(); if(!command.empty()) { start_one_command(command, info.pipe); } else { pipes_.discard(info.pipe); } if(!display_status(status, info.command)) { cleanup(); exit(EXIT_FAILURE); } } } bool generator_manager_base::display_status(int status, const std::string& command) { if(WIFEXITED(status) && WEXITSTATUS(status) != 0) { std::cerr << "Command '" << command << "' exited with error status " << WEXITSTATUS(status) << std::endl; return false; } else if(WIFSIGNALED(status)) { std::cerr << "Command '" << command << "' killed by signal " << WTERMSIG(status) << std::endl; return false; } return true; } } // namespace jellyfish Jellyfish-2.2.8/lib/int128.cc000066400000000000000000000077261323712541700155770ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_INT128 #include void __int128_ns::__print_bases(std::ostream& prefix, std::ostream& os, unsigned __int128 x, const std::ios::fmtflags& ff) { if(x == 0) { os << "0"; return; } if(ff & std::ios::showbase) { if(ff & std::ios::hex) { if(ff & std::ios::uppercase) prefix << "0X"; else prefix << "0x"; } else if(ff & std::ios::oct) { prefix << "0"; } } if(ff & std::ios::hex) { __print_digits<16>(os, (unsigned __int128)x, !(ff & std::ios::uppercase)); } else if(ff & std::ios::oct) { __print_digits<8>(os, (unsigned __int128)x); } } #ifndef HAVE_NUMERIC_LIMITS128 const int std::numeric_limits<__int128>::digits; const int std::numeric_limits<__int128>::digits10; const bool std::numeric_limits<__int128>::is_signed; const bool std::numeric_limits<__int128>::is_integer; const bool std::numeric_limits<__int128>::is_exact; const int std::numeric_limits<__int128>::radix; const int std::numeric_limits<__int128>::min_exponent; const int std::numeric_limits<__int128>::min_exponent10; const int std::numeric_limits<__int128>::max_exponent; const int std::numeric_limits<__int128>::max_exponent10; const bool std::numeric_limits<__int128>::has_infinity; const bool std::numeric_limits<__int128>::has_quiet_NaN; const bool std::numeric_limits<__int128>::has_signaling_NaN; const std::float_denorm_style std::numeric_limits<__int128>::has_denorm; const bool std::numeric_limits<__int128>::has_denorm_loss; const bool std::numeric_limits<__int128>::is_iec559; const bool std::numeric_limits<__int128>::is_bounded; const bool std::numeric_limits<__int128>::is_modulo; const bool std::numeric_limits<__int128>::traps; const bool std::numeric_limits<__int128>::tinyness_before; const std::float_round_style std::numeric_limits<__int128>::round_style; const int std::numeric_limits::digits; const int std::numeric_limits::digits10; const bool std::numeric_limits::is_signed; const bool std::numeric_limits::is_integer; const bool std::numeric_limits::is_exact; const int std::numeric_limits::radix; const int std::numeric_limits::min_exponent; const int std::numeric_limits::min_exponent10; const int std::numeric_limits::max_exponent; const int std::numeric_limits::max_exponent10; const bool std::numeric_limits::has_infinity; const bool std::numeric_limits::has_quiet_NaN; const bool std::numeric_limits::has_signaling_NaN; const std::float_denorm_style std::numeric_limits::has_denorm; const bool std::numeric_limits::has_denorm_loss; const bool std::numeric_limits::is_iec559; const bool std::numeric_limits::is_bounded; const bool std::numeric_limits::is_modulo; const bool std::numeric_limits::traps; const bool std::numeric_limits::tinyness_before; const std::float_round_style std::numeric_limits::round_style; #endif #endif Jellyfish-2.2.8/lib/jsoncpp.cpp000066400000000000000000003126711323712541700164210ustar00rootroot00000000000000/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). /// It is intented to be used with #include // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: LICENSE // ////////////////////////////////////////////////////////////////////// /* The JsonCpp library's source code, including accompanying documentation, tests and demonstration applications, are licensed under the following conditions... The author (Baptiste Lepilleur) explicitly disclaims copyright in all jurisdictions which recognize such a disclaimer. In such jurisdictions, this software is released into the Public Domain. In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is released under the terms of the MIT License (see below). In jurisdictions which recognize Public Domain property, the user of this software may choose to accept it either as 1) Public Domain, 2) under the conditions of the MIT License (see below), or 3) under the terms of dual Public Domain/MIT License conditions described here, as they choose. The MIT License is about as close to Public Domain as a license can get, and is described in clear, concise terms at: http://en.wikipedia.org/wiki/MIT_License The full text of the MIT License follows: ======================================================================== Copyright (c) 2007-2010 Baptiste Lepilleur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ======================================================================== (END LICENSE TEXT) The MIT license is compatible with both the GPL and commercial software, affording one all of the rights of Public Domain with the minor nuisance of being required to keep the above copyright notice and license text in the source code. Note also that by accepting the Public Domain "license" you can re-license your copy using whatever license you like. */ // ////////////////////////////////////////////////////////////////////// // End of content of file: LICENSE // ////////////////////////////////////////////////////////////////////// #include // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: src/lib_json/json_tool.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED # define LIB_JSONCPP_JSON_TOOL_H_INCLUDED /* This header provides common string manipulation support, such as UTF-8, * portable conversion from/to string... * * It is an internal header that must not be exposed. */ namespace Json { /// Converts a unicode code-point to UTF-8. static inline std::string codePointToUTF8(unsigned int cp) { std::string result; // based on description from http://en.wikipedia.org/wiki/UTF-8 if (cp <= 0x7f) { result.resize(1); result[0] = static_cast(cp); } else if (cp <= 0x7FF) { result.resize(2); result[1] = static_cast(0x80 | (0x3f & cp)); result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); } else if (cp <= 0xFFFF) { result.resize(3); result[2] = static_cast(0x80 | (0x3f & cp)); result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); } else if (cp <= 0x10FFFF) { result.resize(4); result[3] = static_cast(0x80 | (0x3f & cp)); result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); } return result; } /// Returns true if ch is a control character (in range [0,32[). static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } enum { /// Constant that specify the size of the buffer that must be passed to uintToString. uintToStringBufferSize = 3*sizeof(LargestUInt)+1 }; // Defines a char buffer for use with uintToString(). typedef char UIntToStringBuffer[uintToStringBufferSize]; /** Converts an unsigned integer to string. * @param value Unsigned interger to convert to string * @param current Input/Output string buffer. * Must have at least uintToStringBufferSize chars free. */ static inline void uintToString( LargestUInt value, char *¤t ) { *--current = 0; do { *--current = char(value % 10) + '0'; value /= 10; } while ( value != 0 ); } } // namespace Json { #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_tool.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: src/lib_json/json_reader.cpp // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) # include # include # include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) #include #include #include #include #include #include #if _MSC_VER >= 1400 // VC++ 8.0 #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. #endif namespace Json { // Implementation of class Features // //////////////////////////////// Features::Features() : allowComments_( true ) , strictRoot_( false ) { } Features Features::all() { return Features(); } Features Features::strictMode() { Features features; features.allowComments_ = false; features.strictRoot_ = true; return features; } // Implementation of class Reader // //////////////////////////////// static inline bool in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) { return c == c1 || c == c2 || c == c3 || c == c4; } static inline bool in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) { return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; } static bool containsNewLine( Reader::Location begin, Reader::Location end ) { for ( ;begin < end; ++begin ) if ( *begin == '\n' || *begin == '\r' ) return true; return false; } // Class Reader // ////////////////////////////////////////////////////////////////// Reader::Reader() : features_( Features::all() ) { } Reader::Reader( const Features &features ) : features_( features ) { } bool Reader::parse( const std::string &document, Value &root, bool collectComments ) { document_ = document; const char *begin = document_.c_str(); const char *end = begin + document_.length(); return parse( begin, end, root, collectComments ); } bool Reader::parse( std::istream& sin, Value &root, bool collectComments ) { //std::istream_iterator begin(sin); //std::istream_iterator end; // Those would allow streamed input from a file, if parse() were a // template function. // Since std::string is reference-counted, this at least does not // create an extra copy. std::string doc; std::getline(sin, doc, (char)EOF); return parse( doc, root, collectComments ); } bool Reader::parse( const char *beginDoc, const char *endDoc, Value &root, bool collectComments ) { if ( !features_.allowComments_ ) { collectComments = false; } begin_ = beginDoc; end_ = endDoc; collectComments_ = collectComments; current_ = begin_; lastValueEnd_ = 0; lastValue_ = 0; commentsBefore_ = ""; errors_.clear(); while ( !nodes_.empty() ) nodes_.pop(); nodes_.push( &root ); bool successful = readValue(); Token token; skipCommentTokens( token ); if ( collectComments_ && !commentsBefore_.empty() ) root.setComment( commentsBefore_, commentAfter ); if ( features_.strictRoot_ ) { if ( !root.isArray() && !root.isObject() ) { // Set error location to start of doc, ideally should be first token found in doc token.type_ = tokenError; token.start_ = beginDoc; token.end_ = endDoc; addError( "A valid JSON document must be either an array or an object value.", token ); return false; } } return successful; } bool Reader::readValue() { Token token; skipCommentTokens( token ); bool successful = true; if ( collectComments_ && !commentsBefore_.empty() ) { currentValue().setComment( commentsBefore_, commentBefore ); commentsBefore_ = ""; } switch ( token.type_ ) { case tokenObjectBegin: successful = readObject( token ); break; case tokenArrayBegin: successful = readArray( token ); break; case tokenNumber: successful = decodeNumber( token ); break; case tokenString: successful = decodeString( token ); break; case tokenTrue: currentValue() = true; break; case tokenFalse: currentValue() = false; break; case tokenNull: currentValue() = Value(); break; default: return addError( "Syntax error: value, object or array expected.", token ); } if ( collectComments_ ) { lastValueEnd_ = current_; lastValue_ = ¤tValue(); } return successful; } void Reader::skipCommentTokens( Token &token ) { if ( features_.allowComments_ ) { do { readToken( token ); } while ( token.type_ == tokenComment ); } else { readToken( token ); } } bool Reader::expectToken( TokenType type, Token &token, const char *message ) { readToken( token ); if ( token.type_ != type ) return addError( message, token ); return true; } bool Reader::readToken( Token &token ) { skipSpaces(); token.start_ = current_; Char c = getNextChar(); bool ok = true; switch ( c ) { case '{': token.type_ = tokenObjectBegin; break; case '}': token.type_ = tokenObjectEnd; break; case '[': token.type_ = tokenArrayBegin; break; case ']': token.type_ = tokenArrayEnd; break; case '"': token.type_ = tokenString; ok = readString(); break; case '/': token.type_ = tokenComment; ok = readComment(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': token.type_ = tokenNumber; readNumber(); break; case 't': token.type_ = tokenTrue; ok = match( "rue", 3 ); break; case 'f': token.type_ = tokenFalse; ok = match( "alse", 4 ); break; case 'n': token.type_ = tokenNull; ok = match( "ull", 3 ); break; case ',': token.type_ = tokenArraySeparator; break; case ':': token.type_ = tokenMemberSeparator; break; case 0: token.type_ = tokenEndOfStream; break; default: ok = false; break; } if ( !ok ) token.type_ = tokenError; token.end_ = current_; return true; } void Reader::skipSpaces() { while ( current_ != end_ ) { Char c = *current_; if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) ++current_; else break; } } bool Reader::match( Location pattern, int patternLength ) { if ( end_ - current_ < patternLength ) return false; int index = patternLength; while ( index-- ) if ( current_[index] != pattern[index] ) return false; current_ += patternLength; return true; } bool Reader::readComment() { Location commentBegin = current_ - 1; Char c = getNextChar(); bool successful = false; if ( c == '*' ) successful = readCStyleComment(); else if ( c == '/' ) successful = readCppStyleComment(); if ( !successful ) return false; if ( collectComments_ ) { CommentPlacement placement = commentBefore; if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) { if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) placement = commentAfterOnSameLine; } addComment( commentBegin, current_, placement ); } return true; } void Reader::addComment( Location begin, Location end, CommentPlacement placement ) { assert( collectComments_ ); if ( placement == commentAfterOnSameLine ) { assert( lastValue_ != 0 ); lastValue_->setComment( std::string( begin, end ), placement ); } else { if ( !commentsBefore_.empty() ) commentsBefore_ += "\n"; commentsBefore_ += std::string( begin, end ); } } bool Reader::readCStyleComment() { while ( current_ != end_ ) { Char c = getNextChar(); if ( c == '*' && *current_ == '/' ) break; } return getNextChar() == '/'; } bool Reader::readCppStyleComment() { while ( current_ != end_ ) { Char c = getNextChar(); if ( c == '\r' || c == '\n' ) break; } return true; } void Reader::readNumber() { while ( current_ != end_ ) { if ( !(*current_ >= '0' && *current_ <= '9') && !in( *current_, '.', 'e', 'E', '+', '-' ) ) break; ++current_; } } bool Reader::readString() { Char c = 0; while ( current_ != end_ ) { c = getNextChar(); if ( c == '\\' ) getNextChar(); else if ( c == '"' ) break; } return c == '"'; } bool Reader::readObject( Token &/*tokenStart*/ ) { Token tokenName; std::string name; currentValue() = Value( objectValue ); while ( readToken( tokenName ) ) { bool initialTokenOk = true; while ( tokenName.type_ == tokenComment && initialTokenOk ) initialTokenOk = readToken( tokenName ); if ( !initialTokenOk ) break; if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object return true; if ( tokenName.type_ != tokenString ) break; name = ""; if ( !decodeString( tokenName, name ) ) return recoverFromError( tokenObjectEnd ); Token colon; if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) { return addErrorAndRecover( "Missing ':' after object member name", colon, tokenObjectEnd ); } Value &value = currentValue()[ name ]; nodes_.push( &value ); bool ok = readValue(); nodes_.pop(); if ( !ok ) // error already set return recoverFromError( tokenObjectEnd ); Token comma; if ( !readToken( comma ) || ( comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment ) ) { return addErrorAndRecover( "Missing ',' or '}' in object declaration", comma, tokenObjectEnd ); } bool finalizeTokenOk = true; while ( comma.type_ == tokenComment && finalizeTokenOk ) finalizeTokenOk = readToken( comma ); if ( comma.type_ == tokenObjectEnd ) return true; } return addErrorAndRecover( "Missing '}' or object member name", tokenName, tokenObjectEnd ); } bool Reader::readArray( Token &/*tokenStart*/ ) { currentValue() = Value( arrayValue ); skipSpaces(); if ( *current_ == ']' ) // empty array { Token endArray; readToken( endArray ); return true; } int index = 0; for (;;) { Value &value = currentValue()[ index++ ]; nodes_.push( &value ); bool ok = readValue(); nodes_.pop(); if ( !ok ) // error already set return recoverFromError( tokenArrayEnd ); Token token; // Accept Comment after last item in the array. ok = readToken( token ); while ( token.type_ == tokenComment && ok ) { ok = readToken( token ); } bool badTokenType = ( token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd ); if ( !ok || badTokenType ) { return addErrorAndRecover( "Missing ',' or ']' in array declaration", token, tokenArrayEnd ); } if ( token.type_ == tokenArrayEnd ) break; } return true; } bool Reader::decodeNumber( Token &token ) { bool isDouble = false; for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) { isDouble = isDouble || in( *inspect, '.', 'e', 'E', '+' ) || ( *inspect == '-' && inspect != token.start_ ); } if ( isDouble ) return decodeDouble( token ); // Attempts to parse the number as an integer. If the number is // larger than the maximum supported value of an integer then // we decode the number as a double. Location current = token.start_; bool isNegative = *current == '-'; if ( isNegative ) ++current; Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) : Value::maxLargestUInt; Value::LargestUInt threshold = maxIntegerValue / 10; Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 ); assert( lastDigitThreshold <= 9 ); Value::LargestUInt value = 0; while ( current < token.end_ ) { Char c = *current++; if ( c < '0' || c > '9' ) return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); Value::UInt digit(c - '0'); if ( value >= threshold ) { // If the current digit is not the last one, or if it is // greater than the last digit of the maximum integer value, // the parse the number as a double. if ( current != token.end_ || digit > lastDigitThreshold ) { return decodeDouble( token ); } } value = value * 10 + digit; } if ( isNegative ) currentValue() = -Value::LargestInt( value ); else if ( value <= Value::LargestUInt(Value::maxInt) ) currentValue() = Value::LargestInt( value ); else currentValue() = value; return true; } bool Reader::decodeDouble( Token &token ) { double value = 0; const int bufferSize = 32; int count; int length = int(token.end_ - token.start_); if ( length <= bufferSize ) { Char buffer[bufferSize+1]; memcpy( buffer, token.start_, length ); buffer[length] = 0; count = sscanf( buffer, "%lf", &value ); } else { std::string buffer( token.start_, token.end_ ); count = sscanf( buffer.c_str(), "%lf", &value ); } if ( count != 1 ) return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); currentValue() = value; return true; } bool Reader::decodeString( Token &token ) { std::string decoded; if ( !decodeString( token, decoded ) ) return false; currentValue() = decoded; return true; } bool Reader::decodeString( Token &token, std::string &decoded ) { decoded.reserve( token.end_ - token.start_ - 2 ); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' while ( current != end ) { Char c = *current++; if ( c == '"' ) break; else if ( c == '\\' ) { if ( current == end ) return addError( "Empty escape sequence in string", token, current ); Char escape = *current++; switch ( escape ) { case '"': decoded += '"'; break; case '/': decoded += '/'; break; case '\\': decoded += '\\'; break; case 'b': decoded += '\b'; break; case 'f': decoded += '\f'; break; case 'n': decoded += '\n'; break; case 'r': decoded += '\r'; break; case 't': decoded += '\t'; break; case 'u': { unsigned int unicode; if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) return false; decoded += codePointToUTF8(unicode); } break; default: return addError( "Bad escape sequence in string", token, current ); } } else { decoded += c; } } return true; } bool Reader::decodeUnicodeCodePoint( Token &token, Location ¤t, Location end, unsigned int &unicode ) { if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) return false; if (unicode >= 0xD800 && unicode <= 0xDBFF) { // surrogate pairs if (end - current < 6) return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); unsigned int surrogatePair; if (*(current++) == '\\' && *(current++)== 'u') { if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) { unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else return false; } else return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); } return true; } bool Reader::decodeUnicodeEscapeSequence( Token &token, Location ¤t, Location end, unsigned int &unicode ) { if ( end - current < 4 ) return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); unicode = 0; for ( int index =0; index < 4; ++index ) { Char c = *current++; unicode *= 16; if ( c >= '0' && c <= '9' ) unicode += c - '0'; else if ( c >= 'a' && c <= 'f' ) unicode += c - 'a' + 10; else if ( c >= 'A' && c <= 'F' ) unicode += c - 'A' + 10; else return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); } return true; } bool Reader::addError( const std::string &message, Token &token, Location extra ) { ErrorInfo info; info.token_ = token; info.message_ = message; info.extra_ = extra; errors_.push_back( info ); return false; } bool Reader::recoverFromError( TokenType skipUntilToken ) { int errorCount = int(errors_.size()); Token skip; for (;;) { if ( !readToken(skip) ) errors_.resize( errorCount ); // discard errors caused by recovery if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) break; } errors_.resize( errorCount ); return false; } bool Reader::addErrorAndRecover( const std::string &message, Token &token, TokenType skipUntilToken ) { addError( message, token ); return recoverFromError( skipUntilToken ); } Value & Reader::currentValue() { return *(nodes_.top()); } Reader::Char Reader::getNextChar() { if ( current_ == end_ ) return 0; return *current_++; } void Reader::getLocationLineAndColumn( Location location, int &line, int &column ) const { Location current = begin_; Location lastLineStart = current; line = 0; while ( current < location && current != end_ ) { Char c = *current++; if ( c == '\r' ) { if ( *current == '\n' ) ++current; lastLineStart = current; ++line; } else if ( c == '\n' ) { lastLineStart = current; ++line; } } // column & line start at 1 column = int(location - lastLineStart) + 1; ++line; } std::string Reader::getLocationLineAndColumn( Location location ) const { int line, column; getLocationLineAndColumn( location, line, column ); char buffer[18+16+16+1]; sprintf( buffer, "Line %d, Column %d", line, column ); return buffer; } // Deprecated. Preserved for backward compatibility std::string Reader::getFormatedErrorMessages() const { return getFormattedErrorMessages(); } std::string Reader::getFormattedErrorMessages() const { std::string formattedMessage; for ( Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError ) { const ErrorInfo &error = *itError; formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; formattedMessage += " " + error.message_ + "\n"; if ( error.extra_ ) formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; } return formattedMessage; } std::istream& operator>>( std::istream &sin, Value &root ) { Json::Reader reader; bool ok = reader.parse(sin, root, true); //JSON_ASSERT( ok ); if (!ok) throw std::runtime_error(reader.getFormattedErrorMessages()); return sin; } } // namespace Json // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_reader.cpp // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: src/lib_json/json_batchallocator.h // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED # define JSONCPP_BATCHALLOCATOR_H_INCLUDED # include # include # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION namespace Json { /* Fast memory allocator. * * This memory allocator allocates memory for a batch of object (specified by * the page size, the number of object in each page). * * It does not allow the destruction of a single object. All the allocated objects * can be destroyed at once. The memory can be either released or reused for future * allocation. * * The in-place new operator must be used to construct the object using the pointer * returned by allocate. */ template class BatchAllocator { public: typedef AllocatedType Type; BatchAllocator( unsigned int objectsPerPage = 255 ) : freeHead_( 0 ) , objectsPerPage_( objectsPerPage ) { // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. assert( objectsPerPage >= 16 ); batches_ = allocateBatch( 0 ); // allocated a dummy page currentBatch_ = batches_; } ~BatchAllocator() { for ( BatchInfo *batch = batches_; batch; ) { BatchInfo *nextBatch = batch->next_; free( batch ); batch = nextBatch; } } /// allocate space for an array of objectPerAllocation object. /// @warning it is the responsability of the caller to call objects constructors. AllocatedType *allocate() { if ( freeHead_ ) // returns node from free list. { AllocatedType *object = freeHead_; freeHead_ = *(AllocatedType **)object; return object; } if ( currentBatch_->used_ == currentBatch_->end_ ) { currentBatch_ = currentBatch_->next_; while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) currentBatch_ = currentBatch_->next_; if ( !currentBatch_ ) // no free batch found, allocate a new one { currentBatch_ = allocateBatch( objectsPerPage_ ); currentBatch_->next_ = batches_; // insert at the head of the list batches_ = currentBatch_; } } AllocatedType *allocated = currentBatch_->used_; currentBatch_->used_ += objectPerAllocation; return allocated; } /// Release the object. /// @warning it is the responsability of the caller to actually destruct the object. void release( AllocatedType *object ) { assert( object != 0 ); *(AllocatedType **)object = freeHead_; freeHead_ = object; } private: struct BatchInfo { BatchInfo *next_; AllocatedType *used_; AllocatedType *end_; AllocatedType buffer_[objectPerAllocation]; }; // disabled copy constructor and assignement operator. BatchAllocator( const BatchAllocator & ); void operator =( const BatchAllocator &); static BatchInfo *allocateBatch( unsigned int objectsPerPage ) { const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; BatchInfo *batch = static_cast( malloc( mallocSize ) ); batch->next_ = 0; batch->used_ = batch->buffer_; batch->end_ = batch->buffer_ + objectsPerPage; return batch; } BatchInfo *batches_; BatchInfo *currentBatch_; /// Head of a single linked list within the allocated space of freeed object AllocatedType *freeHead_; unsigned int objectsPerPage_; }; } // namespace Json # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_batchallocator.h // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: src/lib_json/json_valueiterator.inl // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE // included by json_value.cpp namespace Json { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class ValueIteratorBase // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// ValueIteratorBase::ValueIteratorBase() #ifndef JSON_VALUE_USE_INTERNAL_MAP : current_() , isNull_( true ) { } #else : isArray_( true ) , isNull_( true ) { iterator_.array_ = ValueInternalArray::IteratorState(); } #endif #ifndef JSON_VALUE_USE_INTERNAL_MAP ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator ¤t ) : current_( current ) , isNull_( false ) { } #else ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state ) : isArray_( true ) { iterator_.array_ = state; } ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state ) : isArray_( false ) { iterator_.map_ = state; } #endif Value & ValueIteratorBase::deref() const { #ifndef JSON_VALUE_USE_INTERNAL_MAP return current_->second; #else if ( isArray_ ) return ValueInternalArray::dereference( iterator_.array_ ); return ValueInternalMap::value( iterator_.map_ ); #endif } void ValueIteratorBase::increment() { #ifndef JSON_VALUE_USE_INTERNAL_MAP ++current_; #else if ( isArray_ ) ValueInternalArray::increment( iterator_.array_ ); ValueInternalMap::increment( iterator_.map_ ); #endif } void ValueIteratorBase::decrement() { #ifndef JSON_VALUE_USE_INTERNAL_MAP --current_; #else if ( isArray_ ) ValueInternalArray::decrement( iterator_.array_ ); ValueInternalMap::decrement( iterator_.map_ ); #endif } ValueIteratorBase::difference_type ValueIteratorBase::computeDistance( const SelfType &other ) const { #ifndef JSON_VALUE_USE_INTERNAL_MAP # ifdef JSON_USE_CPPTL_SMALLMAP return current_ - other.current_; # else // Iterator for null value are initialized using the default // constructor, which initialize current_ to the default // std::map::iterator. As begin() and end() are two instance // of the default std::map::iterator, they can not be compared. // To allow this, we handle this comparison specifically. if ( isNull_ && other.isNull_ ) { return 0; } // Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL, // which is the one used by default). // Using a portable hand-made version for non random iterator instead: // return difference_type( std::distance( current_, other.current_ ) ); difference_type myDistance = 0; for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it ) { ++myDistance; } return myDistance; # endif #else if ( isArray_ ) return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ ); return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ ); #endif } bool ValueIteratorBase::isEqual( const SelfType &other ) const { #ifndef JSON_VALUE_USE_INTERNAL_MAP if ( isNull_ ) { return other.isNull_; } return current_ == other.current_; #else if ( isArray_ ) return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ ); return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ ); #endif } void ValueIteratorBase::copy( const SelfType &other ) { #ifndef JSON_VALUE_USE_INTERNAL_MAP current_ = other.current_; #else if ( isArray_ ) iterator_.array_ = other.iterator_.array_; iterator_.map_ = other.iterator_.map_; #endif } Value ValueIteratorBase::key() const { #ifndef JSON_VALUE_USE_INTERNAL_MAP const Value::CZString czstring = (*current_).first; if ( czstring.c_str() ) { if ( czstring.isStaticString() ) return Value( StaticString( czstring.c_str() ) ); return Value( czstring.c_str() ); } return Value( czstring.index() ); #else if ( isArray_ ) return Value( ValueInternalArray::indexOf( iterator_.array_ ) ); bool isStatic; const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic ); if ( isStatic ) return Value( StaticString( memberName ) ); return Value( memberName ); #endif } UInt ValueIteratorBase::index() const { #ifndef JSON_VALUE_USE_INTERNAL_MAP const Value::CZString czstring = (*current_).first; if ( !czstring.c_str() ) return czstring.index(); return Value::UInt( -1 ); #else if ( isArray_ ) return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) ); return Value::UInt( -1 ); #endif } const char * ValueIteratorBase::memberName() const { #ifndef JSON_VALUE_USE_INTERNAL_MAP const char *name = (*current_).first.c_str(); return name ? name : ""; #else if ( !isArray_ ) return ValueInternalMap::key( iterator_.map_ ); return ""; #endif } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class ValueConstIterator // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// ValueConstIterator::ValueConstIterator() { } #ifndef JSON_VALUE_USE_INTERNAL_MAP ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator ¤t ) : ValueIteratorBase( current ) { } #else ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state ) : ValueIteratorBase( state ) { } ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state ) : ValueIteratorBase( state ) { } #endif ValueConstIterator & ValueConstIterator::operator =( const ValueIteratorBase &other ) { copy( other ); return *this; } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class ValueIterator // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// ValueIterator::ValueIterator() { } #ifndef JSON_VALUE_USE_INTERNAL_MAP ValueIterator::ValueIterator( const Value::ObjectValues::iterator ¤t ) : ValueIteratorBase( current ) { } #else ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state ) : ValueIteratorBase( state ) { } ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state ) : ValueIteratorBase( state ) { } #endif ValueIterator::ValueIterator( const ValueConstIterator &other ) : ValueIteratorBase( other ) { } ValueIterator::ValueIterator( const ValueIterator &other ) : ValueIteratorBase( other ) { } ValueIterator & ValueIterator::operator =( const SelfType &other ) { copy( other ); return *this; } } // namespace Json // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_valueiterator.inl // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: src/lib_json/json_value.cpp // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) # include # include # ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR # include "json_batchallocator.h" # endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR #endif // if !defined(JSON_IS_AMALGAMATION) #include #include #include #include #include #ifdef JSON_USE_CPPTL # include #endif #include // size_t #define JSON_ASSERT_UNREACHABLE assert( false ) #define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw #define JSON_FAIL_MESSAGE( message ) throw std::runtime_error( message ); #define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) JSON_FAIL_MESSAGE( message ) namespace Json { const Value Value::null; const Int Value::minInt = Int( ~(UInt(-1)/2) ); const Int Value::maxInt = Int( UInt(-1)/2 ); const UInt Value::maxUInt = UInt(-1); const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) ); const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 ); const UInt64 Value::maxUInt64 = UInt64(-1); const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) ); const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 ); const LargestUInt Value::maxLargestUInt = LargestUInt(-1); /// Unknown size marker static const unsigned int unknown = (unsigned)-1; /** Duplicates the specified string value. * @param value Pointer to the string to duplicate. Must be zero-terminated if * length is "unknown". * @param length Length of the value. if equals to unknown, then it will be * computed using strlen(value). * @return Pointer on the duplicate instance of string. */ static inline char * duplicateStringValue( const char *value, unsigned int length = unknown ) { if ( length == unknown ) length = (unsigned int)strlen(value); char *newString = static_cast( malloc( length + 1 ) ); JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" ); memcpy( newString, value, length ); newString[length] = 0; return newString; } /** Free the string duplicated by duplicateStringValue(). */ static inline void releaseStringValue( char *value ) { if ( value ) free( value ); } } // namespace Json // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ValueInternals... // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// #if !defined(JSON_IS_AMALGAMATION) # ifdef JSON_VALUE_USE_INTERNAL_MAP # include "json_internalarray.inl" # include "json_internalmap.inl" # endif // JSON_VALUE_USE_INTERNAL_MAP # include "json_valueiterator.inl" #endif // if !defined(JSON_IS_AMALGAMATION) namespace Json { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Value::CommentInfo // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// Value::CommentInfo::CommentInfo() : comment_( 0 ) { } Value::CommentInfo::~CommentInfo() { if ( comment_ ) releaseStringValue( comment_ ); } void Value::CommentInfo::setComment( const char *text ) { if ( comment_ ) releaseStringValue( comment_ ); JSON_ASSERT( text != 0 ); JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /"); // It seems that /**/ style comments are acceptable as well. comment_ = duplicateStringValue( text ); } // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Value::CZString // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// # ifndef JSON_VALUE_USE_INTERNAL_MAP // Notes: index_ indicates if the string was allocated when // a string is stored. Value::CZString::CZString( ArrayIndex index ) : cstr_( 0 ) , index_( index ) { } Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate ) : cstr_( allocate == duplicate ? duplicateStringValue(cstr) : cstr ) , index_( allocate ) { } Value::CZString::CZString( const CZString &other ) : cstr_( other.index_ != noDuplication && other.cstr_ != 0 ? duplicateStringValue( other.cstr_ ) : other.cstr_ ) , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) : other.index_ ) { } Value::CZString::~CZString() { if ( cstr_ && index_ == duplicate ) releaseStringValue( const_cast( cstr_ ) ); } void Value::CZString::swap( CZString &other ) { std::swap( cstr_, other.cstr_ ); std::swap( index_, other.index_ ); } Value::CZString & Value::CZString::operator =( const CZString &other ) { CZString temp( other ); swap( temp ); return *this; } bool Value::CZString::operator<( const CZString &other ) const { if ( cstr_ ) return strcmp( cstr_, other.cstr_ ) < 0; return index_ < other.index_; } bool Value::CZString::operator==( const CZString &other ) const { if ( cstr_ ) return strcmp( cstr_, other.cstr_ ) == 0; return index_ == other.index_; } ArrayIndex Value::CZString::index() const { return index_; } const char * Value::CZString::c_str() const { return cstr_; } bool Value::CZString::isStaticString() const { return index_ == noDuplication; } #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // class Value::Value // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// /*! \internal Default constructor initialization must be equivalent to: * memset( this, 0, sizeof(Value) ) * This optimization is used in ValueInternalMap fast allocator. */ Value::Value( ValueType type ) : type_( type ) , allocated_( 0 ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { switch ( type ) { case nullValue: break; case intValue: case uintValue: value_.int_ = 0; break; case realValue: value_.real_ = 0.0; break; case stringValue: value_.string_ = 0; break; #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: case objectValue: value_.map_ = new ObjectValues(); break; #else case arrayValue: value_.array_ = arrayAllocator()->newArray(); break; case objectValue: value_.map_ = mapAllocator()->newMap(); break; #endif case booleanValue: value_.bool_ = false; break; default: JSON_ASSERT_UNREACHABLE; } } #if defined(JSON_HAS_INT64) Value::Value( UInt value ) : type_( uintValue ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.uint_ = value; } Value::Value( Int value ) : type_( intValue ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.int_ = value; } #endif // if defined(JSON_HAS_INT64) Value::Value( Int64 value ) : type_( intValue ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.int_ = value; } Value::Value( UInt64 value ) : type_( uintValue ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.uint_ = value; } Value::Value( double value ) : type_( realValue ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.real_ = value; } Value::Value( const char *value ) : type_( stringValue ) , allocated_( true ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.string_ = duplicateStringValue( value ); } Value::Value( const char *beginValue, const char *endValue ) : type_( stringValue ) , allocated_( true ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.string_ = duplicateStringValue( beginValue, (unsigned int)(endValue - beginValue) ); } Value::Value( const std::string &value ) : type_( stringValue ) , allocated_( true ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.string_ = duplicateStringValue( value.c_str(), (unsigned int)value.length() ); } Value::Value( const StaticString &value ) : type_( stringValue ) , allocated_( false ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.string_ = const_cast( value.c_str() ); } # ifdef JSON_USE_CPPTL Value::Value( const CppTL::ConstString &value ) : type_( stringValue ) , allocated_( true ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.string_ = duplicateStringValue( value, value.length() ); } # endif Value::Value( bool value ) : type_( booleanValue ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { value_.bool_ = value; } Value::Value( const Value &other ) : type_( other.type_ ) , comments_( 0 ) # ifdef JSON_VALUE_USE_INTERNAL_MAP , itemIsUsed_( 0 ) #endif { switch ( type_ ) { case nullValue: case intValue: case uintValue: case realValue: case booleanValue: value_ = other.value_; break; case stringValue: if ( other.value_.string_ ) { value_.string_ = duplicateStringValue( other.value_.string_ ); allocated_ = true; } else value_.string_ = 0; break; #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: case objectValue: value_.map_ = new ObjectValues( *other.value_.map_ ); break; #else case arrayValue: value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ ); break; case objectValue: value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ ); break; #endif default: JSON_ASSERT_UNREACHABLE; } if ( other.comments_ ) { comments_ = new CommentInfo[numberOfCommentPlacement]; for ( int comment =0; comment < numberOfCommentPlacement; ++comment ) { const CommentInfo &otherComment = other.comments_[comment]; if ( otherComment.comment_ ) comments_[comment].setComment( otherComment.comment_ ); } } } Value::~Value() { switch ( type_ ) { case nullValue: case intValue: case uintValue: case realValue: case booleanValue: break; case stringValue: if ( allocated_ ) releaseStringValue( value_.string_ ); break; #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: case objectValue: delete value_.map_; break; #else case arrayValue: arrayAllocator()->destructArray( value_.array_ ); break; case objectValue: mapAllocator()->destructMap( value_.map_ ); break; #endif default: JSON_ASSERT_UNREACHABLE; } if ( comments_ ) delete[] comments_; } Value & Value::operator=( const Value &other ) { Value temp( other ); swap( temp ); return *this; } void Value::swap( Value &other ) { ValueType temp = type_; type_ = other.type_; other.type_ = temp; std::swap( value_, other.value_ ); int temp2 = allocated_; allocated_ = other.allocated_; other.allocated_ = temp2; } ValueType Value::type() const { return type_; } int Value::compare( const Value &other ) const { if ( *this < other ) return -1; if ( *this > other ) return 1; return 0; } bool Value::operator <( const Value &other ) const { int typeDelta = type_ - other.type_; if ( typeDelta ) return typeDelta < 0 ? true : false; switch ( type_ ) { case nullValue: return false; case intValue: return value_.int_ < other.value_.int_; case uintValue: return value_.uint_ < other.value_.uint_; case realValue: return value_.real_ < other.value_.real_; case booleanValue: return value_.bool_ < other.value_.bool_; case stringValue: return ( value_.string_ == 0 && other.value_.string_ ) || ( other.value_.string_ && value_.string_ && strcmp( value_.string_, other.value_.string_ ) < 0 ); #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: case objectValue: { int delta = int( value_.map_->size() - other.value_.map_->size() ); if ( delta ) return delta < 0; return (*value_.map_) < (*other.value_.map_); } #else case arrayValue: return value_.array_->compare( *(other.value_.array_) ) < 0; case objectValue: return value_.map_->compare( *(other.value_.map_) ) < 0; #endif default: JSON_ASSERT_UNREACHABLE; } return false; // unreachable } bool Value::operator <=( const Value &other ) const { return !(other < *this); } bool Value::operator >=( const Value &other ) const { return !(*this < other); } bool Value::operator >( const Value &other ) const { return other < *this; } bool Value::operator ==( const Value &other ) const { //if ( type_ != other.type_ ) // GCC 2.95.3 says: // attempt to take address of bit-field structure member `Json::Value::type_' // Beats me, but a temp solves the problem. int temp = other.type_; if ( type_ != temp ) return false; switch ( type_ ) { case nullValue: return true; case intValue: return value_.int_ == other.value_.int_; case uintValue: return value_.uint_ == other.value_.uint_; case realValue: return value_.real_ == other.value_.real_; case booleanValue: return value_.bool_ == other.value_.bool_; case stringValue: return ( value_.string_ == other.value_.string_ ) || ( other.value_.string_ && value_.string_ && strcmp( value_.string_, other.value_.string_ ) == 0 ); #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: case objectValue: return value_.map_->size() == other.value_.map_->size() && (*value_.map_) == (*other.value_.map_); #else case arrayValue: return value_.array_->compare( *(other.value_.array_) ) == 0; case objectValue: return value_.map_->compare( *(other.value_.map_) ) == 0; #endif default: JSON_ASSERT_UNREACHABLE; } return false; // unreachable } bool Value::operator !=( const Value &other ) const { return !( *this == other ); } const char * Value::asCString() const { JSON_ASSERT( type_ == stringValue ); return value_.string_; } std::string Value::asString() const { switch ( type_ ) { case nullValue: return ""; case stringValue: return value_.string_ ? value_.string_ : ""; case booleanValue: return value_.bool_ ? "true" : "false"; case intValue: case uintValue: case realValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to string" ); default: JSON_ASSERT_UNREACHABLE; } return ""; // unreachable } # ifdef JSON_USE_CPPTL CppTL::ConstString Value::asConstString() const { return CppTL::ConstString( asString().c_str() ); } # endif Value::Int Value::asInt() const { switch ( type_ ) { case nullValue: return 0; case intValue: JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" ); return Int(value_.int_); case uintValue: JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" ); return Int(value_.uint_); case realValue: JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" ); return Int( value_.real_ ); case booleanValue: return value_.bool_ ? 1 : 0; case stringValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to int" ); default: JSON_ASSERT_UNREACHABLE; } return 0; // unreachable; } Value::UInt Value::asUInt() const { switch ( type_ ) { case nullValue: return 0; case intValue: JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" ); JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" ); return UInt(value_.int_); case uintValue: JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" ); return UInt(value_.uint_); case realValue: JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" ); return UInt( value_.real_ ); case booleanValue: return value_.bool_ ? 1 : 0; case stringValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to uint" ); default: JSON_ASSERT_UNREACHABLE; } return 0; // unreachable; } # if defined(JSON_HAS_INT64) Value::Int64 Value::asInt64() const { switch ( type_ ) { case nullValue: return 0; case intValue: return value_.int_; case uintValue: JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" ); return value_.uint_; case realValue: JSON_ASSERT_MESSAGE( value_.real_ >= minInt64 && value_.real_ <= maxInt64, "Real out of Int64 range" ); return Int( value_.real_ ); case booleanValue: return value_.bool_ ? 1 : 0; case stringValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to Int64" ); default: JSON_ASSERT_UNREACHABLE; } return 0; // unreachable; } Value::UInt64 Value::asUInt64() const { switch ( type_ ) { case nullValue: return 0; case intValue: JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" ); return value_.int_; case uintValue: return value_.uint_; case realValue: JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt64, "Real out of UInt64 range" ); return UInt( value_.real_ ); case booleanValue: return value_.bool_ ? 1 : 0; case stringValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to UInt64" ); default: JSON_ASSERT_UNREACHABLE; } return 0; // unreachable; } # endif // if defined(JSON_HAS_INT64) LargestInt Value::asLargestInt() const { #if defined(JSON_NO_INT64) return asInt(); #else return asInt64(); #endif } LargestUInt Value::asLargestUInt() const { #if defined(JSON_NO_INT64) return asUInt(); #else return asUInt64(); #endif } double Value::asDouble() const { switch ( type_ ) { case nullValue: return 0.0; case intValue: return static_cast( value_.int_ ); case uintValue: #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) return static_cast( value_.uint_ ); #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) case realValue: return value_.real_; case booleanValue: return value_.bool_ ? 1.0 : 0.0; case stringValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to double" ); default: JSON_ASSERT_UNREACHABLE; } return 0; // unreachable; } float Value::asFloat() const { switch ( type_ ) { case nullValue: return 0.0f; case intValue: return static_cast( value_.int_ ); case uintValue: #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) return static_cast( value_.uint_ ); #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) return static_cast( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1); #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) case realValue: return static_cast( value_.real_ ); case booleanValue: return value_.bool_ ? 1.0f : 0.0f; case stringValue: case arrayValue: case objectValue: JSON_FAIL_MESSAGE( "Type is not convertible to float" ); default: JSON_ASSERT_UNREACHABLE; } return 0.0f; // unreachable; } bool Value::asBool() const { switch ( type_ ) { case nullValue: return false; case intValue: case uintValue: return value_.int_ != 0; case realValue: return value_.real_ != 0.0; case booleanValue: return value_.bool_; case stringValue: return value_.string_ && value_.string_[0] != 0; case arrayValue: case objectValue: return value_.map_->size() != 0; default: JSON_ASSERT_UNREACHABLE; } return false; // unreachable; } bool Value::isConvertibleTo( ValueType other ) const { switch ( type_ ) { case nullValue: return true; case intValue: return ( other == nullValue && value_.int_ == 0 ) || other == intValue || ( other == uintValue && value_.int_ >= 0 ) || other == realValue || other == stringValue || other == booleanValue; case uintValue: return ( other == nullValue && value_.uint_ == 0 ) || ( other == intValue && value_.uint_ <= (unsigned)maxInt ) || other == uintValue || other == realValue || other == stringValue || other == booleanValue; case realValue: return ( other == nullValue && value_.real_ == 0.0 ) || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt ) || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt ) || other == realValue || other == stringValue || other == booleanValue; case booleanValue: return ( other == nullValue && value_.bool_ == false ) || other == intValue || other == uintValue || other == realValue || other == stringValue || other == booleanValue; case stringValue: return other == stringValue || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) ); case arrayValue: return other == arrayValue || ( other == nullValue && value_.map_->size() == 0 ); case objectValue: return other == objectValue || ( other == nullValue && value_.map_->size() == 0 ); default: JSON_ASSERT_UNREACHABLE; } return false; // unreachable; } /// Number of values in array or object ArrayIndex Value::size() const { switch ( type_ ) { case nullValue: case intValue: case uintValue: case realValue: case booleanValue: case stringValue: return 0; #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: // size of the array is highest index + 1 if ( !value_.map_->empty() ) { ObjectValues::const_iterator itLast = value_.map_->end(); --itLast; return (*itLast).first.index()+1; } return 0; case objectValue: return ArrayIndex( value_.map_->size() ); #else case arrayValue: return Int( value_.array_->size() ); case objectValue: return Int( value_.map_->size() ); #endif default: JSON_ASSERT_UNREACHABLE; } return 0; // unreachable; } bool Value::empty() const { if ( isNull() || isArray() || isObject() ) return size() == 0u; else return false; } bool Value::operator!() const { return isNull(); } void Value::clear() { JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue ); switch ( type_ ) { #ifndef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: case objectValue: value_.map_->clear(); break; #else case arrayValue: value_.array_->clear(); break; case objectValue: value_.map_->clear(); break; #endif default: break; } } void Value::resize( ArrayIndex newSize ) { JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); if ( type_ == nullValue ) *this = Value( arrayValue ); #ifndef JSON_VALUE_USE_INTERNAL_MAP ArrayIndex oldSize = size(); if ( newSize == 0 ) clear(); else if ( newSize > oldSize ) (*this)[ newSize - 1 ]; else { for ( ArrayIndex index = newSize; index < oldSize; ++index ) { value_.map_->erase( index ); } assert( size() == newSize ); } #else value_.array_->resize( newSize ); #endif } Value & Value::operator[]( ArrayIndex index ) { JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); if ( type_ == nullValue ) *this = Value( arrayValue ); #ifndef JSON_VALUE_USE_INTERNAL_MAP CZString key( index ); ObjectValues::iterator it = value_.map_->lower_bound( key ); if ( it != value_.map_->end() && (*it).first == key ) return (*it).second; ObjectValues::value_type defaultValue( key, null ); it = value_.map_->insert( it, defaultValue ); return (*it).second; #else return value_.array_->resolveReference( index ); #endif } Value & Value::operator[]( int index ) { JSON_ASSERT( index >= 0 ); return (*this)[ ArrayIndex(index) ]; } const Value & Value::operator[]( ArrayIndex index ) const { JSON_ASSERT( type_ == nullValue || type_ == arrayValue ); if ( type_ == nullValue ) return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP CZString key( index ); ObjectValues::const_iterator it = value_.map_->find( key ); if ( it == value_.map_->end() ) return null; return (*it).second; #else Value *value = value_.array_->find( index ); return value ? *value : null; #endif } const Value & Value::operator[]( int index ) const { JSON_ASSERT( index >= 0 ); return (*this)[ ArrayIndex(index) ]; } Value & Value::operator[]( const char *key ) { return resolveReference( key, false ); } Value & Value::resolveReference( const char *key, bool isStatic ) { JSON_ASSERT( type_ == nullValue || type_ == objectValue ); if ( type_ == nullValue ) *this = Value( objectValue ); #ifndef JSON_VALUE_USE_INTERNAL_MAP CZString actualKey( key, isStatic ? CZString::noDuplication : CZString::duplicateOnCopy ); ObjectValues::iterator it = value_.map_->lower_bound( actualKey ); if ( it != value_.map_->end() && (*it).first == actualKey ) return (*it).second; ObjectValues::value_type defaultValue( actualKey, null ); it = value_.map_->insert( it, defaultValue ); Value &value = (*it).second; return value; #else return value_.map_->resolveReference( key, isStatic ); #endif } Value Value::get( ArrayIndex index, const Value &defaultValue ) const { const Value *value = &((*this)[index]); return value == &null ? defaultValue : *value; } bool Value::isValidIndex( ArrayIndex index ) const { return index < size(); } const Value & Value::operator[]( const char *key ) const { JSON_ASSERT( type_ == nullValue || type_ == objectValue ); if ( type_ == nullValue ) return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP CZString actualKey( key, CZString::noDuplication ); ObjectValues::const_iterator it = value_.map_->find( actualKey ); if ( it == value_.map_->end() ) return null; return (*it).second; #else const Value *value = value_.map_->find( key ); return value ? *value : null; #endif } Value & Value::operator[]( const std::string &key ) { return (*this)[ key.c_str() ]; } const Value & Value::operator[]( const std::string &key ) const { return (*this)[ key.c_str() ]; } Value & Value::operator[]( const StaticString &key ) { return resolveReference( key, true ); } # ifdef JSON_USE_CPPTL Value & Value::operator[]( const CppTL::ConstString &key ) { return (*this)[ key.c_str() ]; } const Value & Value::operator[]( const CppTL::ConstString &key ) const { return (*this)[ key.c_str() ]; } # endif Value & Value::append( const Value &value ) { return (*this)[size()] = value; } Value Value::get( const char *key, const Value &defaultValue ) const { const Value *value = &((*this)[key]); return value == &null ? defaultValue : *value; } Value Value::get( const std::string &key, const Value &defaultValue ) const { return get( key.c_str(), defaultValue ); } Value Value::removeMember( const char* key ) { JSON_ASSERT( type_ == nullValue || type_ == objectValue ); if ( type_ == nullValue ) return null; #ifndef JSON_VALUE_USE_INTERNAL_MAP CZString actualKey( key, CZString::noDuplication ); ObjectValues::iterator it = value_.map_->find( actualKey ); if ( it == value_.map_->end() ) return null; Value old(it->second); value_.map_->erase(it); return old; #else Value *value = value_.map_->find( key ); if (value){ Value old(*value); value_.map_.remove( key ); return old; } else { return null; } #endif } Value Value::removeMember( const std::string &key ) { return removeMember( key.c_str() ); } # ifdef JSON_USE_CPPTL Value Value::get( const CppTL::ConstString &key, const Value &defaultValue ) const { return get( key.c_str(), defaultValue ); } # endif bool Value::isMember( const char *key ) const { const Value *value = &((*this)[key]); return value != &null; } bool Value::isMember( const std::string &key ) const { return isMember( key.c_str() ); } # ifdef JSON_USE_CPPTL bool Value::isMember( const CppTL::ConstString &key ) const { return isMember( key.c_str() ); } #endif Value::Members Value::getMemberNames() const { JSON_ASSERT( type_ == nullValue || type_ == objectValue ); if ( type_ == nullValue ) return Value::Members(); Members members; members.reserve( value_.map_->size() ); #ifndef JSON_VALUE_USE_INTERNAL_MAP ObjectValues::const_iterator it = value_.map_->begin(); ObjectValues::const_iterator itEnd = value_.map_->end(); for ( ; it != itEnd; ++it ) members.push_back( std::string( (*it).first.c_str() ) ); #else ValueInternalMap::IteratorState it; ValueInternalMap::IteratorState itEnd; value_.map_->makeBeginIterator( it ); value_.map_->makeEndIterator( itEnd ); for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) ) members.push_back( std::string( ValueInternalMap::key( it ) ) ); #endif return members; } // //# ifdef JSON_USE_CPPTL //EnumMemberNames //Value::enumMemberNames() const //{ // if ( type_ == objectValue ) // { // return CppTL::Enum::any( CppTL::Enum::transform( // CppTL::Enum::keys( *(value_.map_), CppTL::Type() ), // MemberNamesTransform() ) ); // } // return EnumMemberNames(); //} // // //EnumValues //Value::enumValues() const //{ // if ( type_ == objectValue || type_ == arrayValue ) // return CppTL::Enum::anyValues( *(value_.map_), // CppTL::Type() ); // return EnumValues(); //} // //# endif bool Value::isNull() const { return type_ == nullValue; } bool Value::isBool() const { return type_ == booleanValue; } bool Value::isInt() const { return type_ == intValue; } bool Value::isUInt() const { return type_ == uintValue; } bool Value::isIntegral() const { return type_ == intValue || type_ == uintValue || type_ == booleanValue; } bool Value::isDouble() const { return type_ == realValue; } bool Value::isNumeric() const { return isIntegral() || isDouble(); } bool Value::isString() const { return type_ == stringValue; } bool Value::isArray() const { return type_ == nullValue || type_ == arrayValue; } bool Value::isObject() const { return type_ == nullValue || type_ == objectValue; } void Value::setComment( const char *comment, CommentPlacement placement ) { if ( !comments_ ) comments_ = new CommentInfo[numberOfCommentPlacement]; comments_[placement].setComment( comment ); } void Value::setComment( const std::string &comment, CommentPlacement placement ) { setComment( comment.c_str(), placement ); } bool Value::hasComment( CommentPlacement placement ) const { return comments_ != 0 && comments_[placement].comment_ != 0; } std::string Value::getComment( CommentPlacement placement ) const { if ( hasComment(placement) ) return comments_[placement].comment_; return ""; } std::string Value::toStyledString() const { StyledWriter writer; return writer.write( *this ); } Value::const_iterator Value::begin() const { switch ( type_ ) { #ifdef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: if ( value_.array_ ) { ValueInternalArray::IteratorState it; value_.array_->makeBeginIterator( it ); return const_iterator( it ); } break; case objectValue: if ( value_.map_ ) { ValueInternalMap::IteratorState it; value_.map_->makeBeginIterator( it ); return const_iterator( it ); } break; #else case arrayValue: case objectValue: if ( value_.map_ ) return const_iterator( value_.map_->begin() ); break; #endif default: break; } return const_iterator(); } Value::const_iterator Value::end() const { switch ( type_ ) { #ifdef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: if ( value_.array_ ) { ValueInternalArray::IteratorState it; value_.array_->makeEndIterator( it ); return const_iterator( it ); } break; case objectValue: if ( value_.map_ ) { ValueInternalMap::IteratorState it; value_.map_->makeEndIterator( it ); return const_iterator( it ); } break; #else case arrayValue: case objectValue: if ( value_.map_ ) return const_iterator( value_.map_->end() ); break; #endif default: break; } return const_iterator(); } Value::iterator Value::begin() { switch ( type_ ) { #ifdef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: if ( value_.array_ ) { ValueInternalArray::IteratorState it; value_.array_->makeBeginIterator( it ); return iterator( it ); } break; case objectValue: if ( value_.map_ ) { ValueInternalMap::IteratorState it; value_.map_->makeBeginIterator( it ); return iterator( it ); } break; #else case arrayValue: case objectValue: if ( value_.map_ ) return iterator( value_.map_->begin() ); break; #endif default: break; } return iterator(); } Value::iterator Value::end() { switch ( type_ ) { #ifdef JSON_VALUE_USE_INTERNAL_MAP case arrayValue: if ( value_.array_ ) { ValueInternalArray::IteratorState it; value_.array_->makeEndIterator( it ); return iterator( it ); } break; case objectValue: if ( value_.map_ ) { ValueInternalMap::IteratorState it; value_.map_->makeEndIterator( it ); return iterator( it ); } break; #else case arrayValue: case objectValue: if ( value_.map_ ) return iterator( value_.map_->end() ); break; #endif default: break; } return iterator(); } // class PathArgument // ////////////////////////////////////////////////////////////////// PathArgument::PathArgument() : kind_( kindNone ) { } PathArgument::PathArgument( ArrayIndex index ) : index_( index ) , kind_( kindIndex ) { } PathArgument::PathArgument( const char *key ) : key_( key ) , kind_( kindKey ) { } PathArgument::PathArgument( const std::string &key ) : key_( key.c_str() ) , kind_( kindKey ) { } // class Path // ////////////////////////////////////////////////////////////////// Path::Path( const std::string &path, const PathArgument &a1, const PathArgument &a2, const PathArgument &a3, const PathArgument &a4, const PathArgument &a5 ) { InArgs in; in.push_back( &a1 ); in.push_back( &a2 ); in.push_back( &a3 ); in.push_back( &a4 ); in.push_back( &a5 ); makePath( path, in ); } void Path::makePath( const std::string &path, const InArgs &in ) { const char *current = path.c_str(); const char *end = current + path.length(); InArgs::const_iterator itInArg = in.begin(); while ( current != end ) { if ( *current == '[' ) { ++current; if ( *current == '%' ) addPathInArg( path, in, itInArg, PathArgument::kindIndex ); else { ArrayIndex index = 0; for ( ; current != end && *current >= '0' && *current <= '9'; ++current ) index = index * 10 + ArrayIndex(*current - '0'); args_.push_back( index ); } if ( current == end || *current++ != ']' ) invalidPath( path, int(current - path.c_str()) ); } else if ( *current == '%' ) { addPathInArg( path, in, itInArg, PathArgument::kindKey ); ++current; } else if ( *current == '.' ) { ++current; } else { const char *beginName = current; while ( current != end && !strchr( "[.", *current ) ) ++current; args_.push_back( std::string( beginName, current ) ); } } } void Path::addPathInArg( const std::string &path, const InArgs &in, InArgs::const_iterator &itInArg, PathArgument::Kind kind ) { if ( itInArg == in.end() ) { // Error: missing argument %d } else if ( (*itInArg)->kind_ != kind ) { // Error: bad argument type } else { args_.push_back( **itInArg ); } } void Path::invalidPath( const std::string &path, int location ) { // Error: invalid path. } const Value & Path::resolve( const Value &root ) const { const Value *node = &root; for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) { const PathArgument &arg = *it; if ( arg.kind_ == PathArgument::kindIndex ) { if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) { // Error: unable to resolve path (array value expected at position... } node = &((*node)[arg.index_]); } else if ( arg.kind_ == PathArgument::kindKey ) { if ( !node->isObject() ) { // Error: unable to resolve path (object value expected at position...) } node = &((*node)[arg.key_]); if ( node == &Value::null ) { // Error: unable to resolve path (object has no member named '' at position...) } } } return *node; } Value Path::resolve( const Value &root, const Value &defaultValue ) const { const Value *node = &root; for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) { const PathArgument &arg = *it; if ( arg.kind_ == PathArgument::kindIndex ) { if ( !node->isArray() || node->isValidIndex( arg.index_ ) ) return defaultValue; node = &((*node)[arg.index_]); } else if ( arg.kind_ == PathArgument::kindKey ) { if ( !node->isObject() ) return defaultValue; node = &((*node)[arg.key_]); if ( node == &Value::null ) return defaultValue; } } return *node; } Value & Path::make( Value &root ) const { Value *node = &root; for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it ) { const PathArgument &arg = *it; if ( arg.kind_ == PathArgument::kindIndex ) { if ( !node->isArray() ) { // Error: node is not an array at position ... } node = &((*node)[arg.index_]); } else if ( arg.kind_ == PathArgument::kindKey ) { if ( !node->isObject() ) { // Error: node is not an object at position... } node = &((*node)[arg.key_]); } } return *node; } } // namespace Json // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_value.cpp // ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// // Beginning of content of file: src/lib_json/json_writer.cpp // ////////////////////////////////////////////////////////////////////// // Copyright 2007-2010 Baptiste Lepilleur // Distributed under MIT license, or public domain if desired and // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) # include # include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) #include #include #include #include #include #include #include #if _MSC_VER >= 1400 // VC++ 8.0 #pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. #endif namespace Json { static bool containsControlCharacter( const char* str ) { while ( *str ) { if ( isControlCharacter( *(str++) ) ) return true; } return false; } std::string valueToString( LargestInt value ) { UIntToStringBuffer buffer; char *current = buffer + sizeof(buffer); bool isNegative = value < 0; if ( isNegative ) value = -value; uintToString( LargestUInt(value), current ); if ( isNegative ) *--current = '-'; assert( current >= buffer ); return current; } std::string valueToString( LargestUInt value ) { UIntToStringBuffer buffer; char *current = buffer + sizeof(buffer); uintToString( value, current ); assert( current >= buffer ); return current; } #if defined(JSON_HAS_INT64) std::string valueToString( Int value ) { return valueToString( LargestInt(value) ); } std::string valueToString( UInt value ) { return valueToString( LargestUInt(value) ); } #endif // # if defined(JSON_HAS_INT64) std::string valueToString( double value ) { char buffer[32]; #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. sprintf_s(buffer, sizeof(buffer), "%#.16g", value); #else sprintf(buffer, "%#.16g", value); #endif char* ch = buffer + strlen(buffer) - 1; if (*ch != '0') return buffer; // nothing to truncate, so save time while(ch > buffer && *ch == '0'){ --ch; } char* last_nonzero = ch; while(ch >= buffer){ switch(*ch){ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': --ch; continue; case '.': // Truncate zeroes to save bytes in output, but keep one. *(last_nonzero+2) = '\0'; return buffer; default: return buffer; } } return buffer; } std::string valueToString( bool value ) { return value ? "true" : "false"; } std::string valueToQuotedString( const char *value ) { // Not sure how to handle unicode... if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value )) return std::string("\"") + value + "\""; // We have to walk value and escape any special characters. // Appending to std::string is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) std::string::size_type maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL std::string result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; for (const char* c=value; *c != 0; ++c) { switch(*c) { case '\"': result += "\\\""; break; case '\\': result += "\\\\"; break; case '\b': result += "\\b"; break; case '\f': result += "\\f"; break; case '\n': result += "\\n"; break; case '\r': result += "\\r"; break; case '\t': result += "\\t"; break; //case '/': // Even though \/ is considered a legal escape in JSON, a bare // slash is also legal, so I see no reason to escape it. // (I hope I am not misunderstanding something. // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); result += oss.str(); } else { result += *c; } break; } } result += "\""; return result; } // Class Writer // ////////////////////////////////////////////////////////////////// Writer::~Writer() { } // Class FastWriter // ////////////////////////////////////////////////////////////////// FastWriter::FastWriter() : yamlCompatiblityEnabled_( false ) { } void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } std::string FastWriter::write( const Value &root ) { document_ = ""; writeValue( root ); document_ += "\n"; return document_; } void FastWriter::writeValue( const Value &value ) { switch ( value.type() ) { case nullValue: document_ += "null"; break; case intValue: document_ += valueToString( value.asLargestInt() ); break; case uintValue: document_ += valueToString( value.asLargestUInt() ); break; case realValue: document_ += valueToString( value.asDouble() ); break; case stringValue: document_ += valueToQuotedString( value.asCString() ); break; case booleanValue: document_ += valueToString( value.asBool() ); break; case arrayValue: { document_ += "["; int size = value.size(); for ( int index =0; index < size; ++index ) { if ( index > 0 ) document_ += ","; writeValue( value[index] ); } document_ += "]"; } break; case objectValue: { Value::Members members( value.getMemberNames() ); document_ += "{"; for ( Value::Members::iterator it = members.begin(); it != members.end(); ++it ) { const std::string &name = *it; if ( it != members.begin() ) document_ += ","; document_ += valueToQuotedString( name.c_str() ); document_ += yamlCompatiblityEnabled_ ? ": " : ":"; writeValue( value[name] ); } document_ += "}"; } break; } } // Class StyledWriter // ////////////////////////////////////////////////////////////////// StyledWriter::StyledWriter() : rightMargin_( 74 ) , indentSize_( 3 ) { } std::string StyledWriter::write( const Value &root ) { document_ = ""; addChildValues_ = false; indentString_ = ""; writeCommentBeforeValue( root ); writeValue( root ); writeCommentAfterValueOnSameLine( root ); document_ += "\n"; return document_; } void StyledWriter::writeValue( const Value &value ) { switch ( value.type() ) { case nullValue: pushValue( "null" ); break; case intValue: pushValue( valueToString( value.asLargestInt() ) ); break; case uintValue: pushValue( valueToString( value.asLargestUInt() ) ); break; case realValue: pushValue( valueToString( value.asDouble() ) ); break; case stringValue: pushValue( valueToQuotedString( value.asCString() ) ); break; case booleanValue: pushValue( valueToString( value.asBool() ) ); break; case arrayValue: writeArrayValue( value); break; case objectValue: { Value::Members members( value.getMemberNames() ); if ( members.empty() ) pushValue( "{}" ); else { writeWithIndent( "{" ); indent(); Value::Members::iterator it = members.begin(); for (;;) { const std::string &name = *it; const Value &childValue = value[name]; writeCommentBeforeValue( childValue ); writeWithIndent( valueToQuotedString( name.c_str() ) ); document_ += " : "; writeValue( childValue ); if ( ++it == members.end() ) { writeCommentAfterValueOnSameLine( childValue ); break; } document_ += ","; writeCommentAfterValueOnSameLine( childValue ); } unindent(); writeWithIndent( "}" ); } } break; } } void StyledWriter::writeArrayValue( const Value &value ) { unsigned size = value.size(); if ( size == 0 ) pushValue( "[]" ); else { bool isArrayMultiLine = isMultineArray( value ); if ( isArrayMultiLine ) { writeWithIndent( "[" ); indent(); bool hasChildValue = !childValues_.empty(); unsigned index =0; for (;;) { const Value &childValue = value[index]; writeCommentBeforeValue( childValue ); if ( hasChildValue ) writeWithIndent( childValues_[index] ); else { writeIndent(); writeValue( childValue ); } if ( ++index == size ) { writeCommentAfterValueOnSameLine( childValue ); break; } document_ += ","; writeCommentAfterValueOnSameLine( childValue ); } unindent(); writeWithIndent( "]" ); } else // output on a single line { assert( childValues_.size() == size ); document_ += "[ "; for ( unsigned index =0; index < size; ++index ) { if ( index > 0 ) document_ += ", "; document_ += childValues_[index]; } document_ += " ]"; } } } bool StyledWriter::isMultineArray( const Value &value ) { int size = value.size(); bool isMultiLine = size*3 >= rightMargin_ ; childValues_.clear(); for ( int index =0; index < size && !isMultiLine; ++index ) { const Value &childValue = value[index]; isMultiLine = isMultiLine || ( (childValue.isArray() || childValue.isObject()) && childValue.size() > 0 ); } if ( !isMultiLine ) // check if line length > max line length { childValues_.reserve( size ); addChildValues_ = true; int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' for ( int index =0; index < size && !isMultiLine; ++index ) { writeValue( value[index] ); lineLength += int( childValues_[index].length() ); isMultiLine = isMultiLine && hasCommentForValue( value[index] ); } addChildValues_ = false; isMultiLine = isMultiLine || lineLength >= rightMargin_; } return isMultiLine; } void StyledWriter::pushValue( const std::string &value ) { if ( addChildValues_ ) childValues_.push_back( value ); else document_ += value; } void StyledWriter::writeIndent() { if ( !document_.empty() ) { char last = document_[document_.length()-1]; if ( last == ' ' ) // already indented return; if ( last != '\n' ) // Comments may add new-line document_ += '\n'; } document_ += indentString_; } void StyledWriter::writeWithIndent( const std::string &value ) { writeIndent(); document_ += value; } void StyledWriter::indent() { indentString_ += std::string( indentSize_, ' ' ); } void StyledWriter::unindent() { assert( int(indentString_.size()) >= indentSize_ ); indentString_.resize( indentString_.size() - indentSize_ ); } void StyledWriter::writeCommentBeforeValue( const Value &root ) { if ( !root.hasComment( commentBefore ) ) return; document_ += normalizeEOL( root.getComment( commentBefore ) ); document_ += "\n"; } void StyledWriter::writeCommentAfterValueOnSameLine( const Value &root ) { if ( root.hasComment( commentAfterOnSameLine ) ) document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); if ( root.hasComment( commentAfter ) ) { document_ += "\n"; document_ += normalizeEOL( root.getComment( commentAfter ) ); document_ += "\n"; } } bool StyledWriter::hasCommentForValue( const Value &value ) { return value.hasComment( commentBefore ) || value.hasComment( commentAfterOnSameLine ) || value.hasComment( commentAfter ); } std::string StyledWriter::normalizeEOL( const std::string &text ) { std::string normalized; normalized.reserve( text.length() ); const char *begin = text.c_str(); const char *end = begin + text.length(); const char *current = begin; while ( current != end ) { char c = *current++; if ( c == '\r' ) // mac or dos EOL { if ( *current == '\n' ) // convert dos EOL ++current; normalized += '\n'; } else // handle unix EOL & other char normalized += c; } return normalized; } // Class StyledStreamWriter // ////////////////////////////////////////////////////////////////// StyledStreamWriter::StyledStreamWriter( std::string indentation ) : document_(NULL) , rightMargin_( 74 ) , indentation_( indentation ) { } void StyledStreamWriter::write( std::ostream &out, const Value &root ) { document_ = &out; addChildValues_ = false; indentString_ = ""; writeCommentBeforeValue( root ); writeValue( root ); writeCommentAfterValueOnSameLine( root ); *document_ << "\n"; document_ = NULL; // Forget the stream, for safety. } void StyledStreamWriter::writeValue( const Value &value ) { switch ( value.type() ) { case nullValue: pushValue( "null" ); break; case intValue: pushValue( valueToString( value.asLargestInt() ) ); break; case uintValue: pushValue( valueToString( value.asLargestUInt() ) ); break; case realValue: pushValue( valueToString( value.asDouble() ) ); break; case stringValue: pushValue( valueToQuotedString( value.asCString() ) ); break; case booleanValue: pushValue( valueToString( value.asBool() ) ); break; case arrayValue: writeArrayValue( value); break; case objectValue: { Value::Members members( value.getMemberNames() ); if ( members.empty() ) pushValue( "{}" ); else { writeWithIndent( "{" ); indent(); Value::Members::iterator it = members.begin(); for (;;) { const std::string &name = *it; const Value &childValue = value[name]; writeCommentBeforeValue( childValue ); writeWithIndent( valueToQuotedString( name.c_str() ) ); *document_ << " : "; writeValue( childValue ); if ( ++it == members.end() ) { writeCommentAfterValueOnSameLine( childValue ); break; } *document_ << ","; writeCommentAfterValueOnSameLine( childValue ); } unindent(); writeWithIndent( "}" ); } } break; } } void StyledStreamWriter::writeArrayValue( const Value &value ) { unsigned size = value.size(); if ( size == 0 ) pushValue( "[]" ); else { bool isArrayMultiLine = isMultineArray( value ); if ( isArrayMultiLine ) { writeWithIndent( "[" ); indent(); bool hasChildValue = !childValues_.empty(); unsigned index =0; for (;;) { const Value &childValue = value[index]; writeCommentBeforeValue( childValue ); if ( hasChildValue ) writeWithIndent( childValues_[index] ); else { writeIndent(); writeValue( childValue ); } if ( ++index == size ) { writeCommentAfterValueOnSameLine( childValue ); break; } *document_ << ","; writeCommentAfterValueOnSameLine( childValue ); } unindent(); writeWithIndent( "]" ); } else // output on a single line { assert( childValues_.size() == size ); *document_ << "[ "; for ( unsigned index =0; index < size; ++index ) { if ( index > 0 ) *document_ << ", "; *document_ << childValues_[index]; } *document_ << " ]"; } } } bool StyledStreamWriter::isMultineArray( const Value &value ) { int size = value.size(); bool isMultiLine = size*3 >= rightMargin_ ; childValues_.clear(); for ( int index =0; index < size && !isMultiLine; ++index ) { const Value &childValue = value[index]; isMultiLine = isMultiLine || ( (childValue.isArray() || childValue.isObject()) && childValue.size() > 0 ); } if ( !isMultiLine ) // check if line length > max line length { childValues_.reserve( size ); addChildValues_ = true; int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' for ( int index =0; index < size && !isMultiLine; ++index ) { writeValue( value[index] ); lineLength += int( childValues_[index].length() ); isMultiLine = isMultiLine && hasCommentForValue( value[index] ); } addChildValues_ = false; isMultiLine = isMultiLine || lineLength >= rightMargin_; } return isMultiLine; } void StyledStreamWriter::pushValue( const std::string &value ) { if ( addChildValues_ ) childValues_.push_back( value ); else *document_ << value; } void StyledStreamWriter::writeIndent() { /* Some comments in this method would have been nice. ;-) if ( !document_.empty() ) { char last = document_[document_.length()-1]; if ( last == ' ' ) // already indented return; if ( last != '\n' ) // Comments may add new-line *document_ << '\n'; } */ *document_ << '\n' << indentString_; } void StyledStreamWriter::writeWithIndent( const std::string &value ) { writeIndent(); *document_ << value; } void StyledStreamWriter::indent() { indentString_ += indentation_; } void StyledStreamWriter::unindent() { assert( indentString_.size() >= indentation_.size() ); indentString_.resize( indentString_.size() - indentation_.size() ); } void StyledStreamWriter::writeCommentBeforeValue( const Value &root ) { if ( !root.hasComment( commentBefore ) ) return; *document_ << normalizeEOL( root.getComment( commentBefore ) ); *document_ << "\n"; } void StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root ) { if ( root.hasComment( commentAfterOnSameLine ) ) *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); if ( root.hasComment( commentAfter ) ) { *document_ << "\n"; *document_ << normalizeEOL( root.getComment( commentAfter ) ); *document_ << "\n"; } } bool StyledStreamWriter::hasCommentForValue( const Value &value ) { return value.hasComment( commentBefore ) || value.hasComment( commentAfterOnSameLine ) || value.hasComment( commentAfter ); } std::string StyledStreamWriter::normalizeEOL( const std::string &text ) { std::string normalized; normalized.reserve( text.length() ); const char *begin = text.c_str(); const char *end = begin + text.length(); const char *current = begin; while ( current != end ) { char c = *current++; if ( c == '\r' ) // mac or dos EOL { if ( *current == '\n' ) // convert dos EOL ++current; normalized += '\n'; } else // handle unix EOL & other char normalized += c; } return normalized; } std::ostream& operator<<( std::ostream &sout, const Value &root ) { Json::StyledStreamWriter writer; writer.write(sout, root); return sout; } } // namespace Json // ////////////////////////////////////////////////////////////////////// // End of content of file: src/lib_json/json_writer.cpp // ////////////////////////////////////////////////////////////////////// Jellyfish-2.2.8/lib/mer_dna.cc000066400000000000000000000016711323712541700161500ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include namespace jellyfish { namespace mer_dna_ns { const char* const error_different_k = "Length of k-mers are different"; const char* const error_short_string = "Input string is to short"; } } // namespace jellyfish { namespace mer_dna_ns Jellyfish-2.2.8/lib/misc.cc000066400000000000000000000053031323712541700154720ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by n the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include namespace jellyfish { uint64_t bogus_sum(void *data, size_t len) { uint64_t res = 0, tmp = 0; uint64_t *ptr = (uint64_t *)data; while(len >= sizeof(uint64_t)) { res ^= *ptr++; len -= sizeof(uint64_t); } if(len > 0) { memcpy(&tmp, ptr, len); res ^= tmp; } return res; } void disabled_misaligned_mem_access() { #if defined(__GNUC__) # if defined(__i386__) /* Enable Alignment Checking on x86 */ __asm__("pushf\norl $0x40000,(%esp)\npopf"); # elif defined(__x86_64__) /* Enable Alignment Checking on x86_64 */ __asm__("pushf\norl $0x40000,(%rsp)\npopf"); # endif #endif } // Return -1 if size cannot be obtained. std::streamoff get_file_size(std::istream& is) { if(!is.good()) return -1; std::streampos cpos = is.tellg(); if(!is.good()) { is.clear(); return -1; } is.seekg(0, std::ios::end); if(!is.good()) { is.clear(); return -1; } std::streamoff res = is.tellg() - cpos; if(!is.good()) { is.clear(); return -1; } is.seekg(cpos); return res; } template struct ConstFloorLog2 { static const int val = ConstFloorLog2::val + 1; }; template<> struct ConstFloorLog2<1> { static const int val = 0; }; // Return length random bits uint64_t random_bits(int length) { uint64_t res = 0; for(int i = 0; i < length; i += ConstFloorLog2::val) { res ^= (uint64_t)random() << i; } return res & ((uint64_t)-1 >> (bsizeof(uint64_t) - length)); } bool isblunt(char c) { return isalnum(c) || c == '_' || c == '-' || c == '/' || c == '.'; } std::string quote_arg(const std::string& arg) { if(std::all_of(arg.begin(), arg.end(), isblunt)) return arg; std::string res("'"); size_t pos = 0; while(true) { size_t qpos = arg.find_first_of("'", pos); res += arg.substr(pos, qpos - pos); if(qpos == std::string::npos) break; res += "'\\''"; pos = qpos + 1; } res += "'"; return res; } } // namespace jellyfish Jellyfish-2.2.8/lib/rectangular_binary_matrix.cc000066400000000000000000000162201323712541700217760ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include uint64_t *jellyfish::RectangularBinaryMatrix::alloc(unsigned int r, unsigned int c) { if(r > (sizeof(uint64_t) * 8) || r == 0 || c == 0) { std::ostringstream err; err << "Invalid matrix size " << r << "x" << c; throw std::out_of_range(err.str()); } void *mem; // Make sure the number of words allocated is a multiple of // 8. Necessary for loop unrolling of vector multiplication size_t alloc_columns = (c / 8 + (c % 8 != 0)) * 8; // if(posix_memalign(&mem, sizeof(uint64_t) * 2, alloc_columns * sizeof(uint64_t))) if(!(mem = aligned_alloc(sizeof(uint64_t) * 2, alloc_columns * sizeof(uint64_t)))) throw std::bad_alloc(); memset(mem, '\0', sizeof(uint64_t) * alloc_columns); return (uint64_t *)mem; } void jellyfish::RectangularBinaryMatrix::init_low_identity(bool simplify) { if(!_columns) return; if(_c == _r && simplify) { free(_columns); _columns = NULL; return; } memset(_columns, '\0', sizeof(uint64_t) * _c); unsigned int row = std::min(_c, _r); unsigned int col = _c - row; _columns[col] = (uint64_t)1 << (row - 1); for(unsigned int i = col + 1; i < _c; ++i) _columns[i] = _columns[i - 1] >> 1; } bool jellyfish::RectangularBinaryMatrix::is_low_identity() const { if(!_columns) return true; unsigned int row = std::min(_c, _r); unsigned int col = _c - row; for(unsigned int i = 0; i < col; ++i) if(_columns[i]) return false; if(_columns[col] != (uint64_t)1 << (row - 1)) return false; for(unsigned int i = col + 1; i < _c; ++i) if(_columns[i] != _columns[i - 1] >> 1) return false; return true; } jellyfish::RectangularBinaryMatrix jellyfish::RectangularBinaryMatrix::pseudo_multiplication(const jellyfish::RectangularBinaryMatrix &rhs) const { if(_r != rhs._r || _c != rhs._c) throw std::domain_error("Matrices of different size"); if(!_columns) return rhs; if(!rhs._columns) return *this; RectangularBinaryMatrix res(_r, _c); // v is a vector. The lower part is equal to the given column of rhs // and the high part is the identity matrix. // uint64_t v[nb_words()]; uint64_t *v = new uint64_t[nb_words()]; memset(v, '\0', sizeof(uint64_t) * nb_words()); unsigned int j = nb_words() - 1; v[j] = msb(); const unsigned int row = std::min(_c, _r); const unsigned int col = _c - row; unsigned int i; for(i = 0; i < col; ++i) { // Set the lower part to rhs and do vector multiplication v[0] ^= rhs[i]; res.get(i) = this->times(&v[0]); //res.get(i) = this->times_loop(v); // Zero the lower part and shift the one down the diagonal. v[0] ^= rhs[i]; v[j] >>= 1; if(!v[j]) v[--j] = (uint64_t)1 << (sizeof(uint64_t) * 8 - 1); } // No more identity part to deal with memset(v, '\0', sizeof(uint64_t) * nb_words()); for( ; i < _c; ++i) { v[0] = rhs[i]; res.get(i) = this->times(v); //res.get(i) = this->times_loop(v); } delete[] v; return res; } unsigned int jellyfish::RectangularBinaryMatrix::pseudo_rank() const { if(!_columns) return _c; unsigned int rank = _c; RectangularBinaryMatrix pivot(*this); // Make the matrix lower triangular. unsigned int srow = std::min(_r, _c); unsigned int scol = _c - srow; uint64_t mask = (uint64_t)1 << (srow - 1); for(unsigned int i = scol; i < _c; ++i, mask >>= 1) { if(!(pivot.get(i) & mask)) { // current column has a 0 in the diagonal. XOR it with another // column to get a 1. unsigned int j; for(j = i + 1; j < _c; ++j) if(pivot.get(j) & mask) break; if(j == _c) { // Did not find one, the matrix is not full rank. rank = i; break; } pivot.get(i) ^= pivot.get(j); } // Zero out every ones on the ith row in the upper part of the // matrix. for(unsigned int j = i + 1; j < _c; ++j) if(pivot.get(j) & mask) pivot.get(j) ^= pivot.get(i); } return rank; } jellyfish::RectangularBinaryMatrix jellyfish::RectangularBinaryMatrix::pseudo_inverse() const { if(!_columns) return *this; RectangularBinaryMatrix pivot(*this); RectangularBinaryMatrix res(_r, _c); res.init_low_identity(false); unsigned int i, j; uint64_t mask; // Do gaussian elimination on the columns and apply the same // operation to res. // Make pivot lower triangular. unsigned int srow = std::min(_r, _c); unsigned int scol = _c - srow; mask = (uint64_t)1 << (srow - 1); for(i = scol; i < _c; ++i, mask >>= 1) { if(!(pivot.get(i) & mask)) { // current column has a 0 in the diagonal. XOR it with another // column to get a 1. unsigned int j; for(j = i + 1; j < _c; ++j) if(pivot.get(j) & mask) break; if(j == _c) throw std::domain_error("Matrix is singular"); pivot.get(i) ^= pivot.get(j); res.get(i) ^= res.get(j); } // Zero out every ones on the ith row in the upper part of the // matrix. for(j = i + 1; j < _c; ++j) { if(pivot.get(j) & mask) { pivot.get(j) ^= pivot.get(i); res.get(j) ^= res.get(i); } } } // Make pivot the lower identity mask = (uint64_t)1 << (srow - 1); for(i = scol; i < _c; ++i, mask >>= 1) { for(j = 0; j < i; ++j) { if(pivot.get(j) & mask) { pivot.get(j) ^= pivot.get(i); res.get(j) ^= res.get(i); } } } return res; } void jellyfish::RectangularBinaryMatrix::print(std::ostream &os) const { if(!_columns) { for(unsigned int i = 0; i < _c; ++i) { for(unsigned int j = 0; j < _c; ++j) os << (i == j ? '1' : '0'); os << '\n'; } } else { uint64_t mask = (uint64_t)1 << (_r - 1); for( ; mask; mask >>= 1) { for(unsigned int j = 0; j < _c; ++j) os << (mask & _columns[j] ? '1' : '0'); os << '\n'; } } } template void jellyfish::RectangularBinaryMatrix::print_vector(std::ostream &os, const T &v) const { uint64_t mask = msb(); for(int i = nb_words() - 1; i >= 0; --i) { for( ; mask; mask >>= 1) os << (v[i] & mask ? "1" : "0"); mask = (uint64_t)1 << (sizeof(uint64_t) * 8 - 1); } os << "\n"; } jellyfish::RectangularBinaryMatrix jellyfish::RectangularBinaryMatrix::randomize_pseudo_inverse(uint64_t (*rng)()) { while(true) { randomize(rng); try { return pseudo_inverse(); } catch(std::domain_error &e) { } } } Jellyfish-2.2.8/lib/storage.cc000066400000000000000000000052331323712541700162050ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include "config.h" #include namespace jellyfish { const size_t _quadratic_reprobes[257] = { 1, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, 1326, 1378, 1431, 1485, 1540, 1596, 1653, 1711, 1770, 1830, 1891, 1953, 2016, 2080, 2145, 2211, 2278, 2346, 2415, 2485, 2556, 2628, 2701, 2775, 2850, 2926, 3003, 3081, 3160, 3240, 3321, 3403, 3486, 3570, 3655, 3741, 3828, 3916, 4005, 4095, 4186, 4278, 4371, 4465, 4560, 4656, 4753, 4851, 4950, 5050, 5151, 5253, 5356, 5460, 5565, 5671, 5778, 5886, 5995, 6105, 6216, 6328, 6441, 6555, 6670, 6786, 6903, 7021, 7140, 7260, 7381, 7503, 7626, 7750, 7875, 8001, 8128, 8256, 8385, 8515, 8646, 8778, 8911, 9045, 9180, 9316, 9453, 9591, 9730, 9870, 10011, 10153, 10296, 10440, 10585, 10731, 10878, 11026, 11175, 11325, 11476, 11628, 11781, 11935, 12090, 12246, 12403, 12561, 12720, 12880, 13041, 13203, 13366, 13530, 13695, 13861, 14028, 14196, 14365, 14535, 14706, 14878, 15051, 15225, 15400, 15576, 15753, 15931, 16110, 16290, 16471, 16653, 16836, 17020, 17205, 17391, 17578, 17766, 17955, 18145, 18336, 18528, 18721, 18915, 19110, 19306, 19503, 19701, 19900, 20100, 20301, 20503, 20706, 20910, 21115, 21321, 21528, 21736, 21945, 22155, 22366, 22578, 22791, 23005, 23220, 23436, 23653, 23871, 24090, 24310, 24531, 24753, 24976, 25200, 25425, 25651, 25878, 26106, 26335, 26565, 26796, 27028, 27261, 27495, 27730, 27966, 28203, 28441, 28680, 28920, 29161, 29403, 29646, 29890, 30135, 30381, 30628, 30876, 31125, 31375, 31626, 31878, 32131, 32385, 32640, 32896 }; const size_t *quadratic_reprobes = _quadratic_reprobes; } Jellyfish-2.2.8/lib/thread_exec.cc000066400000000000000000000027551323712541700170220ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include void jellyfish::thread_exec::exec(int nb_threads) { struct thread_info empty = {0, 0, 0}; infos.resize(nb_threads, empty); for(int i = 0; i < nb_threads; i++) { infos[i].id = i; infos[i].self = this; int err = pthread_create(&infos[i].thid, NULL, start_routine, &infos[i]); if(err) throw Error(err::msg() << "Can't create thread: " << err::no); } } void jellyfish::thread_exec::join() { for(unsigned int i = 0; i < infos.size(); i++) { int err = pthread_join(infos[i].thid, NULL); if(err) throw Error(err::msg() << "Can't join thread '" << infos[i].thid << "': " << err::no); } } void *jellyfish::thread_exec::start_routine(void *_info) { struct thread_info *info = (struct thread_info *)_info; info->self->start(info->id); return 0; } Jellyfish-2.2.8/lib/time.cc000066400000000000000000000013571323712541700155020ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include const Time Time::zero = Time(0, 0); Jellyfish-2.2.8/local.mk000066400000000000000000000001521323712541700151020ustar00rootroot00000000000000mer_counter: square_binary_matrix.o dump_stats: square_binary_matrix.o hash_merge: square_binary_matrix.o Jellyfish-2.2.8/m4/000077500000000000000000000000001323712541700140015ustar00rootroot00000000000000Jellyfish-2.2.8/m4/.gitignore000066400000000000000000000001201323712541700157620ustar00rootroot00000000000000# Ignore everything in this directory * # Except our files !.gitignore !m4-ax_* Jellyfish-2.2.8/m4/m4-ax_check_compile_flag.m4000066400000000000000000000064021323712541700210310ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 4 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS Jellyfish-2.2.8/m4/m4-ax_ext.m4000066400000000000000000000340471323712541700160610ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_ext.html # =========================================================================== # # SYNOPSIS # # AX_EXT # # DESCRIPTION # # Find supported SIMD extensions by requesting cpuid. When a SIMD # extension is found, the -m"simdextensionname" is added to SIMD_FLAGS if # compiler supports it. For example, if "sse2" is available then "-msse2" # is added to SIMD_FLAGS. # # Find other supported CPU extensions by requesting cpuid. When a # processor extension is found, the -m"extensionname" is added to # CPUEXT_FLAGS if compiler supports it. For example, if "bmi2" is # available then "-mbmi2" is added to CPUEXT_FLAGS. # # This macro calls: # # AC_SUBST(SIMD_FLAGS) # AC_SUBST(CPUEXT_FLAGS) # # And defines: # # HAVE_RDRND / HAVE_BMI1 / HAVE_BMI2 / HAVE_ADX / HAVE_MPX # HAVE_PREFETCHWT1 / HAVE_ABM / HAVE_MMX / HAVE_SSE / HAVE_SSE2 # HAVE_SSE3 / HAVE_SSSE3 / HAVE_SSE4_1 / HAVE_SSE4_2 / HAVE_SSE4a # HAVE_SHA / HAVE_AES / HAVE_AVX / HAVE_FMA3 / HAVE_FMA4 / HAVE_XOP # HAVE_AVX2 / HAVE_AVX512_F / HAVE_AVX512_CD / HAVE_AVX512_PF # HAVE_AVX512_ER / HAVE_AVX512_VL / HAVE_AVX512_BW / HAVE_AVX512_DQ # HAVE_AVX512_IFMA / HAVE_AVX512_VBMI # # LICENSE # # Copyright (c) 2007 Christophe Tournayre # Copyright (c) 2013,2015 Michael Petch # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 15 AC_DEFUN([AX_EXT], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_CC]) CPUEXT_FLAGS="" SIMD_FLAGS="" case $host_cpu in powerpc*) AC_CACHE_CHECK([whether altivec is supported], [ax_cv_have_altivec_ext], [ if test `/usr/sbin/sysctl -a 2>/dev/null| grep -c hw.optional.altivec` != 0; then if test `/usr/sbin/sysctl -n hw.optional.altivec` = 1; then ax_cv_have_altivec_ext=yes fi fi ]) if test "$ax_cv_have_altivec_ext" = yes; then AC_DEFINE(HAVE_ALTIVEC,,[Support Altivec instructions]) AX_CHECK_COMPILE_FLAG(-faltivec, SIMD_FLAGS="$SIMD_FLAGS -faltivec", []) fi ;; i[[3456]]86*|x86_64*|amd64*) AC_REQUIRE([AX_GCC_X86_CPUID]) AC_REQUIRE([AX_GCC_X86_CPUID_COUNT]) AC_REQUIRE([AX_GCC_X86_AVX_XGETBV]) eax_cpuid0=0 AX_GCC_X86_CPUID(0x00000000) if test "$ax_cv_gcc_x86_cpuid_0x00000000" != "unknown"; then eax_cpuid0=`echo $ax_cv_gcc_x86_cpuid_0x00000000 | cut -d ":" -f 1` fi eax_cpuid80000000=0 AX_GCC_X86_CPUID(0x80000000) if test "$ax_cv_gcc_x86_cpuid_0x80000000" != "unknown"; then eax_cpuid80000000=`echo $ax_cv_gcc_x86_cpuid_0x80000000 | cut -d ":" -f 1` fi ecx_cpuid1=0 edx_cpuid1=0 if test "$((0x$eax_cpuid0))" -ge 1 ; then AX_GCC_X86_CPUID(0x00000001) if test "$ax_cv_gcc_x86_cpuid_0x00000001" != "unknown"; then ecx_cpuid1=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3` edx_cpuid1=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4` fi fi ebx_cpuid7=0 ecx_cpuid7=0 if test "$((0x$eax_cpuid0))" -ge 7 ; then AX_GCC_X86_CPUID_COUNT(0x00000007, 0x00) if test "$ax_cv_gcc_x86_cpuid_0x00000007" != "unknown"; then ebx_cpuid7=`echo $ax_cv_gcc_x86_cpuid_0x00000007 | cut -d ":" -f 2` ecx_cpuid7=`echo $ax_cv_gcc_x86_cpuid_0x00000007 | cut -d ":" -f 3` fi fi ecx_cpuid80000001=0 edx_cpuid80000001=0 if test "$((0x$eax_cpuid80000000))" -ge "$((0x80000001))" ; then AX_GCC_X86_CPUID(0x80000001) if test "$ax_cv_gcc_x86_cpuid_0x80000001" != "unknown"; then ecx_cpuid80000001=`echo $ax_cv_gcc_x86_cpuid_0x80000001 | cut -d ":" -f 3` edx_cpuid80000001=`echo $ax_cv_gcc_x86_cpuid_0x80000001 | cut -d ":" -f 4` fi fi AC_CACHE_VAL([ax_cv_have_mmx_os_support_ext], [ ax_cv_have_mmx_os_support_ext=yes ]) ax_cv_have_none_os_support_ext=yes AC_CACHE_VAL([ax_cv_have_sse_os_support_ext], [ ax_cv_have_sse_os_support_ext=no, if test "$((0x$edx_cpuid1>>25&0x01))" = 1; then AC_LANG_PUSH([C]) AC_TRY_RUN([ #include #include /* No way at ring1 to ring3 in protected mode to check the CR0 and CR4 control registers directly. Execute an SSE instruction. If it raises SIGILL then OS doesn't support SSE based instructions */ void sig_handler(int signum){ exit(1); } int main(){ signal(SIGILL, sig_handler); /* SSE instruction xorps %xmm0,%xmm0 */ __asm__ __volatile__ (".byte 0x0f, 0x57, 0xc0"); return 0; }], ax_cv_have_sse_os_support_ext=yes, ax_cv_have_sse_os_support_ext=no, ax_cv_have_sse_os_support_ext=no) AC_LANG_POP([C]) fi ]) xgetbv_eax=0 if test "$((0x$ecx_cpuid1>>28&0x01))" = 1; then AX_GCC_X86_AVX_XGETBV(0x00000000) if test x"$ax_cv_gcc_x86_avx_xgetbv_0x00000000" != x"unknown"; then xgetbv_eax=`echo $ax_cv_gcc_x86_avx_xgetbv_0x00000000 | cut -d ":" -f 1` fi AC_CACHE_VAL([ax_cv_have_avx_os_support_ext], [ ax_cv_have_avx_os_support_ext=no if test "$((0x$ecx_cpuid1>>27&0x01))" = 1; then if test "$((0x$xgetbv_eax&0x6))" = 6; then ax_cv_have_avx_os_support_ext=yes fi fi ]) fi AC_CACHE_VAL([ax_cv_have_avx512_os_support_ext], [ ax_cv_have_avx512_os_support_ext=no if test "$ax_cv_have_avx_os_support_ext" = yes; then if test "$((0x$xgetbv_eax&0xe6))" = "$((0xe6))"; then ax_cv_have_avx512_os_support_ext=yes fi fi ]) for ac_instr_info dnl in "none;rdrnd;RDRND;ecx_cpuid1,30;-mrdrnd;HAVE_RDRND;CPUEXT_FLAGS" dnl "none;bmi1;BMI1;ebx_cpuid7,3;-mbmi;HAVE_BMI1;CPUEXT_FLAGS" dnl "none;bmi2;BMI2;ebx_cpuid7,8;-mbmi2;HAVE_BMI2;CPUEXT_FLAGS" dnl "none;adx;ADX;ebx_cpuid7,19;-madx;HAVE_ADX;CPUEXT_FLAGS" dnl "none;mpx;MPX;ebx_cpuid7,14;-mmpx;HAVE_MPX;CPUEXT_FLAGS" dnl "none;prefetchwt1;PREFETCHWT1;ecx_cpuid7,0;-mprefetchwt1;HAVE_PREFETCHWT1;CPUEXT_FLAGS" dnl "none;abm;ABM;ecx_cpuid80000001,5;-mabm;HAVE_ABM;CPUEXT_FLAGS" dnl "mmx;mmx;MMX;edx_cpuid1,23;-mmmx;HAVE_MMX;SIMD_FLAGS" dnl "sse;sse;SSE;edx_cpuid1,25;-msse;HAVE_SSE;SIMD_FLAGS" dnl "sse;sse2;SSE2;edx_cpuid1,26;-msse2;HAVE_SSE2;SIMD_FLAGS" dnl "sse;sse3;SSE3;ecx_cpuid1,1;-msse3;HAVE_SSE3;SIMD_FLAGS" dnl "sse;ssse3;SSSE3;ecx_cpuid1,9;-mssse3;HAVE_SSSE3;SIMD_FLAGS" dnl "sse;sse41;SSE4.1;ecx_cpuid1,19;-msse4.1;HAVE_SSE4_1;SIMD_FLAGS" dnl "sse;sse42;SSE4.2;ecx_cpuid1,20;-msse4.2;HAVE_SSE4_2;SIMD_FLAGS" dnl "sse;sse4a;SSE4a;ecx_cpuid80000001,6;-msse4a;HAVE_SSE4a;SIMD_FLAGS" dnl "sse;sha;SHA;ebx_cpuid7,29;-msha;HAVE_SHA;SIMD_FLAGS" dnl "sse;aes;AES;ecx_cpuid1,25;-maes;HAVE_AES;SIMD_FLAGS" dnl "avx;avx;AVX;ecx_cpuid1,28;-mavx;HAVE_AVX;SIMD_FLAGS" dnl "avx;fma3;FMA3;ecx_cpuid1,12;-mfma;HAVE_FMA3;SIMD_FLAGS" dnl "avx;fma4;FMA4;ecx_cpuid80000001,16;-mfma4;HAVE_FMA4;SIMD_FLAGS" dnl "avx;xop;XOP;ecx_cpuid80000001,11;-mxop;HAVE_XOP;SIMD_FLAGS" dnl "avx;avx2;AVX2;ebx_cpuid7,5;-mavx2;HAVE_AVX2;SIMD_FLAGS" dnl "avx512;avx512f;AVX512-F;ebx_cpuid7,16;-mavx512f;HAVE_AVX512_F;SIMD_FLAGS" dnl "avx512;avx512cd;AVX512-CD;ebx_cpuid7,28;-mavx512cd;HAVE_AVX512_CD;SIMD_FLAGS" dnl "avx512;avx512pf;AVX512-PF;ebx_cpuid7,26;-mavx512pf;HAVE_AVX512_PF;SIMD_FLAGS" dnl "avx512;avx512er;AVX512-ER;ebx_cpuid7,27;-mavx512er;HAVE_AVX512_ER;SIMD_FLAGS" dnl "avx512;avx512vl;AVX512-VL;ebx_cpuid7,31;-mavx512vl;HAVE_AVX512_VL;SIMD_FLAGS" dnl "avx512;avx512bw;AVX512-BW;ebx_cpuid7,30;-mavx512bw;HAVE_AVX512_BW;SIMD_FLAGS" dnl "avx512;avx512dq;AVX512-DQ;ebx_cpuid7,17;-mavx512dq;HAVE_AVX512_DQ;SIMD_FLAGS" dnl "avx512;avx512ifma;AVX512-IFMA;ebx_cpuid7,21;-mavx512ifma;HAVE_AVX512_IFMA;SIMD_FLAGS" dnl "avx512;avx512vbmi;AVX512-VBMI;ecx_cpuid7,1;-mavx512vbmi;HAVE_AVX512_VBMI;SIMD_FLAGS" dnl # do ac_instr_os_support=$(eval echo \$ax_cv_have_$(echo $ac_instr_info | cut -d ";" -f 1)_os_support_ext) ac_instr_acvar=$(echo $ac_instr_info | cut -d ";" -f 2) ac_instr_shortname=$(echo $ac_instr_info | cut -d ";" -f 3) ac_instr_chk_loc=$(echo $ac_instr_info | cut -d ";" -f 4) ac_instr_chk_reg=0x$(eval echo \$$(echo $ac_instr_chk_loc | cut -d "," -f 1)) ac_instr_chk_bit=$(echo $ac_instr_chk_loc | cut -d "," -f 2) ac_instr_compiler_flags=$(echo $ac_instr_info | cut -d ";" -f 5) ac_instr_have_define=$(echo $ac_instr_info | cut -d ";" -f 6) ac_instr_flag_type=$(echo $ac_instr_info | cut -d ";" -f 7) AC_CACHE_CHECK([whether ${ac_instr_shortname} is supported by the processor], [ax_cv_have_${ac_instr_acvar}_cpu_ext], [ eval ax_cv_have_${ac_instr_acvar}_cpu_ext=no if test "$((${ac_instr_chk_reg}>>${ac_instr_chk_bit}&0x01))" = 1 ; then eval ax_cv_have_${ac_instr_acvar}_cpu_ext=yes fi ]) if test x"$(eval echo \$ax_cv_have_${ac_instr_acvar}_cpu_ext)" = x"yes"; then AC_CACHE_CHECK([whether ${ac_instr_shortname} is supported by the processor and OS], [ax_cv_have_${ac_instr_acvar}_ext], [ eval ax_cv_have_${ac_instr_acvar}_ext=no if test x"${ac_instr_os_support}" = x"yes"; then eval ax_cv_have_${ac_instr_acvar}_ext=yes fi ]) if test "$(eval echo \$ax_cv_have_${ac_instr_acvar}_ext)" = yes; then AX_CHECK_COMPILE_FLAG(${ac_instr_compiler_flags}, eval ax_cv_support_${ac_instr_acvar}_ext=yes, eval ax_cv_support_${ac_instr_acvar}_ext=no) if test x"$(eval echo \$ax_cv_support_${ac_instr_acvar}_ext)" = x"yes"; then eval ${ac_instr_flag_type}=\"\$${ac_instr_flag_type} ${ac_instr_compiler_flags}\" AC_DEFINE_UNQUOTED([${ac_instr_have_define}]) else AC_MSG_WARN([Your processor and OS supports ${ac_instr_shortname} instructions but not your compiler, can you try another compiler?]) fi else if test x"${ac_instr_os_support}" = x"no"; then AC_CACHE_VAL(ax_cv_support_${ac_instr_acvar}_ext, eval ax_cv_support_${ac_instr_acvar}_ext=no) AC_MSG_WARN([Your processor supports ${ac_instr_shortname}, but your OS doesn't]) fi fi else AC_CACHE_VAL(ax_cv_have_${ac_instr_acvar}_ext, eval ax_cv_have_${ac_instr_acvar}_ext=no) AC_CACHE_VAL(ax_cv_support_${ac_instr_acvar}_ext, eval ax_cv_support_${ac_instr_acvar}_ext=no) fi done ;; esac AH_TEMPLATE([HAVE_RDRND],[Define to 1 to support Digital Random Number Generator]) AH_TEMPLATE([HAVE_BMI1],[Define to 1 to support Bit Manipulation Instruction Set 1]) AH_TEMPLATE([HAVE_BMI2],[Define to 1 to support Bit Manipulation Instruction Set 2]) AH_TEMPLATE([HAVE_ADX],[Define to 1 to support Multi-Precision Add-Carry Instruction Extensions]) AH_TEMPLATE([HAVE_MPX],[Define to 1 to support Memory Protection Extensions]) AH_TEMPLATE([HAVE_PREFETCHWT1],[Define to 1 to support Prefetch Vector Data Into Caches WT1]) AH_TEMPLATE([HAVE_ABM],[Define to 1 to support Advanced Bit Manipulation]) AH_TEMPLATE([HAVE_MMX],[Define to 1 to support Multimedia Extensions]) AH_TEMPLATE([HAVE_SSE],[Define to 1 to support Streaming SIMD Extensions]) AH_TEMPLATE([HAVE_SSE2],[Define to 1 to support Streaming SIMD Extensions]) AH_TEMPLATE([HAVE_SSE3],[Define to 1 to support Streaming SIMD Extensions 3]) AH_TEMPLATE([HAVE_SSSE3],[Define to 1 to support Supplemental Streaming SIMD Extensions 3]) AH_TEMPLATE([HAVE_SSE4_1],[Define to 1 to support Streaming SIMD Extensions 4.1]) AH_TEMPLATE([HAVE_SSE4_2],[Define to 1 to support Streaming SIMD Extensions 4.2]) AH_TEMPLATE([HAVE_SSE4a],[Define to 1 to support AMD Streaming SIMD Extensions 4a]) AH_TEMPLATE([HAVE_SHA],[Define to 1 to support Secure Hash Algorithm Extension]) AH_TEMPLATE([HAVE_AES],[Define to 1 to support Advanced Encryption Standard New Instruction Set (AES-NI)]) AH_TEMPLATE([HAVE_AVX],[Define to 1 to support Advanced Vector Extensions]) AH_TEMPLATE([HAVE_FMA3],[Define to 1 to support Fused Multiply-Add Extensions 3]) AH_TEMPLATE([HAVE_FMA4],[Define to 1 to support Fused Multiply-Add Extensions 4]) AH_TEMPLATE([HAVE_XOP],[Define to 1 to support eXtended Operations Extensions]) AH_TEMPLATE([HAVE_AVX2],[Define to 1 to support Advanced Vector Extensions 2]) AH_TEMPLATE([HAVE_AVX512_F],[Define to 1 to support AVX-512 Foundation Extensions]) AH_TEMPLATE([HAVE_AVX512_CD],[Define to 1 to support AVX-512 Conflict Detection Instructions]) AH_TEMPLATE([HAVE_AVX512_PF],[Define to 1 to support AVX-512 Conflict Prefetch Instructions]) AH_TEMPLATE([HAVE_AVX512_ER],[Define to 1 to support AVX-512 Exponential & Reciprocal Instructions]) AH_TEMPLATE([HAVE_AVX512_VL],[Define to 1 to support AVX-512 Vector Length Extensions]) AH_TEMPLATE([HAVE_AVX512_BW],[Define to 1 to support AVX-512 Byte and Word Instructions]) AH_TEMPLATE([HAVE_AVX512_DQ],[Define to 1 to support AVX-512 Doubleword and Quadword Instructions]) AH_TEMPLATE([HAVE_AVX512_IFMA],[Define to 1 to support AVX-512 Integer Fused Multiply Add Instructions]) AH_TEMPLATE([HAVE_AVX512_VBMI],[Define to 1 to support AVX-512 Vector Byte Manipulation Instructions]) AC_SUBST(SIMD_FLAGS) AC_SUBST(CPUEXT_FLAGS) ]) Jellyfish-2.2.8/m4/m4-ax_gcc_x86_avx_xgetbv.m4000066400000000000000000000064211323712541700207520ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_avx_xgetbv.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_AVX_XGETBV # # DESCRIPTION # # On later x86 processors with AVX SIMD support, with gcc or a compiler # that has a compatible syntax for inline assembly instructions, run a # small program that executes the xgetbv instruction with input OP. This # can be used to detect if the OS supports AVX instruction usage. # # On output, the values of the eax and edx registers are stored as # hexadecimal strings as "eax:edx" in the cache variable # ax_cv_gcc_x86_avx_xgetbv. # # If the xgetbv instruction fails (because you are running a # cross-compiler, or because you are not using gcc, or because you are on # a processor that doesn't have this instruction), # ax_cv_gcc_x86_avx_xgetbv_OP is set to the string "unknown". # # This macro mainly exists to be used in AX_EXT. # # LICENSE # # Copyright (c) 2013 Michael Petch # # 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 2 AC_DEFUN([AX_GCC_X86_AVX_XGETBV], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86-AVX xgetbv $1 output, ax_cv_gcc_x86_avx_xgetbv_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ int op = $1, eax, edx; FILE *f; /* Opcodes for xgetbv */ __asm__ __volatile__ (".byte 0x0f, 0x01, 0xd0" : "=a" (eax), "=d" (edx) : "c" (op)); f = fopen("conftest_xgetbv", "w"); if (!f) return 1; fprintf(f, "%x:%x\n", eax, edx); fclose(f); return 0; ])], [ax_cv_gcc_x86_avx_xgetbv_$1=`cat conftest_xgetbv`; rm -f conftest_xgetbv], [ax_cv_gcc_x86_avx_xgetbv_$1=unknown; rm -f conftest_xgetbv], [ax_cv_gcc_x86_avx_xgetbv_$1=unknown])]) AC_LANG_POP([C]) ]) Jellyfish-2.2.8/m4/m4-ax_gcc_x86_cpuid.m4000066400000000000000000000071641323712541700177060ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_CPUID(OP) # AX_GCC_X86_CPUID_COUNT(OP, COUNT) # # DESCRIPTION # # On Pentium and later x86 processors, with gcc or a compiler that has a # compatible syntax for inline assembly instructions, run a small program # that executes the cpuid instruction with input OP. This can be used to # detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT # parameter that gets passed into register ECX before calling cpuid. # # On output, the values of the eax, ebx, ecx, and edx registers are stored # as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable # ax_cv_gcc_x86_cpuid_OP. # # If the cpuid instruction fails (because you are running a # cross-compiler, or because you are not using gcc, or because you are on # a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP # is set to the string "unknown". # # This macro mainly exists to be used in AX_GCC_ARCHFLAG. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo # Copyright (c) 2015 Michael Petch # # 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 9 AC_DEFUN([AX_GCC_X86_CPUID], [AX_GCC_X86_CPUID_COUNT($1, 0) ]) AC_DEFUN([AX_GCC_X86_CPUID_COUNT], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ int op = $1, level = $2, eax, ebx, ecx, edx; FILE *f; __asm__ __volatile__ ("xchg %%ebx, %1\n" "cpuid\n" "xchg %%ebx, %1\n" : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) : "a" (op), "2" (level)); f = fopen("conftest_cpuid", "w"); if (!f) return 1; fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); fclose(f); return 0; ])], [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid], [ax_cv_gcc_x86_cpuid_$1=unknown])]) AC_LANG_POP([C]) ]) Jellyfish-2.2.8/m4/m4-ax_perl_ext.m4000066400000000000000000000133551323712541700171020ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_perl_ext.html # =========================================================================== # # SYNOPSIS # # AX_PERL_EXT([prefix]) # # DESCRIPTION # # Fetches the linker flags and C compiler flags for compiling and linking # Perl binary extensions. The macro substitutes PERL_EXT_PREFIX, # PERL_EXT_INC, PERL_EXT_LIB, PERL_EXT_CPPFLAGS, PERL_EXT_LDFLAGS and # PERL_EXT_DLEXT variables if Perl executable was found. It also checks # the same variables before trying to retrieve them from the Perl # configuration. # # PERL_EXT_PREFIX: top-level perl installation path (--prefix) # PERL_EXT_INC: XS include directory # PERL_EXT_LIB: Perl extensions destination directory # PERL_EXT_CPPFLAGS: C preprocessor flags to compile extensions # PERL_EXT_LDFLAGS: linker flags to build extensions # PERL_EXT_DLEXT: extensions suffix for perl modules (e.g. ".so") # # Examples: # # AX_PERL_EXT # if test x"$PERL" = x; then # AC_ERROR(["cannot find Perl"]) # fi # # LICENSE # # Copyright (c) 2011 Stanislav Sedov # Copyright (c) 2014 Thomas Klausner # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. #serial 2 AC_DEFUN([AX_PERL_EXT],[ # # Check if perl executable exists. # AC_PATH_PROGS(PERL, ["${PERL-perl}"], []) if test -n "$PERL" ; then # # Check for Perl prefix. # AC_ARG_VAR(PERL_EXT_PREFIX, [Perl PREFIX]) AC_MSG_CHECKING([for Perl prefix]) if test -z "$PERL_EXT_PREFIX" ; then [PERL_EXT_PREFIX=`$PERL -MConfig -e 'print $Config{prefix};'`]; fi AC_MSG_RESULT([$PERL_EXT_PREFIX]) AC_SUBST(PERL_EXT_PREFIX) # # Check for Perl extensions include path. # AC_ARG_VAR(PERL_EXT_INC, [Directory to include XS headers from]) AC_MSG_CHECKING([for Perl extension include path]) if test -z "$PERL_EXT_INC" ; then [PERL_EXT_INC=`$PERL -MConfig -e 'print $Config{archlibexp}, "/CORE";'`]; fi AC_MSG_RESULT([$PERL_EXT_INC]) AC_SUBST(PERL_EXT_INC) # # Check for the extensions target directory. # AC_ARG_VAR(PERL_EXT_LIB, [Directory to install perl files into]) AC_MSG_CHECKING([for Perl extension target directory]) if test -z "$PERL_EXT_LIB" ; then if test -z "$1" -o "x$1" = xNONE ; then [PERL_EXT_LIB=`$PERL -MConfig -e 'print $Config{sitearch};'`]; else [PERL_EXT_LIB=`$PERL -MConfig -e 'print $ARGV.shift, "/lib/perl/", $Config{api_versionstring};' $1`] fi fi AC_MSG_RESULT([$PERL_EXT_LIB]) AC_SUBST(PERL_EXT_LIB) # # Check for Perl CPP flags. # AC_ARG_VAR(PERL_EXT_CPPFLAGS, [CPPFLAGS to compile perl extensions]) AC_MSG_CHECKING([for Perl extensions C preprocessor flags]) if test -z "$PERL_EXT_CPPFLAGS" ; then [PERL_EXT_CPPFLAGS=`$PERL -MConfig -e 'print $Config{cppflags};'`]; fi AC_MSG_RESULT([$PERL_EXT_CPPFLAGS]) AC_SUBST(PERL_EXT_CPPFLAGS) # # Check for Perl extension link flags. # AC_ARG_VAR(PERL_EXT_LDFLAGS, [LDFLAGS to build perl extensions]) AC_MSG_CHECKING([for Perl extensions linker flags]) if test -z "$PERL_EXT_LDFLAGS" ; then [PERL_EXT_LDFLAGS=`$PERL -MConfig -e 'print $Config{lddlflags};'`]; fi # Fix LDFLAGS for OS X. We don't want any -arch flags here, otherwise # linking will fail. Also, OS X Perl LDFLAGS contains "-arch ppc" which # is not supported by XCode anymore. case "${host}" in *darwin*) PERL_EXT_LDFLAGS=`echo ${PERL_EXT_LDFLAGS} | sed -e "s,-arch [[^ ]]*,,g"` ;; esac AC_MSG_RESULT([$PERL_EXT_LDFLAGS]) AC_SUBST(PERL_EXT_LDFLAGS) fi ]) Jellyfish-2.2.8/m4/m4-ax_pkg_swig.m4000066400000000000000000000151531323712541700170700ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html # =========================================================================== # # SYNOPSIS # # AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found]) # # DESCRIPTION # # This macro searches for a SWIG installation on your system. If found, # then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is # found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd. # # You can use the optional first argument to check if the version of the # available SWIG is greater than or equal to the value of the argument. It # should have the format: N[.N[.N]] (N is a number between 0 and 999. Only # the first N is mandatory.) If the version argument is given (e.g. # 1.3.17), AX_PKG_SWIG checks that the swig package is this version number # or higher. # # As usual, action-if-found is executed if SWIG is found, otherwise # action-if-not-found is executed. # # In configure.in, use as: # # AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ]) # AX_SWIG_ENABLE_CXX # AX_SWIG_MULTI_MODULE_SUPPORT # AX_SWIG_PYTHON # # LICENSE # # Copyright (c) 2008 Sebastian Huber # Copyright (c) 2008 Alan W. Irwin # Copyright (c) 2008 Rafael Laboissiere # Copyright (c) 2008 Andrew Collier # Copyright (c) 2011 Murray Cumming # # 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 2 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 11 AC_DEFUN([AX_PKG_SWIG],[ # Ubuntu has swig 2.0 as /usr/bin/swig2.0 AC_PATH_PROGS([SWIG],[swig swig2.0]) if test -z "$SWIG" ; then m4_ifval([$3],[$3],[:]) elif test -n "$1" ; then AC_MSG_CHECKING([SWIG version]) [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] AC_MSG_RESULT([$swig_version]) if test -n "$swig_version" ; then # Calculate the required version number components [required=$1] [required_major=`echo $required | sed 's/[^0-9].*//'`] if test -z "$required_major" ; then [required_major=0] fi [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] [required_minor=`echo $required | sed 's/[^0-9].*//'`] if test -z "$required_minor" ; then [required_minor=0] fi [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] [required_patch=`echo $required | sed 's/[^0-9].*//'`] if test -z "$required_patch" ; then [required_patch=0] fi # Calculate the available version number components [available=$swig_version] [available_major=`echo $available | sed 's/[^0-9].*//'`] if test -z "$available_major" ; then [available_major=0] fi [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] [available_minor=`echo $available | sed 's/[^0-9].*//'`] if test -z "$available_minor" ; then [available_minor=0] fi [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] [available_patch=`echo $available | sed 's/[^0-9].*//'`] if test -z "$available_patch" ; then [available_patch=0] fi # Convert the version tuple into a single number for easier comparison. # Using base 100 should be safe since SWIG internally uses BCD values # to encode its version number. required_swig_vernum=`expr $required_major \* 10000 \ \+ $required_minor \* 100 \+ $required_patch` available_swig_vernum=`expr $available_major \* 10000 \ \+ $available_minor \* 100 \+ $available_patch` if test $available_swig_vernum -lt $required_swig_vernum; then AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.]) SWIG='' m4_ifval([$3],[$3],[]) else AC_MSG_CHECKING([for SWIG library]) SWIG_LIB=`$SWIG -swiglib` AC_MSG_RESULT([$SWIG_LIB]) m4_ifval([$2],[$2],[]) fi else AC_MSG_WARN([cannot determine SWIG version]) SWIG='' m4_ifval([$3],[$3],[]) fi fi AC_SUBST([SWIG_LIB]) ]) Jellyfish-2.2.8/m4/m4-ax_python_devel.m4000066400000000000000000000263311323712541700177560ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_python_devel.html # =========================================================================== # # SYNOPSIS # # AX_PYTHON_DEVEL([version], [prefix]) # # DESCRIPTION # # Note: Defines as a precious variable "PYTHON_VERSION". Don't override it # in your configure.ac. # # This macro checks for Python and tries to get the include path to # 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) # output variables. It also exports $(PYTHON_EXTRA_LIBS) and # $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. # # You can search for some particular version of Python by passing a # parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please # note that you *have* to pass also an operator along with the version to # match, and pay special attention to the single quotes surrounding the # version number. Don't use "PYTHON_VERSION" for this: that environment # variable is declared as precious and thus reserved for the end-user. # # This macro should work for all versions of Python >= 2.1.0. As an end # user, you can disable the check for the python version by setting the # PYTHON_NOVERSIONCHECK environment variable to something else than the # empty string. # # If you need to use this macro for an older Python version, please # contact the authors. We're always open for feedback. # # LICENSE # # Copyright (c) 2009 Sebastian Huber # Copyright (c) 2009 Alan W. Irwin # Copyright (c) 2009 Rafael Laboissiere # Copyright (c) 2009 Andrew Collier # Copyright (c) 2009 Matteo Settenvini # Copyright (c) 2009 Horst Knorr # Copyright (c) 2013 Daniel Mullner # # 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 17 AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) AC_DEFUN([AX_PYTHON_DEVEL],[ # # Allow the use of a (user set) custom python version # AC_ARG_VAR([PYTHON_VERSION],[The installed Python version to use, for example '2.3'. This string will be appended to the Python interpreter canonical name.]) AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) if test -z "$PYTHON"; then AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) PYTHON_VERSION="" fi # # Check for a version of Python >= 2.1.0 # AC_MSG_CHECKING([for a version of Python >= '2.1.0']) ac_supports_python_ver=`$PYTHON -c "import sys; \ ver = sys.version.split ()[[0]]; \ print (ver >= '2.1.0')"` if test "$ac_supports_python_ver" != "True"; then if test -z "$PYTHON_NOVERSIONCHECK"; then AC_MSG_RESULT([no]) AC_MSG_FAILURE([ This version of the AC@&t@_PYTHON_DEVEL macro doesn't work properly with versions of Python before 2.1.0. You may need to re-run configure, setting the variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. Moreover, to disable this check, set PYTHON_NOVERSIONCHECK to something else than an empty string. ]) else AC_MSG_RESULT([skip at user request]) fi else AC_MSG_RESULT([yes]) fi # # if the macro parameter ``version'' is set, honour it # if test -n "$1"; then AC_MSG_CHECKING([for a version of Python $1]) ac_supports_python_ver=`$PYTHON -c "import sys; \ ver = sys.version.split ()[[0]]; \ print (ver $1)"` if test "$ac_supports_python_ver" = "True"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) AC_MSG_ERROR([this package requires Python $1. If you have it installed, but it isn't the default Python interpreter in your system path, please pass the PYTHON_VERSION variable to configure. See ``configure --help'' for reference. ]) PYTHON_VERSION="" fi fi if test -n "$2" -a "x$2" != xNONE; then prefix=$2 else prefix= fi # # Check if you have distutils, else fail # AC_MSG_CHECKING([for the distutils Python package]) ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` if test -z "$ac_distutils_result"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) AC_MSG_ERROR([cannot import Python module "distutils". Please check your Python installation. The error was: $ac_distutils_result]) PYTHON_VERSION="" fi # # Check for Python include path # AC_MSG_CHECKING([for Python include path]) if test -z "$PYTHON_CPPFLAGS"; then python_path=`$PYTHON -c "import distutils.sysconfig; \ print (distutils.sysconfig.get_python_inc ());"` plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ print (distutils.sysconfig.get_python_inc (plat_specific=1));"` if test -n "${python_path}"; then if test "${plat_python_path}" != "${python_path}"; then python_path="-I$python_path -I$plat_python_path" else python_path="-I$python_path" fi fi PYTHON_CPPFLAGS=$python_path fi AC_MSG_RESULT([$PYTHON_CPPFLAGS]) AC_SUBST([PYTHON_CPPFLAGS]) # # Check for Python library path # AC_MSG_CHECKING([for Python library path]) if test -z "$PYTHON_LDFLAGS"; then # (makes two attempts to ensure we've got a version number # from the interpreter) ac_python_version=`cat< 0 and pref != '-c' else None; \ print(distutils.sysconfig.get_python_lib(0,0,pref));" $prefix` fi AC_MSG_RESULT([$PYTHON_SITE_PKG]) AC_SUBST([PYTHON_SITE_PKG]) # # libraries which must be linked in when embedding # AC_MSG_CHECKING(python extra libraries) if test -z "$PYTHON_EXTRA_LIBS"; then PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ conf = distutils.sysconfig.get_config_var; \ print (conf('LIBS') + ' ' + conf('SYSLIBS'))"` fi AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) AC_SUBST(PYTHON_EXTRA_LIBS) # # linking flags needed when embedding # AC_MSG_CHECKING(python extra linking flags) if test -z "$PYTHON_EXTRA_LDFLAGS"; then PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ conf = distutils.sysconfig.get_config_var; \ print (conf('LINKFORSHARED'))"` fi AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) AC_SUBST(PYTHON_EXTRA_LDFLAGS) # # final check to see if everything compiles alright # AC_MSG_CHECKING([consistency of all components of python development environment]) # save current global flags ac_save_LIBS="$LIBS" ac_save_CPPFLAGS="$CPPFLAGS" LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS" CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS" AC_LANG_PUSH([C]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([[#include ]], [[Py_Initialize();]]) ],[pythonexists=yes],[pythonexists=no]) AC_LANG_POP([C]) # turn back to default flags CPPFLAGS="$ac_save_CPPFLAGS" LIBS="$ac_save_LIBS" AC_MSG_RESULT([$pythonexists]) if test ! "x$pythonexists" = "xyes"; then AC_MSG_FAILURE([ Could not link test program to Python. Maybe the main Python library has been installed in some non-standard library path. If so, pass it to configure, via the LDFLAGS environment variable. Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" ============================================================================ ERROR! You probably have to install the development version of the Python package for your distribution. The exact name of this package varies among them. ============================================================================ ]) PYTHON_VERSION="" fi # # all done! # ]) Jellyfish-2.2.8/m4/m4-ax_ruby_ext.m4000066400000000000000000000125321323712541700171150ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_ruby_ext.html # =========================================================================== # # SYNOPSIS # # AX_RUBY_EXT([prefix]) # # DESCRIPTION # # Fetches the linker flags and C compiler flags for compiling and linking # Ruby binary extensions. The macro substitutes RUBY_VERSION, # RUBY_EXT_INC, RUBY_EXT_LIB, RUBY_EXT_CPPFLAGS, RUBY_EXT_LDFLAGS and # RUBY_EXT_DLEXT variables if Ruby executable has been found. It also # checks the same variables before trying to retrieve them from the Ruby # configuration. # # RUBY_VERSION: version of the Ruby interpreter # RUBY_EXT_INC: Ruby include directory # RUBY_EXT_LIB: Ruby extensions destination directory # RUBY_EXT_CPPFLAGS: C preprocessor flags to compile extensions # RUBY_EXT_LDFLAGS: linker flags to build extensions # RUBY_EXT_DLEXT: extensions suffix for ruby modules (e.g. "so") # # Examples: # # AX_RUBY_EXT # if test x"$RUBY" = x; then # AC_ERROR(["cannot find Ruby"]) # fi # # LICENSE # # Copyright (c) 2011 Stanislav Sedov # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. #serial 2 AC_DEFUN([AX_RUBY_EXT],[ # # Check if ruby executable exists. # AC_ARG_VAR([RUBY], [the Ruby interpreter]) AC_PATH_PROGS(RUBY, ["${RUBY-ruby}"], []) if test -n "$RUBY" ; then # # Check Ruby version. # AC_MSG_CHECKING([for Ruby version]) [RUBY_VERSION=`$RUBY -e 'print RUBY_VERSION'`]; AC_MSG_RESULT([$RUBY_VERSION]) AC_SUBST(RUBY_VERSION) # # Check for the extensions target directory. # AC_MSG_CHECKING([for Ruby extensions target directory]) AS_IF([test -z "$RUBY_EXT_LIB"], AS_IF([test -z "$1" -o "x$1" = xNONE], [RUBY_EXT_LIB=`$RUBY -rrbconfig -e 'print RbConfig::expand(RbConfig::CONFIG.fetch("sitearchdir"))'`], [RUBY_EXT_LIB=`$RUBY -rrbconfig -e 'print(ARGV.fetch(0), "/lib/ruby/", RbConfig::CONFIG.fetch("ruby_version"))' $1`])) AC_MSG_RESULT([$RUBY_EXT_LIB]) AC_SUBST(RUBY_EXT_LIB) # # Check for include flags # AC_MSG_CHECKING([for Ruby include directory]) AS_IF([test -z "$RUBY_EXT_CFLAGS"], [RUBY_EXT_CFLAGS="-I`$RUBY -rrbconfig -e 'print RbConfig::expand(RbConfig::CONFIG.fetch("rubyhdrdir"))'`"] [RUBY_EXT_CFLAGS="$RUBY_EXT_CFLAGS -I`$RUBY -rrbconfig -e 'print RbConfig::CONFIG.has_key?("rubyarchhdrdir") ? RbConfig::expand(RbConfig::CONFIG.fetch("rubyarchhdrdir")) : File.join(RbConfig::expand(RbConfig::CONFIG.fetch("rubyhdrdir")), RbConfig::CONFIG.fetch("arch"))'`"]) AC_MSG_RESULT([$RUBY_EXT_CFLAGS]) AC_SUBST(RUBY_EXT_CFLAGS) # # Check for lib flags # AC_MSG_CHECKING([for Ruby libs]) AS_IF([test -z "$RUBY_EXT_LIBS"], [RUBY_EXT_LIBS="`$RUBY -rrbconfig -e 'print RbConfig::expand(RbConfig::CONFIG.fetch("LIBRUBYARG_SHARED"))'` `$RUBY -rrbconfig -e 'print RbConfig::expand(RbConfig::CONFIG.fetch("LIBS"))'`"]) AC_MSG_RESULT([$RUBY_EXT_LIBS]) AC_SUBST(RUBY_EXT_LIBS) # Fix LDFLAGS for OS X. We don't want any -arch flags here, otherwise # linking might fail. We also including the proper flags to create a bundle. AC_MSG_CHECKING([for Ruby extra LDFLAGS]) case "$host" in *darwin*) RUBY_EXT_LDFLAGS=`echo ${RUBY_EXT_LDFLAGS} | sed -e "s,-arch [[^ ]]*,,g"` RUBY_EXT_LDFLAGS="${RUBY_EXT_LDFLAGS} -bundle -undefined dynamic_lookup" ;; esac AC_MSG_RESULT([$RUBY_EXT_LDFLAGS]) AC_SUBST(RUBY_EXT_LDFLAGS) fi ]) Jellyfish-2.2.8/m4/m4-ax_swig_enable_cxx.m4000066400000000000000000000042741323712541700204210ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_swig_enable_cxx.html # =========================================================================== # # SYNOPSIS # # AX_SWIG_ENABLE_CXX # # DESCRIPTION # # Enable SWIG C++ support. This affects all invocations of $(SWIG). # # LICENSE # # Copyright (c) 2008 Sebastian Huber # Copyright (c) 2008 Alan W. Irwin # Copyright (c) 2008 Rafael Laboissiere # Copyright (c) 2008 Andrew Collier # # 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 2 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 9 AU_ALIAS([SWIG_ENABLE_CXX], [AX_SWIG_ENABLE_CXX]) AC_DEFUN([AX_SWIG_ENABLE_CXX],[ AC_REQUIRE([AX_PKG_SWIG]) AC_REQUIRE([AC_PROG_CXX]) SWIG="$SWIG -c++" ]) Jellyfish-2.2.8/m4/m4-ax_swig_python.m4000066400000000000000000000055431323712541700176320ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_swig_python.html # =========================================================================== # # SYNOPSIS # # AX_SWIG_PYTHON([use-shadow-classes = {no, yes}]) # # DESCRIPTION # # Checks for Python and provides the $(AX_SWIG_PYTHON_CPPFLAGS), and # $(AX_SWIG_PYTHON_OPT) output variables. # # $(AX_SWIG_PYTHON_OPT) contains all necessary SWIG options to generate # code for Python. Shadow classes are enabled unless the value of the # optional first argument is exactly 'no'. If you need multi module # support (provided by the AX_SWIG_MULTI_MODULE_SUPPORT macro) use # $(AX_SWIG_PYTHON_LIBS) to link against the appropriate library. It # contains the SWIG Python runtime library that is needed by the type # check system for example. # # LICENSE # # Copyright (c) 2008 Sebastian Huber # Copyright (c) 2008 Alan W. Irwin # Copyright (c) 2008 Rafael Laboissiere # Copyright (c) 2008 Andrew Collier # # 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 2 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 . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 10 AU_ALIAS([SWIG_PYTHON], [AX_SWIG_PYTHON]) AC_DEFUN([AX_SWIG_PYTHON],[ AC_REQUIRE([AX_PKG_SWIG]) AC_REQUIRE([AX_PYTHON_DEVEL]) test "x$1" != "xno" || swig_shadow=" -noproxy" AC_SUBST([AX_SWIG_PYTHON_OPT],[-python$swig_shadow]) AC_SUBST([AX_SWIG_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) ]) Jellyfish-2.2.8/sub_commands/000077500000000000000000000000001323712541700161335ustar00rootroot00000000000000Jellyfish-2.2.8/sub_commands/bc_main.cc000066400000000000000000000130631323712541700200350ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace err = jellyfish::err; using std::chrono::system_clock; using std::chrono::duration; using std::chrono::duration_cast; template inline double as_seconds(DtnType dtn) { return duration_cast>(dtn).count(); } static bc_main_cmdline args; // Command line switches and arguments typedef std::vector file_vector; using jellyfish::mer_dna; using jellyfish::mer_dna_bloom_counter; typedef jellyfish::mer_overlap_sequence_parser > sequence_parser; typedef jellyfish::mer_iterator mer_iterator; template class mer_bloom_counter : public jellyfish::thread_exec { int nb_threads_; mer_dna_bloom_counter& filter_; jellyfish::stream_manager streams_; sequence_parser parser_; public: mer_bloom_counter(int nb_threads, mer_dna_bloom_counter& filter, PathIterator file_begin, PathIterator file_end, PathIterator pipe_begin, PathIterator pipe_end, uint32_t concurent_files) : filter_(filter), streams_(file_begin, file_end, pipe_begin, pipe_end, concurent_files), parser_(jellyfish::mer_dna::k(), streams_.nb_streams(), 3 * nb_threads, 4096, streams_) { } virtual void start(int thid) { for(mer_iterator mers(parser_, args.canonical_flag) ; mers; ++mers) { filter_.insert(*mers); } } }; // If get a termination signal, kill the manager and then kill myself. static pid_t manager_pid = 0; static void signal_handler(int sig) { if(manager_pid) kill(manager_pid, SIGTERM); signal(sig, SIG_DFL); kill(getpid(), sig); _exit(EXIT_FAILURE); // Should not be reached } int bc_main(int argc, char *argv[]) { auto start_time = system_clock::now(); jellyfish::file_header header; header.fill_standard(); header.set_cmdline(argc, argv); args.parse(argc, argv); mer_dna::k(args.mer_len_arg); std::unique_ptr generator_manager; if(args.generator_given) { auto gm = new jellyfish::generator_manager(args.generator_arg, args.Generators_arg, args.shell_given ? args.shell_arg : (const char*)0); generator_manager.reset(gm); generator_manager->start(); manager_pid = generator_manager->pid(); struct sigaction act; memset(&act, '\0', sizeof(act)); act.sa_handler = signal_handler; assert(sigaction(SIGTERM, &act, 0) == 0); } header.canonical(args.canonical_flag); std::ofstream output(args.output_arg); if(!output.good()) err::die(err::msg() << "Can't open output file '" << args.output_arg << "'"); header.format("bloomcounter"); header.key_len(args.mer_len_arg * 2); jellyfish::hash_pair hash_fns; header.matrix(hash_fns.m1, 1); header.matrix(hash_fns.m2, 2); mer_dna_bloom_counter filter(args.fpr_arg, args.size_arg, hash_fns); header.size(filter.m()); header.nb_hashes(filter.k()); header.write(output); auto after_init_time = system_clock::now(); // Iterators to the multi pipe paths. If no generator manager, // generate an empty range. auto pipes_begin = generator_manager.get() ? generator_manager->pipes().begin() : args.file_arg.end(); auto pipes_end = (bool)generator_manager ? generator_manager->pipes().end() : args.file_arg.end(); mer_bloom_counter counter(args.threads_arg, filter, args.file_arg.begin(), args.file_arg.end(), pipes_begin, pipes_end, args.Files_arg); counter.exec_join(args.threads_arg); // If we have a manager, wait for it if(generator_manager) { signal(SIGTERM, SIG_DFL); manager_pid = 0; if(!generator_manager->wait()) err::die("Some generator commands failed"); generator_manager.reset(); } auto after_count_time = system_clock::now(); filter.write_bits(output); output.close(); auto after_dump_time = system_clock::now(); if(args.timing_given) { std::ofstream timing_file(args.timing_arg); timing_file << "Init " << as_seconds(after_init_time - start_time) << "\n" << "Counting " << as_seconds(after_count_time - after_init_time) << "\n" << "Writing " << as_seconds(after_dump_time - after_count_time) << "\n"; } return 0; } Jellyfish-2.2.8/sub_commands/bc_main_cmdline.yaggo000066400000000000000000000030531323712541700222470ustar00rootroot00000000000000purpose "Create a bloom filter from the input k-mers" package "jellyfish bc" description "Here, a bloom filter is a data structure than can tell if a k-mer has been since 0 times, once, or at least twice. The data structure is very memory efficient but has some probability of error. After creating the bloom filter, it can be passed to the count subcommand to avoid counting most k-mers which occur only once." option("s", "size") { description "Expected number of k-mers in input" uint64; suffix; required } option("m", "mer-len") { description "Length of mer" uint32; required } option("f", "fpr") { description "False positive rate" double; default 0.001 } option("C", "canonical") { description "Count both strand, canonical representation" flag; off } option("t", "threads") { description "Number of threads" uint32; default 1 } option("output", "o") { description "Output file" c_string; default "mer_bloom_filter" } option("F", "Files") { description "Number files open simultaneously" uint32; default "1" } option("g", "generator") { description "File of commands generating fast[aq]" c_string; typestr "path" } option("G", "Generators") { description "Number of generators run simultaneously" uint32; default "1" } option("S", "shell") { description "Shell used to run generator commands ($SHELL or /bin/sh)" c_string } option("timing") { description "Print timing information" c_string; typestr "Timing file" } arg("file") { description "Sequence file(s) in fasta or fastq format" c_string; multiple; typestr "path" } Jellyfish-2.2.8/sub_commands/cite_main.cc000066400000000000000000000046771323712541700204100ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ const char *cite = "A fast, lock-free approach for efficient parallel counting of occurrences of k-mers\n" "Guillaume Marcais; Carl Kingsford\n" "Bioinformatics (2011) 27(6): 764-770 first published online January 7, 2011 doi:10.1093/bioinformatics/btr011\n"; const char *url = "http://www.cbcb.umd.edu/software/jellyfish\n" "http://bioinformatics.oxfordjournals.org/content/early/2011/01/07/bioinformatics.btr011"; const char *bibtex = "@article{Jellyfish2010,\n" " author = {Mar\\c{c}ais, Guillaume and Kingsford, Carl},\n" " title = {A fast, lock-free approach for efficient parallel counting of occurrences of k-mers},\n" " volume = {27},\n" " number = {6},\n" " pages = {764-770},\n" " year = {2011},\n" " doi = {10.1093/bioinformatics/btr011},\n" " URL = {http://bioinformatics.oxfordjournals.org/content/27/6/764.abstract},\n" " eprint = {http://bioinformatics.oxfordjournals.org/content/27/6/764.full.pdf+html},\n" " journal = {Bioinformatics}\n" "}"; #include #include #include #include #include #include #include namespace err = jellyfish::err; int cite_main(int argc, char *argv[]) { cite_main_cmdline args(argc, argv); ofstream_default out(args.output_given ? args.output_arg : 0, std::cout); if(!out.good()) err::die(err::msg() << "Can't open output file '" << args.output_arg << "'"); if(args.bibtex_flag) { out << bibtex << std::endl; } else { out << "This software has been published. If you use it for your research, cite:\n\n" << cite << "\n\n" << url << std::endl; } out.close(); return 0; } Jellyfish-2.2.8/sub_commands/cite_main_cmdline.yaggo000066400000000000000000000003471323712541700226120ustar00rootroot00000000000000purpose "How to cite Jellyfish's paper" package "jellyfish cite" description "Citation of paper" option("bibtex", "b") { description "Bibtex format" flag; off } option("output", "o") { description "Output file" c_string } Jellyfish-2.2.8/sub_commands/count_main.cc000066400000000000000000000313571323712541700206070ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include static count_main_cmdline args; // Command line switches and arguments namespace err = jellyfish::err; using std::chrono::system_clock; using std::chrono::duration; using std::chrono::duration_cast; template inline double as_seconds(DtnType dtn) { return duration_cast>(dtn).count(); } using jellyfish::mer_dna; using jellyfish::mer_dna_bloom_counter; using jellyfish::mer_dna_bloom_filter; typedef std::vector file_vector; typedef jellyfish::stream_manager stream_manager_type; // Types for parsing arbitrary sequence ignoring quality scores typedef jellyfish::mer_overlap_sequence_parser sequence_parser; typedef jellyfish::mer_iterator mer_iterator; // Types for parsing reads with quality score. Interface match type // above. class sequence_qual_parser : public jellyfish::whole_sequence_parser > { typedef jellyfish::stream_manager StreamIterator; typedef jellyfish::whole_sequence_parser super; public: sequence_qual_parser(uint16_t mer_len, uint32_t max_producers, uint32_t size, size_t buf_size, StreamIterator& streams) : super(size, 100, max_producers, streams) { } }; class mer_qual_iterator : public jellyfish::mer_qual_iterator { typedef jellyfish::mer_qual_iterator super; public: static char min_qual; mer_qual_iterator(sequence_qual_parser& parser, bool canonical = false) : super(parser, min_qual, canonical) { } }; char mer_qual_iterator::min_qual = '!'; // Phred+33 // k-mer filters. Organized in a linked list, interpreted as a && // (logical and). I.e. all filter must return true for the result to // be true. By default, filter returns true. struct filter { filter* prev_; filter(filter* prev = 0) : prev_(prev) { } virtual ~filter() { } virtual bool operator()(const mer_dna& x) { return and_res(true, x); } bool and_res(bool r, const mer_dna& x) const { return r ? (prev_ ? (*prev_)(x) : true) : false; } }; struct filter_bc : public filter { const mer_dna_bloom_counter& counter_; filter_bc(const mer_dna_bloom_counter& counter, filter* prev = 0) : filter(prev), counter_(counter) { } bool operator()(const mer_dna& m) { unsigned int c = counter_.check(m); return and_res(c > 1, m); } }; struct filter_bf : public filter { mer_dna_bloom_filter& bf_; filter_bf(mer_dna_bloom_filter& bf, filter* prev = 0) : filter(prev), bf_(bf) { } bool operator()(const mer_dna& m) { unsigned int c = bf_.insert(m); return and_res(c > 0, m); } }; enum OPERATION { COUNT, PRIME, UPDATE }; template class mer_counter_base : public jellyfish::thread_exec { int nb_threads_; mer_hash& ary_; ParserType parser_; filter* filter_; OPERATION op_; public: mer_counter_base(int nb_threads, mer_hash& ary, stream_manager_type& streams, OPERATION op, filter* filter = new struct filter) : ary_(ary) , parser_(mer_dna::k(), streams.nb_streams(), 3 * nb_threads, 4096, streams) , filter_(filter) , op_(op) { } virtual void start(int thid) { size_t count = 0; MerIteratorType mers(parser_, args.canonical_flag); switch(op_) { case COUNT: for( ; mers; ++mers) { if((*filter_)(*mers)) ary_.add(*mers, 1); ++count; } break; case PRIME: for( ; mers; ++mers) { if((*filter_)(*mers)) ary_.set(*mers); ++count; } break; case UPDATE: mer_dna tmp; for( ; mers; ++mers) { if((*filter_)(*mers)) ary_.update_add(*mers, 1, tmp); ++count; } break; } ary_.done(); } }; // Counter with and without quality value typedef mer_counter_base mer_counter; typedef mer_counter_base mer_qual_counter; mer_dna_bloom_counter* load_bloom_filter(const char* path) { std::ifstream in(path, std::ios::in|std::ios::binary); jellyfish::file_header header(in); if(!in.good()) err::die(err::msg() << "Failed to parse bloom filter file '" << path << "'"); if(header.format() != "bloomcounter") err::die(err::msg() << "Invalid format '" << header.format() << "'. Expected 'bloomcounter'"); if(header.key_len() != mer_dna::k() * 2) err::die("Invalid mer length in bloom filter"); jellyfish::hash_pair fns(header.matrix(1), header.matrix(2)); auto res = new mer_dna_bloom_counter(header.size(), header.nb_hashes(), in, fns); if(!in.good()) err::die("Bloom filter file is truncated"); in.close(); return res; } // If get a termination signal, kill the manager and then kill myself. static pid_t manager_pid = 0; static void signal_handler(int sig) { if(manager_pid) kill(manager_pid, SIGTERM); signal(sig, SIG_DFL); kill(getpid(), sig); _exit(EXIT_FAILURE); // Should not be reached } int count_main(int argc, char *argv[]) { auto start_time = system_clock::now(); jellyfish::file_header header; header.fill_standard(); header.set_cmdline(argc, argv); args.parse(argc, argv); #ifndef HAVE_HTSLIB if(args.sam_given) count_main_cmdline::error() << "SAM/BAM/CRAM not supported (missing htslib)."; #endif if(args.min_qual_char_given) { if(args.min_qual_char_arg.size() != 1) count_main_cmdline::error("[-Q, --min-qual-char] must be one character."); const char min_qual = args.min_qual_char_arg[0]; if(!isprint(min_qual)) count_main_cmdline::error () << "Invalid non-printable quality character"; if(min_qual < '!' || min_qual > '~') count_main_cmdline::error() << "Quality character '" << min_qual << "' is outside of the range [!, ~]"; mer_qual_iterator::min_qual = min_qual; } if(args.min_quality_given) { if(args.quality_start_arg < '!' || args.quality_start_arg > '~') count_main_cmdline::error() << "Quality start " << args.quality_start_arg << " is outside the range [" << (int)'!' << ", " << (int)'~' << ']'; int min_qual = args.quality_start_arg + args.min_quality_arg; if(min_qual < '!' || min_qual > '~') count_main_cmdline::error() << "Min quality " << args.min_quality_arg << " is outside the range [0, " << ((int)'~' - args.quality_start_arg) << ']'; mer_qual_iterator::min_qual = min_qual; } mer_dna::k(args.mer_len_arg); std::unique_ptr generator_manager; if(args.generator_given) { auto gm = new jellyfish::generator_manager(args.generator_arg, args.Generators_arg, args.shell_given ? args.shell_arg : (const char*)0); generator_manager.reset(gm); generator_manager->start(); manager_pid = generator_manager->pid(); struct sigaction act; memset(&act, '\0', sizeof(act)); act.sa_handler = signal_handler; assert(sigaction(SIGTERM, &act, 0) == 0); } header.canonical(args.canonical_flag); mer_hash ary(args.size_arg, args.mer_len_arg * 2, args.counter_len_arg, args.threads_arg, args.reprobes_arg); if(args.disk_flag) ary.do_size_doubling(false); std::unique_ptr > dumper; if(args.text_flag) dumper.reset(new text_dumper(args.threads_arg, args.output_arg, &header)); else dumper.reset(new binary_dumper(args.out_counter_len_arg, ary.key_len(), args.threads_arg, args.output_arg, &header)); ary.dumper(dumper.get()); auto after_init_time = system_clock::now(); OPERATION do_op = COUNT; if(args.if_given) { stream_manager_type streams(args.Files_arg); streams.paths(args.if_arg.begin(), args.if_arg.end()); mer_counter counter(args.threads_arg, ary, streams, PRIME); counter.exec_join(args.threads_arg); do_op = UPDATE; } // Iterators to the multi pipe paths. If no generator manager, // generate an empty range. auto pipes_begin = generator_manager.get() ? generator_manager->pipes().begin() : args.file_arg.end(); auto pipes_end = (bool)generator_manager ? generator_manager->pipes().end() : args.file_arg.end(); stream_manager_type streams(args.Files_arg); streams.paths(args.file_arg.begin(), args.file_arg.end()); streams.pipes(pipes_begin, pipes_end); #ifdef HAVE_HTSLIB streams.sams(args.sam_arg.begin(), args.sam_arg.end()); #endif // Bloom counter read from file to filter out low frequency // k-mers. Two pass algorithm. std::unique_ptr mer_filter(new filter); std::unique_ptr bc; if(args.bc_given) { bc.reset(load_bloom_filter(args.bc_arg)); mer_filter.reset(new filter_bc(*bc)); } // Bloom filter to filter out low frequency k-mers. One pass // algorithm. std::unique_ptr bf; if(args.bf_size_given) { bf.reset(new mer_dna_bloom_filter(args.bf_fp_arg, args.bf_size_arg)); mer_filter.reset(new filter_bf(*bf)); } if(args.min_qual_char_given || args.min_quality_given) { mer_qual_counter counter(args.threads_arg, ary, streams, do_op, mer_filter.get()); counter.exec_join(args.threads_arg); } else { mer_counter counter(args.threads_arg, ary, streams, do_op, mer_filter.get()); counter.exec_join(args.threads_arg); } // If we have a manager, wait for it if(generator_manager) { signal(SIGTERM, SIG_DFL); manager_pid = 0; if(!generator_manager->wait()) err::die("Some generator commands failed"); generator_manager.reset(); } auto after_count_time = system_clock::now(); // If no intermediate files, dump directly into output file. If not, will do a round of merging if(!args.no_write_flag) { if(dumper->nb_files() == 0) { dumper->one_file(true); if(args.lower_count_given) dumper->min(args.lower_count_arg); if(args.upper_count_given) dumper->max(args.upper_count_arg); dumper->dump(ary.ary()); } else { dumper->dump(ary.ary()); if(!args.no_merge_flag) { std::vector files = dumper->file_names_cstr(); uint64_t min = args.lower_count_given ? args.lower_count_arg : 0; uint64_t max = args.upper_count_given ? args.upper_count_arg : std::numeric_limits::max(); try { merge_files(files, args.output_arg, header, min, max); } catch(MergeError e) { err::die(err::msg() << e.what()); } if(!args.no_unlink_flag) { for(int i =0; i < dumper->nb_files(); ++i) unlink(files[i]); } } // if(!args.no_merge_flag } // if(!args.no_merge_flag } auto after_dump_time = system_clock::now(); if(args.timing_given) { std::ofstream timing_file(args.timing_arg); timing_file << "Init " << as_seconds(after_init_time - start_time) << "\n" << "Counting " << as_seconds(after_count_time - after_init_time) << "\n" << "Writing " << as_seconds(after_dump_time - after_count_time) << "\n"; } return 0; } Jellyfish-2.2.8/sub_commands/count_main_cmdline.yaggo000066400000000000000000000072461323712541700230230ustar00rootroot00000000000000purpose "Count k-mers in fasta or fastq files" package "jellyfish count" option("mer-len", "m") { description "Length of mer" uint32; required } option("size", "s") { description "Initial hash size" uint64; suffix; required } option("threads", "t") { description "Number of threads" uint32; default "1" } option("sam") { description "SAM/BAM/CRAM formatted input file" multiple; c_string; typestr "PATH" } option("F", "Files") { description "Number files open simultaneously" uint32; default "1" } option("g", "generator") { description "File of commands generating fast[aq]" c_string; typestr "path" } option("G", "Generators") { description "Number of generators run simultaneously" uint32; default "1" } option("S", "shell") { description "Shell used to run generator commands ($SHELL or /bin/sh)" c_string } option("output", "o") { description "Output file" c_string; default "mer_counts.jf" } option("counter-len", "c") { description "Length bits of counting field" uint32; default "7"; typestr "Length in bits" } option("out-counter-len") { description "Length in bytes of counter field in output" uint32; default "4"; typestr "Length in bytes" } option("C", "canonical") { description "Count both strand, canonical representation" flag; off } option("bc") { description "Bloom counter to filter out singleton mers" c_string; typestr "peath"; } option("bf-size") { description "Use bloom filter to count high-frequency mers" uint64; suffix; conflict "bc" } option("bf-fp") { description "False positive rate of bloom filter" double; default 0.01 } option("if") { description "Count only k-mers in this files" c_string; typestr "path"; multiple } option("Q", "min-qual-char") { description "Any base with quality below this character is changed to N" string } option("quality-start") { description "ASCII for quality values" int32; default 64; conflict "min-qual-char" } option("min-quality") { description "Minimum quality. A base with lesser quality becomes an N" int32; conflict "min-qual-char" } option("reprobes", "p") { description "Maximum number of reprobes" uint32; default "126" } option("text") { description "Dump in text format" off } option("disk") { description "Disk operation. Do not do size doubling" off } option("no-merge") { description "Do not merge files intermediary files" off; hidden } option("no-unlink") { description "Do not unlink intermediary files after automatic merging" off; hidden } # option("raw", "r") { # description "Write raw database" # flag; off } # option("both") { # description "Write sorted list and raw database" # flag; off; hidden } # option("quality-start") { # description "Starting ASCII for quality values" # uint32; default "64" } # option("min-quality") { # description "Minimum quality. A base with lesser quality becomes an N" # uint32; default "0" } option("lower-count", "L") { description "Don't output k-mer with count < lower-count" uint64 } option("upper-count", "U") { description "Don't output k-mer with count > upper-count" uint64 } # option("invalid-char") { # description "How to treat invalid characters. The char is changed to a N." # enum "warn", "ignore", "error" } # option("matrix") { # description "Hash function binary matrix" # string; typestr "Matrix file" } option("timing") { description "Print timing information" c_string; typestr "Timing file" } # option("stats") { # description "Print stats" # c_string; typestr "Stats file" } option("no-write") { description "Don't write database" flag; off; hidden } arg("file") { description "Sequence file(s) in fasta or fastq format" c_string; multiple; typestr "path" } Jellyfish-2.2.8/sub_commands/dump_main.cc000066400000000000000000000053541323712541700204220ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include namespace err = jellyfish::err; static dump_main_cmdline args; // Command line switches and arguments template void dump(iterator& it, std::ostream &out, uint64_t lower_count, uint64_t upper_count) { if(args.column_flag) { char spacer = args.tab_flag ? '\t' : ' '; while(it.next()) { if(it.val() < lower_count || it.val() > upper_count) continue; out << it.key() << spacer << it.val() << "\n"; } } else { while(it.next()) { if(it.val() < lower_count || it.val() > upper_count) continue; out << ">" << it.val() << "\n" << it.key() << "\n"; } } } int dump_main(int argc, char *argv[]) { args.parse(argc, argv); std::ios::sync_with_stdio(false); // No sync with stdio -> faster ofstream_default out(args.output_given ? args.output_arg : 0, std::cout); if(!out.good()) err::die(err::msg() << "Error opening output file '" << args.output_arg << "'"); std::ifstream is(args.db_arg); if(!is.good()) err::die(err::msg() << "Failed to open input file '" << args.db_arg << "'"); jellyfish::file_header header; header.read(is); jellyfish::mer_dna::k(header.key_len() / 2); if(!args.lower_count_given) args.lower_count_arg = 0; if(!args.upper_count_given) args.upper_count_arg = std::numeric_limits::max(); if(!header.format().compare(binary_dumper::format)) { binary_reader reader(is, &header); dump(reader, out, args.lower_count_arg, args.upper_count_arg); } else if(!header.format().compare(text_dumper::format)) { text_reader reader(is, &header); dump(reader, out, args.lower_count_arg, args.upper_count_arg); } else { err::die(err::msg() << "Unknown format '" << header.format() << "'"); } out.close(); return 0; } Jellyfish-2.2.8/sub_commands/dump_main_cmdline.yaggo000066400000000000000000000013041323712541700226250ustar00rootroot00000000000000purpose "Dump k-mer counts" package "jellyfish dump" description "By default, dump in a fasta format where the header is the count and the sequence is the sequence of the k-mer. The column format is a 2 column output: k-mer count." option("column", "c") { description "Column format" flag; off } option("tab", "t") { description "Tab separator" flag; off } option("lower-count", "L") { description "Don't output k-mer with count < lower-count" uint64; } option("upper-count", "U") { description "Don't output k-mer with count > upper-count" uint64 } option("output", "o") { description "Output file" c_string } arg("db") { description "Jellyfish database" c_string; typestr "path" } Jellyfish-2.2.8/sub_commands/histo_main.cc000066400000000000000000000057211323712541700206010ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include namespace err = jellyfish::err; template void compute_histo(reader_type& reader, const uint64_t base, const uint64_t ceil, uint64_t* histo, const uint64_t nb_buckets, const uint64_t inc) { while(reader.next()) { if(reader.val() < base) ++histo[0]; else if(reader.val() > ceil) ++histo[nb_buckets - 1]; else ++histo[(reader.val() - base) / inc]; } } int histo_main(int argc, char *argv[]) { histo_main_cmdline args(argc, argv); std::ifstream is(args.db_arg); if(!is.good()) err::die(err::msg() << "Failed to open input file '" << args.db_arg << "'"); jellyfish::file_header header; header.read(is); jellyfish::mer_dna::k(header.key_len() / 2); if(args.high_arg < args.low_arg) histo_main_cmdline::error("High count value must be >= to low count value"); ofstream_default out(args.output_given ? args.output_arg : 0, std::cout); if(!out.good()) err::die(err::msg() << "Error opening output file '" << args.output_arg << "'"); const uint64_t base = args.increment_arg >= args.low_arg ? 0 : args.low_arg - args.increment_arg; const uint64_t ceil = args.high_arg + args.increment_arg; const uint64_t inc = args.increment_arg; const uint64_t nb_buckets = (ceil + inc - base) / inc; uint64_t* histo = new uint64_t[nb_buckets]; memset(histo, '\0', sizeof(uint64_t) * nb_buckets); if(!header.format().compare(binary_dumper::format)) { binary_reader reader(is, &header); compute_histo(reader, base, ceil, histo, nb_buckets, inc); } else if(!header.format().compare(text_dumper::format)) { text_reader reader(is, &header); compute_histo(reader, base, ceil, histo, nb_buckets, inc); } else { err::die(err::msg() << "Unknown format '" << header.format() << "'"); } for(uint64_t i = 0, col = base; i < nb_buckets; ++i, col += inc) if(histo[i] > 0 || args.full_flag) out << col << " " << histo[i] << "\n"; delete [] histo; out.close(); return 0; } Jellyfish-2.2.8/sub_commands/histo_main_cmdline.yaggo000066400000000000000000000024101323712541700230050ustar00rootroot00000000000000purpose "Create an histogram of k-mer occurrences" package "jellyfish histo" description "Create an histogram with the number of k-mers having a given count. In bucket 'i' are tallied the k-mers which have a count 'c' satisfying 'low+i*inc <= c < low+(i+1)*inc'. Buckets in the output are labeled by the low end point (low+i*inc). The last bucket in the output behaves as a catchall: it tallies all k-mers with a count greater or equal to the low end point of this bucket." option("low", "l") { description "Low count value of histogram" uint64; default "1" } option("high", "h") { description "High count value of histogram" uint64; default "10000" } option("increment", "i") { description "Increment value for buckets" uint64; default "1" } option("threads", "t") { description "Number of threads" uint32; default "1" } option("full", "f") { description "Full histo. Don't skip count 0." flag; off } option("output", "o") { description "Output file" c_string } option("buffer-size", "s") { description "Length in bytes of input buffer" uint64; default "10000000"; suffix; hidden; typestr "Buffer length" } option("verbose", "v") { description "Output information" flag; off } arg("db") { description "Jellyfish database" c_string; typestr "path" } Jellyfish-2.2.8/sub_commands/info_main.cc000066400000000000000000000026501323712541700204040ustar00rootroot00000000000000#include #include #include #include #include #include #include namespace err = jellyfish::err; static info_main_cmdline args; std::string get_command(const jellyfish::generic_file_header& h) { std::string cmd(h["exe_path"]); std::vector cmdline = h.cmdline(); for(auto it = cmdline.cbegin(); it != cmdline.cend(); ++it) (cmd += " ") += jellyfish::quote_arg(*it); return cmd; } std::string get_where(const jellyfish::generic_file_header& h) { std::string res(jellyfish::quote_arg(h["hostname"])); if(!res.empty()) res += ":"; res += jellyfish::quote_arg(h["pwd"]); return res; } int info_main(int argc, char *argv[]) { args.parse(argc, argv); std::ifstream file(args.file_arg); if(!file.good()) err::die(err::msg() << "Can't open '" << args.file_arg << "'"); jellyfish::file_header header; header.read(file); if(args.skip_flag) std::cout << file.rdbuf(); else if(args.json_flag) std::cout << header; else if(args.cmd_flag) std::cout << get_command(header) << "\n"; else std::cout << "command: " << get_command(header) << "\n" << "where: " << get_where(header) << "\n" << "when: " << header["time"] << "\n" << "canonical: " << (header.canonical() ? "yes" : "no") << "\n"; return 0; } Jellyfish-2.2.8/sub_commands/info_main_cmdline.yaggo000066400000000000000000000011751323712541700226210ustar00rootroot00000000000000purpose "Display information about a jellyfish file" package "jellyfish info" description "This command shows some information about how this jellyfish output file was created. Without any argument, it displays the command line used, when and where it was run." option("s", "skip") { description "Skip header and dump remainder of file" off } option("j", "json") { description "Dump full header in JSON format" off conflict "skip" } option("c", "cmd") { description "Display only the command line" off conflict "skip", "json" } arg("file") { description "Input file in jellyfish format" c_string; typestr "path" } Jellyfish-2.2.8/sub_commands/jellyfish.cc000066400000000000000000000112571323712541700204410ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include typedef int (main_func_t)(int argc, char *argv[]); main_func_t count_main; main_func_t bc_main; main_func_t info_main; main_func_t stats_main; main_func_t merge_main; main_func_t histo_main; main_func_t query_main; main_func_t dump_main; main_func_t cite_main; main_func_t mem_main; // main_func_t dump_fastq_main; // main_func_t histo_fastq_main; // main_func_t hash_fastq_merge_main; main_func_t sos; main_func_t version; main_func_t jf_main; struct cmd_func { const char *cmd; // std::string cmd; main_func_t *func; }; cmd_func cmd_list[] = { {"count", &count_main}, {"bc", &bc_main}, {"info", &info_main}, {"stats", &stats_main}, {"histo", &histo_main}, {"dump", &dump_main}, {"merge", &merge_main}, {"query", &query_main}, {"cite", &cite_main}, {"mem", &mem_main}, // {"qhisto", &histo_fastq_main}, // {"qdump", &dump_fastq_main}, // {"qmerge", &hash_fastq_merge_main}, {"jf", &jf_main}, /* help in all its form. Must be first non-command */ {"help", &sos}, {"-h", &sos}, {"-help", &sos}, {"--help", &sos}, {"-?", &sos}, {"--version", &version}, {"-V", &version}, {"", 0} }; void __sos(std::ostream *os) { *os << "Usage: jellyfish [options] arg..." << std::endl << "Where is one of: "; bool comma = false; for(cmd_func *ccmd = cmd_list; ccmd->func != sos; ccmd++) { *os << (comma ? ", " : "") << ccmd->cmd; comma = true; } *os << "." << std::endl; *os << "Options:" << std::endl << " --version Display version" << std::endl << " --help Display this message" << std::endl; } int jf_main(int argc, char* argv[]) { const char* aa = " .......\n" " .......... .....\n" " .... ....\n" " .. /-+ +---\\ ...\n" " . /--| +----\\ ...\n" " .. ...\n" " . .\n" " .. +----------------+ .\n" " . |. AAGATGGAGCGC .| ..\n" " . |---. .--/ .\n" " .. \\--------/ . .\n" " . . .. .. .\n" " . ... ..... ..... .. ..\n" " . .. . . . .. . .... .\n" " . .. . .. . . .. . . .\n" " . .. . . ... . .. .. .\n" " .... . .. .. ... .. .\n" " .. . ... . .. .. .\n" " . .. . . . ... ..\n" " ... . . .. ... .\n" " . .. . .. .....\n" " ____ ____ ._ __ _ _ ____ ____ ___ _ _\n" " (_ _)( ___)( ) ( ) ( \\/ )( ___)(_ _)/ __)( )_( )\n" ".-_)( )__) )(__ )(__ \\ / )__) _)(_ \\__ \\ ) _ ( \n" "\\____) (____)(____)(____)(__) (__) (____)(___/(_) (_)\n"; std::cout << aa; return 0; } int sos(int argc, char *argv[]) { __sos(&std::cout); return 0; } int version(int argc, char *argv[]) { #ifdef PACKAGE_STRING std::cout << PACKAGE_STRING << std::endl; #else std::cout << "no version" << std::endl; #endif return 0; } int main(int argc, char *argv[]) { std::string error; if(argc < 2) { error = "Too few arguments"; } else { for(cmd_func *ccmd = cmd_list; ccmd->func != 0; ccmd++) { if(!strcmp(ccmd->cmd, argv[1])) // if(!ccmd->cmd.compare(argv[1])) return ccmd->func(argc - 1, argv + 1); } error = "Unknown command '"; error += argv[1]; error += "'\n"; } std::cerr << error << std::endl; __sos(&std::cerr); return 1; } Jellyfish-2.2.8/sub_commands/mem_main.cc000066400000000000000000000031541323712541700202270ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include static const char* suffixes = "kMGTPE"; template std::string add_suffix(uint64_t x) { const int max_i = strlen(suffixes); int i = 0; while(x >= U && i <= max_i) { x /= U; ++i; } std::ostringstream res; res << x; if(i > 0) res << suffixes[i - 1]; return res.str(); } int mem_main(int argc, char *argv[]) { mem_main_cmdline args(argc, argv); jellyfish::large_hash::array::usage_info usage(args.mer_len_arg * 2, args.counter_len_arg, args.reprobes_arg); if(args.size_given) { uint64_t val = usage.mem(args.size_arg); std::cout << val << " (" << add_suffix<1024>(val) << ")\n"; } else { uint64_t val = usage.size(args.mem_arg); std::cout << val << " (" << add_suffix<1000>(val) << ")\n"; } return 0; } Jellyfish-2.2.8/sub_commands/mem_main_cmdline.yaggo000066400000000000000000000074261323712541700224510ustar00rootroot00000000000000purpose "Give memory usage information" package "jellyfish mem" description "The mem subcommand gives some information about the memory usage of Jellyfish when counting mers. If one replace 'count' by 'mem' in the command line, it displays the amount of memory needed. All the switches of the count subcommand are supported, although only the meaningful one for computing the memory usage are used. If the '--size' (-s) switch is omitted and the --mem switch is passed with an amount of memory in bytes, then the largest size that fit in that amount of memory is returned. The memory usage information only takes into account the hash to store the k-mers, not various buffers (e.g. in parsing the input files). But typically those will be small in comparison to the hash." option("mer-len", "m") { description "Length of mer" uint32; required } option("size", "s") { description "Initial hash size" uint64; suffix } option("counter-len", "c") { description "Length bits of counting field" uint32; default "7"; typestr "Length in bits" } option("reprobes", "p") { description "Maximum number of reprobes" uint32; default "126" } option("mem") { description "Return maximum size to fit within that memory" uint64; suffix; conflict "size" } option("threads", "t") { description "Ignored switch" uint32; hidden } option("F", "Files") { description "Ignored switch" uint32; hidden } option("g", "generator") { description "Ignored switch" c_string; typestr "path"; hidden } option("G", "Generators") { description "Ignored switch" uint32; hidden } option("S", "shell") { description "Ignored switch" c_string; hidden } option("output", "o") { description "Ignored switch" c_string; hidden } option("out-counter-len") { description "Ignored switch" uint32; hidden } option("C", "canonical") { description "Ignored switch" flag; off; hidden } option("bc") { description "Ignored switch" c_string; typestr "peath"; } option("bf-size") { description "Ignored switch" uint64; suffix; conflict "bc"; hidden } option("bf-fp") { description "Ignored switch" double; default 0.01; hidden } option("if") { description "Ignored switch" c_string; typestr "path"; multiple; hidden } option("Q", "min-qual-char") { description "Ignored switch" string; hidden } option("text") { description "Ignored switch" off; hidden } option("disk") { description "Ignored switch" off; hidden } option("no-merge") { description "Ignored switch" off; hidden; hidden } option("no-unlink") { description "Ignored switch" off; hidden } # option("raw", "r") { # description "Ignored switch" "Write raw database" # flag; off } # option("both") { # description "Ignored switch" "Write sorted list and raw database" # flag; off; hidden } # option("quality-start") { # description "Ignored switch" "Starting ASCII for quality values" # uint32; default "64" } # option("min-quality") { # description "Ignored switch" "Minimum quality. A base with lesser quality becomes an N" # uint32; default "0" } option("lower-count", "L") { description "Ignored switch" uint64; hidden } option("upper-count", "U") { description "Ignored switch" uint64; hidden } # option("invalid-char") { # description "Ignored switch" "How to treat invalid characters. The char is changed to a N." # enum "warn", "ignore", "error" } # option("matrix") { # description "Ignored switch" "Hash function binary matrix" # string; typestr "Matrix file" } option("timing") { description "Ignored switch" c_string; typestr "Timing file"; hidden } # option("stats") { # description "Ignored switch" "Print stats" # c_string; typestr "Stats file" } option("no-write") { description "Ignored switch" flag; off; hidden } arg("file") { description "Ignored switch" c_string; multiple; typestr "path" } Jellyfish-2.2.8/sub_commands/merge_main.cc000066400000000000000000000025211323712541700205450ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include namespace err = jellyfish::err; int merge_main(int argc, char *argv[]) { jellyfish::file_header out_header; out_header.fill_standard(); out_header.set_cmdline(argc, argv); merge_main_cmdline args(argc, argv); uint64_t min = args.lower_count_given ? args.lower_count_arg : 0; uint64_t max = args.upper_count_given ? args.upper_count_arg : std::numeric_limits::max(); try { merge_files(args.input_arg, args.output_arg, out_header, min, max); } catch(MergeError e) { err::die(err::msg() << e.what()); } return 0; } Jellyfish-2.2.8/sub_commands/merge_main_cmdline.yaggo000066400000000000000000000006711323712541700227650ustar00rootroot00000000000000purpose "Merge jellyfish databases" package "jellyfish merge" option("output", "o") { description "Output file" c_string; default "mer_counts_merged.jf" } option("lower-count", "L") { description "Don't output k-mer with count < lower-count" uint64 } option("upper-count", "U") { description "Don't output k-mer with count > upper-count" uint64 } arg("input") { description "Jellyfish hash" c_string; multiple; at_least 2 } Jellyfish-2.2.8/sub_commands/query_main.cc000066400000000000000000000113521323712541700206150ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include namespace err = jellyfish::err; using jellyfish::mer_dna; using jellyfish::mer_dna_bloom_counter; typedef std::vector file_vector; typedef jellyfish::mer_overlap_sequence_parser > sequence_parser; typedef jellyfish::mer_iterator mer_iterator; static query_main_cmdline args; // mer_dna_bloom_counter query_load_bloom_filter(const char* path) { // return res; // } template void query_from_sequence(PathIterator file_begin, PathIterator file_end, const Database& db, std::ostream& out, bool canonical) { jellyfish::stream_manager streams(file_begin, file_end); sequence_parser parser(mer_dna::k(), 1, 3, 4096, streams); for(mer_iterator mers(parser, canonical); mers; ++mers) out << *mers << " " << db.check(*mers) << "\n"; } template void query_from_cmdline(std::vector mers, const Database& db, std::ostream& out, bool canonical) { mer_dna m; for(auto it = mers.cbegin(); it != mers.cend(); ++it) { try { m = *it; if(canonical) m.canonicalize(); out << m << " " << db.check(m) << "\n"; } catch(std::length_error e) { std::cerr << "Invalid mer '" << *it << "'\n"; } } } template void query_from_stdin(const Database& db, std::ostream& out, bool canonical) { std::string buffer; mer_dna m; while(getline(std::cin, buffer)) { try { m = buffer; if(canonical) m.canonicalize(); out << db.check(m) << std::endl; // a flush is need for interactive use } catch(std::length_error e) { std::cerr << "Invalid mer '" << buffer << "'" << std::endl; } } } int query_main(int argc, char *argv[]) { args.parse(argc, argv); ofstream_default out(args.output_given ? args.output_arg : 0, std::cout); if(!out.good()) err::die(err::msg() << "Error opening output file '" << args.output_arg << "'"); std::ifstream in(args.file_arg, std::ios::in|std::ios::binary); jellyfish::file_header header(in); if(!in.good()) err::die(err::msg() << "Failed to parse header of file '" << args.file_arg << "'"); mer_dna::k(header.key_len() / 2); if(header.format() == "bloomcounter") { jellyfish::hash_pair fns(header.matrix(1), header.matrix(2)); mer_dna_bloom_counter filter(header.size(), header.nb_hashes(), in, fns); if(!in.good()) err::die("Bloom filter file is truncated"); in.close(); query_from_sequence(args.sequence_arg.begin(), args.sequence_arg.end(), filter, out, header.canonical()); query_from_cmdline(args.mers_arg, filter, out, header.canonical()); if(args.interactive_flag) query_from_stdin(filter, out, header.canonical()); } else if(header.format() == binary_dumper::format) { jellyfish::mapped_file binary_map(args.file_arg); if(!args.no_load_flag && (args.load_flag || (args.sequence_arg.begin() != args.sequence_arg.end()) || (args.mers_arg.size() > 100))) binary_map.load(); binary_query bq(binary_map.base() + header.offset(), header.key_len(), header.counter_len(), header.matrix(), header.size() - 1, binary_map.length() - header.offset()); query_from_sequence(args.sequence_arg.begin(), args.sequence_arg.end(), bq, out, header.canonical()); query_from_cmdline(args.mers_arg, bq, out, header.canonical()); if(args.interactive_flag) query_from_stdin(bq, out, header.canonical()); } else { err::die(err::msg() << "Unsupported format '" << header.format() << "'. Must be a bloom counter or binary list."); } return 0; } Jellyfish-2.2.8/sub_commands/query_main_cmdline.yaggo000066400000000000000000000012751323712541700230340ustar00rootroot00000000000000purpose "Query a Jellyfish database" package "jellyfish query" option("s", "sequence") { description "Output counts for all mers in sequence" c_string; typestr "path"; multiple } option("o", "output") { description "Output file (stdout)" c_string; typestr "path" } option("i", "interactive") { description "Interactive, queries from stdin" flag; off } option("l", "load") { description "Force pre-loading of database file into memory" off } option("L", "no-load") { description "Disable pre-loading of database file into memory" off } arg("file") { description "Jellyfish database" c_string; typestr "path" } arg("mers") { description "mers to query" c_string; multiple } Jellyfish-2.2.8/sub_commands/stats_main.cc000066400000000000000000000053461323712541700206140ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include namespace err = jellyfish::err; template void compute_stats(reader_type& reader, uint64_t low, uint64_t high, uint64_t& uniq, uint64_t& distinct, uint64_t& total, uint64_t& max) { uniq = distinct = total = max = 0; while(reader.next()) { if(reader.val() < low || reader.val() > high) continue; uniq += reader.val() == 1; total += reader.val(); max = std::max(max, reader.val()); ++distinct; } } int stats_main(int argc, char *argv[]) { stats_main_cmdline args(argc, argv); std::ifstream is(args.db_arg); if(!is.good()) err::die(err::msg() << "Failed to open input file '" << args.db_arg << "'"); jellyfish::file_header header; header.read(is); jellyfish::mer_dna::k(header.key_len() / 2); ofstream_default out(args.output_given ? args.output_arg : 0, std::cout); if(!out.good()) err::die(err::msg() << "Error opening output file '" << args.output_arg << "'"); if(!args.upper_count_given) args.upper_count_arg = std::numeric_limits::max(); uint64_t uniq = 0, distinct = 0, total = 0, max = 0; if(!header.format().compare(binary_dumper::format)) { binary_reader reader(is, &header); compute_stats(reader, args.lower_count_arg, args.upper_count_arg, uniq, distinct, total, max); } else if(!header.format().compare(text_dumper::format)) { text_reader reader(is, &header); compute_stats(reader, args.lower_count_arg, args.upper_count_arg, uniq, distinct, total, max); } else { err::die(err::msg() << "Unknown format '" << header.format() << "'"); } out << "Unique: " << uniq << "\n" << "Distinct: " << distinct << "\n" << "Total: " << total << "\n" << "Max_count: " << max << "\n"; out.close(); return 0; } Jellyfish-2.2.8/sub_commands/stats_main_cmdline.yaggo000066400000000000000000000014771323712541700230310ustar00rootroot00000000000000purpose "Statistics" package "jellyfish stats" description "Display some statistics about the k-mers in the hash: Unique: Number of k-mers which occur only once. Distinct: Number of k-mers, not counting multiplicity. Total: Number of k-mers, including multiplicity. Max_count: Maximum number of occurrence of a k-mer. " option("recompute", "r") { description "Recompute" flag; off; hidden } option("lower-count", "L") { description "Don't consider k-mer with count < lower-count" uint64; default 0 } option("upper-count", "U") { description "Don't consider k-mer with count > upper-count (2^64)" uint64 } option("verbose", "v") { description "Verbose" flag; off } option("output", "o") { description "Output file" c_string } arg("db") { description "Jellyfish database" c_string; typestr "path" } Jellyfish-2.2.8/swig/000077500000000000000000000000001323712541700144325ustar00rootroot00000000000000Jellyfish-2.2.8/swig/Makefile.am000066400000000000000000000051031323712541700164650ustar00rootroot00000000000000# SWIG SWIG_SRC = swig/jellyfish.i swig/hash_counter.i swig/hash_set.i \ swig/mer_dna.i swig/mer_file.i swig/string_mers.i if HAVE_SWIG SWIG_V_GEN = $(swig_v_GEN_$(V)) swig_v_GEN_ = $(swig_v_GEN_$(AM_DEFAULT_VERBOSITY)) swig_v_GEN_0 = @echo " SWIG " $@; %/swig_wrap.cpp: $(SWIG_SRC) $(SWIG_V_GEN)$(SWIG) -$(notdir $*) -I$(srcdir)/../include -o $@ $< else %/swig_wrap.cpp: @echo >&2 SWIG >= 3.x.x not found. Make sure it is install and rerun configure @false endif # Python support if PYTHON_BINDING PYTHON_BUILT = swig/python/swig_wrap.cpp swig/python/dna_jellyfish.py BUILT_SOURCES += $(PYTHON_BUILT) if PYTHON_DEPRECATED pythonglobaldir = $(PYTHON_SITE_PKG) pythonglobal_SCRIPTS = swig/python/jellyfish.py endif pythonextdir = $(PYTHON_SITE_PKG)/dna_jellyfish pythonext_SCRIPTS = swig/python/__init__.pyc pythonext_LTLIBRARIES = swig/python/_dna_jellyfish.la swig_python__dna_jellyfish_la_SOURCES = swig/python/swig_wrap.cpp $(SWIG_SRC) swig_python__dna_jellyfish_la_CPPFLAGS = $(PYTHON_CPPFLAGS) -I$(srcdir)/include swig_python__dna_jellyfish_la_LDFLAGS = -module swig_python__dna_jellyfish_la_LIBADD = libjellyfish-2.0.la CLEANFILES += $(PYTHON_BUILT) $(pythonext_SCRIPTS) PYTHONC_V_GEN = $(pythonc_v_GEN_$(V)) pythonc_v_GEN_ = $(pythonc_v_GEN_$(AM_DEFAULT_VERBOSITY)) pythonc_v_GEN_0 = @echo " PYTHONC " $@; %/__init__.pyc: %/dna_jellyfish.py $(PYTHONC_V_GEN)$(PYTHON) -c 'import py_compile, sys; py_compile.compile(sys.argv[1], sys.argv[2])' $< $@ swig/python/dna_jellyfish.py: swig/python/swig_wrap.cpp EXTRA_DIST += $(PYTHON_BUILT) endif # Ruby support if RUBY_BINDING RUBY_BUILT = swig/ruby/swig_wrap.cpp BUILT_SOURCES += $(RUBY_BUILT) rubyextdir = $(RUBY_EXT_LIB) rubyext_LTLIBRARIES = swig/ruby/jellyfish.la swig_ruby_jellyfish_la_SOURCES = swig/ruby/swig_wrap.cpp $(SWIG_SRC) swig_ruby_jellyfish_la_CPPFLAGS = $(RUBY_EXT_CFLAGS) -I$(srcdir)/include swig_ruby_jellyfish_la_LDFLAGS = -module swig_ruby_jellyfish_la_LIBADD = libjellyfish-2.0.la CLEANFILES += $(RUBY_BUILT) endif # Perl5 support if PERL_BINDING PERL_BUILT = swig/perl5/swig_wrap.cpp swig/perl5/jellyfish.pm BUILT_SOURCES += $(PERL_BUILT) perlextdir = $(PERL_EXT_LIB) perlext_SCRIPTS = swig/perl5/jellyfish.pm perlext_LTLIBRARIES = swig/perl5/jellyfish.la swig_perl5_jellyfish_la_SOURCES = swig/perl5/swig_wrap.cpp $(SWIG_SRC) swig_perl5_jellyfish_la_CPPFLAGS = $(PERL_EXT_CPPFLAGS) -I$(PERL_EXT_INC) -I$(srcdir)/include swig_perl5_jellyfish_la_LDFLAGS = -module swig_perl5_jellyfish_la_LIBADD = libjellyfish-2.0.la CLEANFILES += $(PERL_BUILT) swig/perl5/jellyfish.pm: swig/perl5/swig_wrap.cpp EXTRA_DIST += $(PERL_BUILT) endif Jellyfish-2.2.8/swig/Readme.md000066400000000000000000000056541323712541700161630ustar00rootroot00000000000000What is it? =========== Bindings of the Jellyfish library to various scripting languages (Python, Ruby and Perl currently). This allows to query the Jellyfish output files and use the Jellyfish hash within these scripting languages, which is much more convenient than in C++, although somewhat slower. Examples ======== Some simplified examples on how to use the Jellyfish binding. jellyfish dump -------------- The following is roughly equivalent to the dump subcommand. It dumps in text format the content of a Jellyfish database. ---- ##### Python ```Python import jellyfish mf = jellyfish.ReadMerFile(sys.argv[1]) for mer, count in mf: print mer, count ``` ---- ##### Ruby ```Ruby require 'jellyfish' mf = Jellyfish::ReadMerFile.new ARGV[0] mf.each { |mer, count| puts("#{mer} #{count}") } ``` ---- ##### Perl ```Perl use jellyfish; my $mf = jellyfish::ReadMerFile->new($ARGV[0]); while($mf->next_mer) { print($mf->mer, " ", $mf->count, "\n"); } ``` ---- jellyfish query --------------- The following is roughly equivalent to the command query subcommand. For every mer passed on the command line, it prints its count in the Jellyfish database, where the mer is in canonical form. ---- ##### Python ```Python import jellyfish qf = jellyfish.QueryMerFile(sys.argv.[1]) for m in sys.argv[2:]: mer = jellyfish.MerDNA(m) mer.canonicalize() print mer, qf[mer]) ``` ---- ##### Ruby ```Ruby require 'jellyfish' qf = Jellyfish::QueryMerFile(ARGV.shift) ARGV.each { |m| mer = Jellyfish::MerDNA.new(m) mer.canonicalize! puts("#{mer} #{qf[mer]}") } ``` ---- ##### Perl ```Perl use jellyfish; my $qf = jellyfish::QueryMerFile->new(shift(@ARGV)); foreach my $m (@ARGV) { my $mer = jellyfish::MerDNA->new($m); $mer->canonicalize; print($mer, " ", $qf->get($mer), "\n"); } ``` ---- jellyfish count =============== The following will parse all the 30-mers in a string (`str` in the examples) and store them in a hash counter. In the following code, by replacing `string_mers` by `string_canonicals`, one gets only the canonical mers. ---- ##### Ruby ```Ruby require 'jellyfish' Jellyfish::MerDNA::k(30) h = Jellyfish::HashCounter.new(1024, 5) str.mers { |m| h.add(m, 1) } ``` ---- ##### Python ```Python import jellyfish jellyfish.MerDNA.k(30) h = jellyfish.HashCounter(1024, 5) mers = jellyfish.string_mers(str) for m in mers: h.add(m, 1) ``` --- ##### Perl ```Perl use jellyfish; jellyfish::MerDNA::k(30); my $h = jellyfish::HashCounter->new(1024, 5); my $mers = jellyfish::string_mers($str); while($mers->next_mer) { $h->add($mers->mer, 1); } ``` The argument to the `HashCounter` constructor are the initial size of the hash and the number of bits in the value field (call it `b`). Note that the number `b` of bits in the value field does not create an upper limit on the value of the count. For best performance, `b` should be chosen so that most k-mers in the hash have a count less than 2^b (2 to the power of b). Jellyfish-2.2.8/swig/Tuprules.tup000066400000000000000000000051631323712541700170140ustar00rootroot00000000000000# Default rules !cc = |> ^ CC %f^ $(CC) $(CPPFLAGS) $(CPPFLAGS_%B) @(CPPFLAGS) $(CFLAGS) $(CFLAGS_%B) @(CFLAGS) -c -o %o %f |> %B.o !cxx = |> ^ CXX %f^ $(CXX) $(CPPFLAGS) $(CPPFLAGS_%B) @(CPPFLAGS) $(CXXFLAGS) $(CXXFLAGS_%B) @(CXXFLAGS) -c -o %o %f |> %B.o !ld = |> ^ LD %o^ $(CC) $(T_LDFLAGS) $(LDFLAGS) $(LDFLAGS_%O) $(LOADLIBES) $(LDLIBS) %f -o %o |> !lxxd = |> ^ LXX %o^ $(CXX) $(T_LDFLAGS) $(LDFLAGS) $(LDFLAGS_%o) @(LDFLAGS) %f $(LOADLIBES) $(LDLIBS) $(LDLIBS_%o) -o %o |> !cld = |> ^ CLD %o^ $(CC) $(CPPFLAGS) $(CPPFLAGS_%B) @(CPPFLAGS) $(CFLAGS) $(CFLAGS_%B) @(CFLAGS) %f -o %o |> !cxxld = |> ^ CXXLD %o^ $(CXX) $(CPPFLAGS) $(CPPFLAGS_%B) @(CPPFLAGS) $(CXXFLAGS) $(CXXFLAGS_%B) @(CXXFLAGS) $(LDFLAGS) $(LDFLAGS_%o) @(LDFLAGS) %f $(LOADLIBES) $(LDLIBS) $(LDLIBS_%o) -o %o |> %B !ar = |> ^ AR %o^ $(AR) sruv $(ARFLAGS) $(ARFLAGS_%O) @(ARFLAGS) %o %f |> !yaggo = |> ^ YAGGO %f^ $(YAGGO) %f |> %B.hpp !swigxx = |> ^ SWIG %f^ $(SWIG) -c++ $(SWIGFLAGS) $(SWIGFLAGS_%B) -o %o %f |> %B.cxx # Default variables ifdef CC CC = @(CC) else CC = gcc endif ifdef CXX CXX = @(CXX) else CXX = g++ endif ifdef AR AR = @(AR) else AR = ar endif ifdef YAGGO YAGGO = @(YAGGO) else YAGGO = yaggo endif ifdef SWIG SWIG = @(SWIG) else SWIG = swig endif ifdef PYTHON PYTHON = @(PYTHON) else PYTHON = python endif ifdef RUBY RUBY = @(RUBY) else RUBY = ruby endif ifdef PERL PERL = @(PERL) else PERL = perl endif ifdef JELLYFISH JELLYFISH = @(JELLYFISH) else JELLYFISH = jellyfish endif CXXFLAGS = -Wall -std=c++0x ifdef JELLYFISH_CFLAGS JELLYFISH_CFLAGS = @(JELLYFISH_CFLAGS) else JELLYFISH_CFLAGS = `pkg-config --cflags jellyfish-2.0` endif ifdef JELLYFISH_LIBS JELLYFISH_LIBS = @(JELLYFISH_LIBS) else JELLYFISH_LIBS = `pkg-config --libs jellyfish-2.0` endif ifdef JELLYFISH_RPATH JELLYFISH_RPATH = @(JELLYFISH_RPATH) else JELLYFISH_RPATH = `pkg-config --libs-only-L jellyfish-2.0 | sed -e 's/-L/-Wl,-rpath,/g'` endif ifdef RUBY_CFLAGS RUBY_CFLAGS = @(RUBY_CFLAGS) else RUBY_CFLAGS = `pkg-config --cflags ruby-1.9` endif ifdef RUBY_LIBS RUBY_LIBS = @(RUBY_LIBS) else RUBY_LIBS = `pkg-config --libs ruby-1.9` endif ifdef PYTHON_CFLAGS PYTHON_CFLAGS = @(PYTHON_CFLAGS) else PYTHON_CFLAGS = `pkg-config --cflags python3` endif ifdef PYTHON_LIBS PYTHON_LIBS = @(PYTHON_LIBS) else PYTHON_LIBS = `pkg-config --libs python3` endif ifdef PERL_CFLAGS PERL_CFLAGS = @(PERL_CFLAGS) else PERL_CFLAGS = `perl -MConfig -e 'print("-I$Config{archlibexp}/CORE")'` endif ifdef PERL_LIBS PERL_LIBS = @(PERL_LIBS) else PERL_LIBS = `perl -MConfig -e 'print($Config{ccdlflags})'` endif Jellyfish-2.2.8/swig/hash_counter.i000066400000000000000000000033131323712541700172660ustar00rootroot00000000000000/*********************************************************************/ /* Proxy class for hash counter: auto size doubling hash on mer_dna. */ /*********************************************************************/ %{ class HashCounter : public jellyfish::cooperative::hash_counter { typedef jellyfish::cooperative::hash_counter super; public: HashCounter(size_t size, unsigned int val_len, unsigned int nb_threads = 1) : \ super(size, jellyfish::mer_dna::k() * 2, val_len, nb_threads) { } bool add(const MerDNA& m, const int& x) { bool res; size_t id; super::add(m, x, &res, &id); return res; } }; %} // Typemaps to return nil/undef/None if the mer asked for is not in // the hash %typemap(in, numinputs=0) std::pair* COUNT (std::pair tmp) { $1 = &tmp; } %typemap(argout) std::pair* COUNT { if(($1)->first) { SWIG_Object o = SWIG_From(unsigned long)(($1)->second); %append_output(o); } else { %append_output(VOID_Object); } } class HashCounter { public: HashCounter(size_t size, unsigned int val_len, unsigned int nb_threads = 1); size_t size() const; unsigned int val_len() const; // unsigned int nb_threads() const; bool add(const MerDNA& m, const int& x); bool update_add(const MerDNA&, const int&); %extend { void get(const MerDNA& m, std::pair* COUNT) const { COUNT->first = $self->ary()->get_val_for_key(m, &COUNT->second); } #ifndef SWIGPERL void __getitem__(const MerDNA& m, std::pair* COUNT) const { COUNT->first = $self->ary()->get_val_for_key(m, &COUNT->second); } #endif } }; Jellyfish-2.2.8/swig/hash_set.i000066400000000000000000000017671323712541700164150ustar00rootroot00000000000000/*********************************************************************/ /* Proxy class for hash counter: auto size doubling hash on mer_dna. */ /*********************************************************************/ %{ class HashSet : public jellyfish::cooperative::hash_counter { typedef jellyfish::cooperative::hash_counter super; public: HashSet(size_t size, unsigned int nb_threads = 1) : \ super(size, jellyfish::mer_dna::k() * 2, 0, nb_threads) { } bool add(const MerDNA& m) { bool res; size_t id; super::set(m, &res, &id); return res; } }; %} class HashSet { public: HashSet(size_t size, unsigned int nb_threads = 1); size_t size() const; // unsigned int nb_threads() const; bool add(const MerDNA& m); %extend { bool get(const MerDNA& m) const { return $self->ary()->has_key(m); } #ifndef SWIGPERL bool __getitem__(const MerDNA& m) const { return $self->ary()->has_key(m); } #endif } }; Jellyfish-2.2.8/swig/jellyfish.i000066400000000000000000000020351323712541700165750ustar00rootroot00000000000000#ifdef SWIGPYTHON // Default Python loading code does not seem to work. Use our own. %define MODULEIMPORT " import os if os.path.basename(__file__) == \"__init__.pyc\" or os.path.basename(__file__) == \"__init__.py\": import dna_jellyfish.$module else: import $module " %enddef %module(docstring="Jellyfish binding", moduleimport=MODULEIMPORT) dna_jellyfish #else %module(docstring="Jellyfish binding") jellyfish #endif %naturalvar; // Use const reference instead of pointers %include "std_string.i" %include "exception.i" %include "std_except.i" %include "typemaps.i" %feature("autodoc", "2"); %{ #ifdef SWIGPYTHON #endif #ifdef SWIGPERL #undef seed #undef random #endif #include #include #undef die #include #include #include #include #include #undef die %} %include "mer_dna.i" %include "mer_file.i" %include "hash_counter.i" %include "hash_set.i" %include "string_mers.i" Jellyfish-2.2.8/swig/mer_dna.i000066400000000000000000000075701323712541700162220ustar00rootroot00000000000000/**********************************/ /* MerDNA proxy class for mer_dna */ /**********************************/ %{ class MerDNA : public jellyfish::mer_dna { public: MerDNA() = default; MerDNA(const char* s) : jellyfish::mer_dna(s) { } MerDNA(const MerDNA& m) : jellyfish::mer_dna(m) { } MerDNA& operator=(const jellyfish::mer_dna& m) { *static_cast(this) = m; return *this; } }; %} #ifdef SWIGRUBY %bang MerDNA::randomize(); %bang MerDNA::canonicalize(); %bang MerDNA::reverse_complement(); %bang MerDNA::polyA(); %bang MerDNA::polyC(); %bang MerDNA::polyG(); %bang MerDNA::polyT(); // %predicate MerDNA::is_homopolymer(); // Does not work??? %rename("MerDNA::homopolymer?") MerDNA::is_homopolymer(); %rename("MerDNA::complement") MerDNA::get_reverse_complement(); %rename("MerDNA::canonical") MerDNA::get_canonical(); #endif %feature("autodoc", "Class representing a mer. All the mers have the same length, which must be set BEFORE instantiating any mers with jellyfish::MerDNA::k(int)"); class MerDNA { public: MerDNA(); MerDNA(const char*); MerDNA(const MerDNA&); %feature("autodoc", "Get the length of the k-mers"); static unsigned int k(); %feature("autodoc", "Set the length of the k-mers"); static unsigned int k(unsigned int); %feature("autodoc", "Change the mer to a homopolymer of A"); void polyA(); %feature("autodoc", "Change the mer to a homopolymer of C"); void polyC(); %feature("autodoc", "Change the mer to a homopolymer of G"); void polyG(); %feature("autodoc", "Change the mer to a homopolymer of T"); void polyT(); %feature("autodoc", "Change the mer to a random one"); void randomize(); %feature("autodoc", "Check if the mer is a homopolymer"); bool is_homopolymer() const; %feature("autodoc", "Shift a base to the left and the leftmost base is return . \"ACGT\", shift_left('A') becomes \"CGTA\" and 'A' is returned"); char shift_left(char); %feature("autodoc", "Shift a base to the right and the rightmost base is return . \"ACGT\", shift_right('A') becomes \"AACG\" and 'T' is returned"); char shift_right(char); %feature("autodoc", "Change the mer to its canonical representation"); void canonicalize(); %feature("autodoc", "Change the mer to its reverse complement"); void reverse_complement(); %feature("autodoc", "Return canonical representation of the mer"); MerDNA get_canonical() const; %feature("autodoc", "Return the reverse complement of the mer"); MerDNA get_reverse_complement() const; %feature("autodoc", "Equality between mers"); bool operator==(const MerDNA&) const; %feature("autodoc", "Lexicographic less-than"); bool operator<(const MerDNA&) const; %feature("autodoc", "Lexicographic greater-than"); bool operator>(const MerDNA&) const; %extend{ %feature("autodoc", "Duplicate the mer"); MerDNA dup() const { return MerDNA(*self); } %feature("autodoc", "Return string representation of the mer"); std::string __str__() { return self->to_str(); } %feature("autodoc", "Set the mer from a string"); void set(const char* s) throw(std::length_error) { *static_cast(self) = s; } #ifdef SWIGPERL char get_base(unsigned int i) { return (char)self->base(i); } void set_base(unsigned int i, char b) { self->base(i) = b; } #else %feature("autodoc", "Get base i (0 <= i < k)"); char __getitem__(unsigned int i) { return (char)self->base(i); } %feature("autodoc", "Set base i (0 <= i < k)"); void __setitem__(unsigned int i, char b) { self->base(i) = b; } // MerDNA __neg__() const { return self->get_reverse_complement(); } %feature("autodoc", "Shift a base to the left and return the mer"); MerDNA& __lshift__(char b) { self->shift_left(b); return *self; } %feature("autodoc", "Shift a base to the right and return the mer"); MerDNA& __rshift__(char b) { self->shift_right(b); return *self; } #endif } }; Jellyfish-2.2.8/swig/mer_file.i000066400000000000000000000135301323712541700163700ustar00rootroot00000000000000/******************************/ /* Query output of jellyfish. */ /******************************/ %{ class QueryMerFile { std::unique_ptr bf; jellyfish::mapped_file binary_map; std::unique_ptr jf; public: QueryMerFile(const char* path) { std::ifstream in(path); if(!in.good()) throw std::runtime_error(std::string("Can't open file '") + path + "'"); jellyfish::file_header header(in); jellyfish::mer_dna::k(header.key_len() / 2); if(header.format() == "bloomcounter") { jellyfish::hash_pair fns(header.matrix(1), header.matrix(2)); bf.reset(new jellyfish::mer_dna_bloom_filter(header.size(), header.nb_hashes(), in, fns)); if(!in.good()) throw std::runtime_error("Bloom filter file is truncated"); } else if(header.format() == "binary/sorted") { binary_map.map(path); jf.reset(new binary_query(binary_map.base() + header.offset(), header.key_len(), header.counter_len(), header.matrix(), header.size() - 1, binary_map.length() - header.offset())); } else { throw std::runtime_error(std::string("Unsupported format '") + header.format() + "'"); } } #ifdef SWIGPERL unsigned int get(const MerDNA& m) { return jf ? jf->check(m) : bf->check(m); } #else unsigned int __getitem__(const MerDNA& m) { return jf ? jf->check(m) : bf->check(m); } #endif }; %} %feature("autodoc", "Give random access to a Jellyfish database. Given a mer, it returns the count associated with that mer"); class QueryMerFile { public: %feature("autodoc", "Open the jellyfish database"); QueryMerFile(const char* path) throw(std::runtime_error); %feature("autodoc", "Get the count for the mer m"); #ifdef SWIGPERL unsigned int get(const MerDNA& m); #else unsigned int __getitem__(const MerDNA& m); #endif }; /****************************/ /* Read output of jellyfish */ /****************************/ #ifdef SWIGRUBY %mixin ReadMerFile "Enumerable"; #endif #ifdef SWIGPYTHON // For python iteratable, throw StopIteration if at end of iterator %exception __next__ { $action; if(!result.first) { PyErr_SetString(PyExc_StopIteration, "Done"); SWIG_fail; } } %exception next { $action; if(!result.first) { PyErr_SetString(PyExc_StopIteration, "Done"); SWIG_fail; } } %typemap(out) std::pair { SWIG_Object m = SWIG_NewPointerObj(const_cast(($1).first), SWIGTYPE_p_MerDNA, 0); SWIG_Object c = SWIG_From(unsigned long)(($1).second); %append_output(m); %append_output(c); } #endif #ifdef SWIGPERL // For perl, return an empty array at end of iterator %typemap(out) std::pair { if(($1).first) { SWIG_Object m = SWIG_NewPointerObj(const_cast(($1).first), SWIGTYPE_p_MerDNA, 0); SWIG_Object c = SWIG_From(unsigned long)(($1).second); %append_output(m); %append_output(c); } } #endif %{ class ReadMerFile { std::ifstream in; std::unique_ptr binary; std::unique_ptr text; std::pair next_mer__() { std::pair res((const MerDNA*)0, 0); if(next_mer()) { res.first = mer(); res.second = count(); } return res; } public: ReadMerFile(const char* path) : in(path) { if(!in.good()) throw std::runtime_error(std::string("Can't open file '") + path + "'"); jellyfish::file_header header(in); jellyfish::mer_dna::k(header.key_len() / 2); if(header.format() == binary_dumper::format) binary.reset(new binary_reader(in, &header)); else if(header.format() == text_dumper::format) text.reset(new text_reader(in, &header)); else throw std::runtime_error(std::string("Unsupported format '") + header.format() + "'"); } bool next_mer() { if(binary) { if(binary->next()) return true; binary.reset(); } else if(text) { if(text->next()) return true; text.reset(); } return false; } const MerDNA* mer() const { return static_cast(binary ? &binary->key() : &text->key()); } unsigned long count() const { return binary ? binary->val() : text->val(); } #ifdef SWIGRUBY void each() { if(!rb_block_given_p()) return; while(next_mer()) { auto m = SWIG_NewPointerObj(const_cast(mer()), SWIGTYPE_p_MerDNA, 0); auto c = SWIG_From_unsigned_SS_long(count()); rb_yield(rb_ary_new3(2, m, c)); } } #endif #ifdef SWIGPERL std::pair each() { return next_mer__(); } #endif #ifdef SWIGPYTHON ReadMerFile* __iter__() { return this; } std::pair __next__() { return next_mer__(); } std::pair next() { return next_mer__(); } #endif }; %} %feature("autodoc", "Read a Jellyfish database sequentially"); class ReadMerFile { public: %feature("autodoc", "Open the jellyfish database"); ReadMerFile(const char* path) throw(std::runtime_error); %feature("autodoc", "Move to the next mer in the file. Returns false if no mers left, true otherwise"); bool next_mer(); %feature("autodoc", "Returns current mer"); const MerDNA* mer() const; %feature("autodoc", "Returns the count of the current mer"); unsigned long count() const; %feature("autodoc", "Iterate through all the mers in the file, passing two values: a mer and its count"); #ifdef SWIGRUBY void each(); #endif #ifdef SWIGPERL std::pair each(); #endif #ifdef SWIGPYTHON ReadMerFile* __iter__(); std::pair __next__(); std::pair next() { return __next__(); } #endif }; Jellyfish-2.2.8/swig/perl5/000077500000000000000000000000001323712541700154615ustar00rootroot00000000000000Jellyfish-2.2.8/swig/perl5/Makefile.PL000066400000000000000000000012151323712541700174320ustar00rootroot00000000000000#! /usr/bin/env perl use strict; use warnings; use ExtUtils::MakeMaker; mkdir('lib'); system('swig', '-c++', '-perl5', '-o', 'jellyfish_wrap.cxx', '../jellyfish.i'); my $jf_cflags = `pkg-config --cflags jellyfish-2.0`; my $jf_libs = `pkg-config --libs jellyfish-2.0`; my $jf_rpath = `pkg-config --libs-only-L jellyfish-2.0 | sed -e 's/-L/-Wl,-rpath,/g'`; WriteMakefile(NAME => 'jellyfish', CC => 'g++-4.4', LD => 'g++-4.4', CCFLAGS => "-std=c++0x $jf_cflags", LIBS => "$jf_libs", OBJECT => 'jellyfish_wrap.o', VERSION => '0.0.1'); Jellyfish-2.2.8/swig/perl5/Tupfile000066400000000000000000000007211323712541700170140ustar00rootroot00000000000000include_rules export PKG_CONFIG_PATH SWIGFLAGS = -perl5 CXXFLAGS += $(JELLYFISH_CFLAGS) $(PERL_CFLAGS) -fPIC LDFLAGS += -shared $(JELLYFISH_LIBS) $(JELLYFISH_RPATH) $(PERL_LIBS) : ../jellyfish.i |> !swigxx |> jellyfish_wrap.cxx | jellyfish.pm : jellyfish_wrap.cxx |> !cxx |> : jellyfish_wrap.o |> !lxxd |> jellyfish.so TESTS = t/test_mer_file.t t/test_hash_counter.t : foreach $(TESTS) | ../tests/ |> $(PERL) -I. %f ../tests > %o 2>&1 |> %B Jellyfish-2.2.8/swig/perl5/t/000077500000000000000000000000001323712541700157245ustar00rootroot00000000000000Jellyfish-2.2.8/swig/perl5/t/test_hash_counter.t000066400000000000000000000020611323712541700216310ustar00rootroot00000000000000use strict; use warnings; use Test::More; use jellyfish; require_ok('jellyfish'); my $data = shift(@ARGV); jellyfish::MerDNA::k(100); my $hash = jellyfish::HashCounter->new(1024, 5); # Check info ok(100 == jellyfish::MerDNA::k, "mer_dna k"); ok(1024 == $hash->size, "Hash size"); ok(5 == $hash->val_len, "Hash value length"); # Test adding mers { my $mer = jellyfish::MerDNA->new; my $good = 1; for(my $i = 0; $i < 1000; $i++) { $mer->randomize(); my $val = int(rand(1000)); $good &&= $hash->add($mer, $val) or (ok($good, "Adding to new mer") || last); if($i % 3 > 0) { my $nval = int(rand(1000)); $val += $nval; if($i % 3 == 1) { $good &&= !$hash->add($mer, $nval) or (ok($good, "Adding to existing mer") || last); } else { $good &&= $hash->update_add($mer, $nval) or (ok($good, "Updating existing mer") || last); } } $good &&= $val == $hash->get($mer) or (ok($good, "Value in hash") || last); } ok($good, "Adding mer to hash"); } done_testing; Jellyfish-2.2.8/swig/perl5/t/test_mer_file.t000066400000000000000000000022111323712541700207260ustar00rootroot00000000000000use strict; use warnings; use Test::More; require_ok('jellyfish'); my $data = shift(@ARGV); # Compare histo { my $rf = jellyfish::ReadMerFile->new($data . "/swig_perl.jf"); my @histo; $histo[$rf->count]++ while($rf->next_mer); open(my $io, "<", $data . "/swig_perl.histo"); my @jf_histo; while(<$io>) { my ($freq, $count) = split; $jf_histo[$freq] = $count; } is_deeply(\@histo, \@jf_histo, "Histogram"); } # Compare dump { my $rf = jellyfish::ReadMerFile->new($data . "/swig_perl.jf"); my $equal = open(my $io, "<", $data . "/swig_perl.dump"); while(<$io>) { my ($mer, $count) = split; $equal &&= $rf->next_mer; $equal &&= ($mer eq $rf->mer); $equal &&= ($count == $rf->count); last unless $equal; } $equal &&= !$rf->next_mer; ok($equal, "Dump"); } # Query { my $rf = jellyfish::ReadMerFile->new($data . "/swig_perl.jf"); my $qf = jellyfish::QueryMerFile->new($data . "/swig_perl.jf"); my $good = 1; while(my ($mer, $count) = $rf->each) { $good &&= $count == $qf->get($mer) or (ok($good, "Query mer") || last); } ok($good, "Query identical to read"); } done_testing; Jellyfish-2.2.8/swig/perl5/t/test_string_mers.t000066400000000000000000000013141323712541700215030ustar00rootroot00000000000000use strict; use warnings; use Test::More; require_ok('jellyfish'); jellyfish::MerDNA::k(int(rand(100)) + 10); my @bases = ("A", "C", "G", "T", "a", "c", "g", "t"); my $str; for(my $i = 0; $i < 1000; $i++) { $str .= $bases[int(rand(8))]; } my $count = 0; my $m2 = jellyfish::MerDNA->new; my $mers = jellyfish::string_mers($str); my $good_mers = 1; my $good_strs = 1; while($mers->next_mer) { my $mstr = uc(substr($str, $count, jellyfish::MerDNA::k())); $m2->set($mstr); $good_strs &&= $mers->mer == $m2; $good_mers &&= $mers->mer eq $mstr; $count++; } ok($good_mers, "Mers equal"); ok($good_strs, "Strs equal"); ok($count == length($str) - jellyfish::MerDNA::k() + 1, "Number of mers"); done_testing; Jellyfish-2.2.8/swig/python/000077500000000000000000000000001323712541700157535ustar00rootroot00000000000000Jellyfish-2.2.8/swig/python/Tupfile000066400000000000000000000007571323712541700173170ustar00rootroot00000000000000include_rules export PKG_CONFIG_PATH SWIGFLAGS = -python CXXFLAGS += $(JELLYFISH_CFLAGS) $(PYTHON_CFLAGS) -fPIC LDFLAGS += -shared $(JELLYFISH_LIBS) $(JELLYFISH_RPATH) $(PYTHON_LIBS) : ../jellyfish.i |> !swigxx |> jellyfish_wrap.cxx | jellyfish.py : jellyfish_wrap.cxx |> !cxx |> : jellyfish_wrap.o |> !lxxd |> _jellyfish.so TESTS = test_mer_file.py test_hash_counter.py : foreach $(TESTS) | ../tests/ |> PYTHONPATH=.:$PYTHONPATH $(PYTHON) -B %f ../tests > %o 2>&1 |> %B Jellyfish-2.2.8/swig/python/setup.py000066400000000000000000000040311323712541700174630ustar00rootroot00000000000000#! /usr/bin/env python import os import re from distutils.core import setup, Extension # Don't use Extension support for swig, it is more annoying than # anything! (1)It does not support very well having the .i in a # different directory. (2)It runs swig every single time, even if it # ran successfully before. So (3)doing first build, then install as # root rebuilds the modules as root. swig_time = os.path.getmtime('../jellyfish.i') older = True try: older = os.path.getmtime('jellyfish_wrap.cxx') < swig_time or os.path.getmtime('jellyfish.py') < swig_time except FileNotFoundError: older = True if older: print("Running swig: swig -c++ -python -o jellyfish_wrap.cxx ../jellyfish.i") os.system("swig -c++ -python -o jellyfish_wrap.cxx ../jellyfish.i") jf_include = [re.sub(r'-I', '', x) for x in os.popen("pkg-config --cflags-only-I jellyfish-2.0").read().rstrip().split()] jf_cflags = os.popen("pkg-config --cflags-only-other").read().rstrip().split() jf_libs = [re.sub(r'-l', '', x) for x in os.popen("pkg-config --libs-only-l jellyfish-2.0").read().rstrip().split()] jf_libdir = [re.sub(r'-L', '', x) for x in os.popen("pkg-config --libs-only-L jellyfish-2.0").read().rstrip().split()] jf_rpath = [re.sub(r'^', '-Wl,-rpath,', x) for x in jf_libdir] jf_ldflags = os.popen("pkg-config --libs-only-other jellyfish-2.0").read().rstrip().split() jellyfish_module = Extension('_dna_jellyfish', sources = ['jellyfish_wrap.cxx'], include_dirs = jf_include, libraries = jf_libs, library_dirs = jf_libdir, extra_compile_args = ["-std=c++0x"] + jf_cflags, extra_link_args = jf_ldflags + jf_rpath, language = "c++") setup(name = 'dna_jellyfish', version = '0.0.1', author = 'Guillaume Marcais', description = 'Access to jellyfish k-mer counting', ext_modules = [jellyfish_module], py_modules = ["dna_jellyfish"]) Jellyfish-2.2.8/swig/python/test_hash_counter.py000066400000000000000000000022241323712541700220460ustar00rootroot00000000000000import unittest import sys import random import dna_jellyfish as jf class TestHashCounter(unittest.TestCase): def setUp(self): jf.MerDNA.k(100) self.hash = jf.HashCounter(1024, 5) def test_info(self): self.assertEqual(100, jf.MerDNA.k()) self.assertEqual(1024, self.hash.size()) self.assertEqual(5, self.hash.val_len()) def test_add(self): mer = jf.MerDNA() good = True for i in range(1000): mer.randomize() val = random.randrange(1000) good = good and self.hash.add(mer, val) if not good: break if i % 3 > 0: nval = random.randrange(1000) val = val + nval if i % 3 == 1: good = good and (not self.hash.add(mer, nval)) else: good = good and self.hash.update_add(mer, nval) if not good: break good = good and (val == self.hash.get(mer)) and (val == self.hash[mer]) if not good: break self.assertTrue(good) if __name__ == '__main__': data = sys.argv.pop(1) unittest.main() Jellyfish-2.2.8/swig/python/test_mer_file.py000066400000000000000000000034711323712541700211530ustar00rootroot00000000000000import unittest import sys import os from collections import Counter import dna_jellyfish as jf class TestMerFile(unittest.TestCase): def setUp(self): self.mf = jf.ReadMerFile(os.path.join(data, "swig_python.jf")) def test_histo(self): histo = Counter() while self.mf.next_mer(): histo[self.mf.count()] += 1 jf_histo = Counter() with open(os.path.join(data, "swig_python.histo")) as f: for line in f: num, count = [int(n) for n in line.split()] self.assertEqual(count, histo[num]) def test_dump(self): good = True with open(os.path.join(data, "swig_python.dump")) as f: for line in f: good = good and self.mf.next_mer() if not good: break a = line.split() good = good and a[0] == str(self.mf.mer()) and int(a[1]) == self.mf.count() if not good: break self.assertTrue(good) def test_iter(self): good = True with open(os.path.join(data, "swig_python.dump")) as f: for mer, count in self.mf: line = f.readline() good = good and line if not good: break fmer, fcount = line.split() good = good and fmer == str(mer) and int(fcount) == count if not good: break self.assertTrue(good) line = f.readline() self.assertTrue(not line) def test_query(self): good = True qf = jf.QueryMerFile(os.path.join(data, "swig_python.jf")) for mer, count in self.mf: good = good and count == qf[mer] if not good: break self.assertTrue(good) if __name__ == '__main__': data = sys.argv.pop(1) unittest.main() Jellyfish-2.2.8/swig/python/test_string_mers.py000066400000000000000000000024571323712541700217300ustar00rootroot00000000000000import unittest import sys import random import dna_jellyfish as jf class TestStringMers(unittest.TestCase): def setUp(self): bases = "ACGTacgt" self.str = ''.join(random.choice(bases) for _ in range(1000)) self.k = random.randint(10, 110) jf.MerDNA.k(self.k) def test_all_mers(self): count = 0 good1 = True good2 = True mers = jf.string_mers(self.str) for m in mers: m2 = jf.MerDNA(self.str[count:count+self.k]) good1 = good1 and m == m2 good2 = good2 and self.str[count:count+self.k].upper() == str(m2) count += 1 self.assertTrue(good1) self.assertTrue(good2) self.assertEqual(len(self.str) - self.k + 1, count) def test_canonical_mers(self): good = True mers = jf.string_canonicals(self.str) for count, m in enumerate(mers): m2 = jf.MerDNA(self.str[count:count+self.k]) rm2 = m2.get_reverse_complement() good = good and (m == m2 or m == rm2) good = good and (not (m > m2)) and (not (m > rm2)) # count += 1 self.assertTrue(good) self.assertEqual(len(self.str) - self.k + 0, count) if __name__ == '__main__': data = sys.argv.pop(1) unittest.main() Jellyfish-2.2.8/swig/ruby/000077500000000000000000000000001323712541700154135ustar00rootroot00000000000000Jellyfish-2.2.8/swig/ruby/Tupfile000066400000000000000000000006651323712541700167550ustar00rootroot00000000000000include_rules export PKG_CONFIG_PATH SWIGFLAGS = -ruby CXXFLAGS += $(JELLYFISH_CFLAGS) $(RUBY_CFLAGS) -fPIC LDFLAGS += -shared $(JELLYFISH_LIBS) $(JELLYFISH_RPATH) $(RUBY_LIBS) : ../jellyfish.i |> !swigxx |> jellyfish_wrap.cxx : jellyfish_wrap.cxx |> !cxx |> : jellyfish_wrap.o |> !lxxd |> jellyfish.so TESTS = test_mer_file.rb test_hash_counter.rb : foreach $(TESTS) | ../tests/ |> $(RUBY) -I. %f ../tests > %o |> %B Jellyfish-2.2.8/swig/ruby/extconf.rb000066400000000000000000000005721323712541700174120ustar00rootroot00000000000000#! /usr/bin/env ruby require 'mkmf' swig = find_executable('swig') system(swig, '-c++', '-ruby', '-o', 'jellyfish_wrap.cxx', '../jellyfish.i') $defs << `pkg-config --cflags jellyfish-2.0`.chomp << '-std=c++0x' $libs << `pkg-config --libs jellyfish-2.0`.chomp $libs << `pkg-config --libs-only-L jellyfish-2.0 | sed -e 's/-L/-Wl,-rpath,/g'`.chomp create_makefile('jellyfish') Jellyfish-2.2.8/swig/ruby/test_hash_counter.rb000066400000000000000000000016321323712541700214630ustar00rootroot00000000000000require 'test/unit' require 'jellyfish' class TestHashCounter < Test::Unit::TestCase def setup Jellyfish::MerDNA::k(100) @hash = Jellyfish::HashCounter.new(1024, 5) end def test_info assert_equal(100, Jellyfish::MerDNA::k) assert_equal(1024, @hash.size) assert_equal(5, @hash.val_len) # assert_equal(1, @hash.nb_threads) end def test_add mer = Jellyfish::MerDNA.new 1000.times { |i| mer.randomize! val = rand(1000) assert(@hash.add(mer, val)) if i % 3 > 0 nval = rand(1000) val += nval if i % 3 == 1 assert(!@hash.add(mer, nval)) else assert(@hash.update_add(mer, nval)) end end assert_equal(val, @hash.get(mer)) assert_equal(val, @hash[mer]) } mer.randomize! assert_nil(@hash.get(mer)) assert_nil(@hash[mer]) assert(!@hash.update_add(mer, 1)) end end Jellyfish-2.2.8/swig/ruby/test_mer_file.rb000066400000000000000000000023551323712541700205660ustar00rootroot00000000000000require 'test/unit' require 'jellyfish' $data = ARGV.shift class TestMerFile < Test::Unit::TestCase def setup @mf = Jellyfish::ReadMerFile.new(File.join($data, "swig_ruby.jf")) end def test_histo histo = [] histo[@mf.count] = (histo[@mf.count] || 0) + 1 while @mf.next_mer jf_histo = [] open(File.join($data, "swig_ruby.histo")) { |f| f.each_line.each { |l| freq, count = l.split.map {|x| x.to_i } jf_histo[freq] = count } } assert_equal jf_histo, histo end def test_each open(File.join($data, "swig_ruby.dump")) { |f| @mf.each { |m, c| l = f.readline assert l fm, fc = l.split assert_equal fm, m.to_s assert_equal fc.to_i, c } assert_raises(EOFError) { f.readline } } end def test_dump open(File.join($data, "swig_ruby.dump")) { |f| f.each_line.each { |l| mer, count = l.split assert @mf.next_mer assert_equal(mer, @mf.mer.to_s) assert_equal(count.to_i, @mf.count) } } assert !@mf.next_mer end def test_query query = Jellyfish::QueryMerFile.new(File.join($data, "swig_ruby.jf")) @mf.each { |m, c| assert_equal c, query[m] } end end Jellyfish-2.2.8/swig/ruby/test_string_mers.rb000066400000000000000000000016351323712541700213400ustar00rootroot00000000000000require 'test/unit' require 'jellyfish' class TestStringMers < Test::Unit::TestCase def setup bases = "ACGTacgt" @str = (0..1000).map { bases[rand(bases.size())] }.join("") Jellyfish::MerDNA::k(rand(100) + 10) end def test_all_mers count = 0 m2 = Jellyfish::MerDNA.new @str.mers.each_with_index { |m, i| assert_equal m.to_s, @str[i, Jellyfish::MerDNA::k()].upcase m2.set @str[i, Jellyfish::MerDNA::k()] assert_equal m2, m count += 1 } assert_equal @str.size - Jellyfish::MerDNA::k() + 1, count end def test_canonical_mers count = 0 m2 = Jellyfish::MerDNA.new @str.canonicals { |m| m2.set @str[count, Jellyfish::MerDNA::k()] cm2 = m2.get_reverse_complement assert(m2 == m || m == cm2) assert(!(m > m2) && !(m > cm2)); count += 1 } assert_equal @str.size - Jellyfish::MerDNA::k() + 1, count end end Jellyfish-2.2.8/swig/string_mers.i000066400000000000000000000101131323712541700171340ustar00rootroot00000000000000/****************************************/ /* Iterator of all the mers in a string */ /****************************************/ #ifdef SWIGPYTHON %exception __next__ { $action; if(!result) { PyErr_SetString(PyExc_StopIteration, "Done"); SWIG_fail; } } %exception next { $action; if(!result) { PyErr_SetString(PyExc_StopIteration, "Done"); SWIG_fail; } } #endif %{ class StringMers { #ifdef SWIGPYTHON const char* const m_str; #endif const char* m_current; const char* const m_last; const bool m_canonical; MerDNA m_m, m_rcm; unsigned int m_filled; public: StringMers(const char* str, int len, bool canonical) #ifdef SWIGPYTHON : m_str(strndup(str, len)) // In Python, duplicate the string! Can this be improved? , m_current(m_str) #else : m_current(str) #endif , m_last(m_current + len) , m_canonical(canonical) , m_filled(0) { } #ifdef SWIGPYTHON ~StringMers() { free((void*)m_str); } #endif bool next_mer() { if(m_current == m_last) return false; do { int code = jellyfish::mer_dna::code(*m_current); ++m_current; if(code >= 0) { m_m.shift_left(code); if(m_canonical) m_rcm.shift_right(m_rcm.complement(code)); m_filled = std::min(m_filled + 1, m_m.k()); } else m_filled = 0; } while(m_filled < m_m.k() && m_current != m_last); return m_filled == m_m.k(); } const MerDNA* mer() const { return !m_canonical || m_m < m_rcm ? &m_m : &m_rcm; } const MerDNA* next_mer__() { return next_mer() ? mer() : nullptr; } #ifdef SWIGRUBY void each() { if(!rb_block_given_p()) return; while(next_mer()) { auto m = SWIG_NewPointerObj(const_cast(mer()), SWIGTYPE_p_MerDNA, 0); rb_yield(m); } } #endif #ifdef SWIGPYTHON StringMers* __iter__() { return this; } const MerDNA* __next__() { return next_mer__(); } const MerDNA* next() { return next_mer__(); } #endif #ifdef SWIGPERL const MerDNA* each() { return next_mer__(); } #endif }; StringMers* string_mers(char* str, int length) { return new StringMers(str, length, false); } StringMers* string_canonicals(char* str, int length) { return new StringMers(str, length, true); } %} %apply (char *STRING, int LENGTH) { (char* str, int length) }; %newobject string_mers; %newobject string_canonicals; %feature("autodoc", "Get an iterator to the mers in the string"); StringMers* string_mers(char* str, int length); %feature("autodoc", "Get an iterator to the canonical mers in the string"); StringMers* string_canonicals(char* str, int length); #ifdef SWIGRUBY %mixin StringMers "Enumerable"; %init %{ rb_eval_string("class String\n" " def mers(&b); it = Jellyfish::string_mers(self); b ? it.each(&b) : it; end\n" " def canonicals(&b); it = Jellyfish::string_canonicals(self, &b); b ? it.each(&b) : it; end\n" "end"); %} #endif /* #ifdef SWIGPERL */ /* // For perl, return an empty array at end of iterator */ /* %typemap(out) const MerDNA* { */ /* if($1) { */ /* SWIG_Object m = SWIG_NewPointerObj(const_cast($1), SWIGTYPE_p_MerDNA, 0); */ /* %append_output(m); */ /* } */ /* } */ /* #endif */ %feature("autodoc", "Extract k-mers from a sequence string"); class StringMers { public: %feature("autodoc", "Create a k-mers parser from a string. Pass true as a second argument to get canonical mers"); StringMers(const char* str, int len, bool canonical); %feature("autodoc", "Get the next mer. Return false if reached the end of the string."); bool next_mer(); %feature("autodoc", "Return the current mer (or its canonical representation)"); const MerDNA* mer() const; #ifdef SWIGRUBY %feature("autodoc", "Iterate through all the mers in the string"); void each(); #endif #ifdef SWIGPYTHON StringMers* __iter__(); const MerDNA* __next__(); const MerDNA* next(); #endif #ifdef SWIGPERL MerDNA* each(); #endif }; Jellyfish-2.2.8/swig/tests/000077500000000000000000000000001323712541700155745ustar00rootroot00000000000000Jellyfish-2.2.8/swig/tests/Tupfile000066400000000000000000000006261323712541700171330ustar00rootroot00000000000000include_rules : |> (echo ">read"; head -c 1000000 /dev/urandom | ruby -e 'b="ACGT"; STDIN.bytes.each { |x| 4.times { |i| print(b[(x >> (2*i)) & 3]) } }') > %o |> sequence.fasta : sequence.fasta |> $(JELLYFISH) count -m 10 -s 10M -t 10 -C -o %o %f |> sequence.jf : sequence.jf |> $(JELLYFISH) histo %f > %o |> sequence.histo : sequence.jf |> $(JELLYFISH) dump -c %f > %o |> sequence.dump Jellyfish-2.2.8/tests/000077500000000000000000000000001323712541700146235ustar00rootroot00000000000000Jellyfish-2.2.8/tests/big.sh000066400000000000000000000014161323712541700157220ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh if [ -z "$BIG" ]; then echo "Skip big test" exit 77 fi sort -k2,2 > ${pref}.md5sum < ${pref}_31.histo && \ echo "Count k-mers on big data set" && \ ([ -f seq30g.fa ] || ${DIR}/generate_sequence -v -o seq30g -r 1000 -s 1602176487 30000000000) && $JF count -m 16 -s 4000000000 -o ${pref}_16.jf -c 4 -p 253 -C --out-counter-len 2 \ -t $nCPUs $JFPARAM seq30g.fa && \ $JF histo ${pref}_16.jf > ${pref}_16.histo && \ check ${pref}.md5sum RET=$? # echo "16-mer timing"; cat ${pref}_16.timing exit $RET Jellyfish-2.2.8/tests/bloom_counter.sh000066400000000000000000000027441323712541700200350ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_commands < ${pref}_none.histo $JF histo ${pref}.jf > ${pref}.histo $JF histo ${pref}_filtered.jf > ${pref}_filtered.histo TOTAL=$(cut -d\ -f2 ${pref}.histo) COLLISION=$(cut -d\ -f2 ${pref}_none.histo) # FPR is 1 in 1000. Should not get more than 1/500 collisions. [ $((TOTAL / 500 > COLLISION)) = 1 ] || { echo >&2 "Too many collisions" false } QUERY_TOT=$($JF query -s seq1m_0.fa ${pref}.bc | grep -c ' 2$') [ $QUERY_TOT = $TOTAL ] || { echo >&2 "Queried count 2 mers should be all mers" false } QUERY_COL=$($JF query -s seq1m_0.fa ${pref}_none.bc | grep -c ' 2$') [ $QUERY_COL = $COLLISION ] || { echo >&2 "Queried count 2 mers should equal collisions" false } check ${pref}.md5sum Jellyfish-2.2.8/tests/bloom_filter.sh000066400000000000000000000016101323712541700176320ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh # sort -k2,2 > ${pref}.md5sum < ${pref}_10m.histo if bc < /dev/null 2> /dev/null; then COLLISIONS=$(cut -d\ -f2 ${pref}_10m.histo | paste -sd+ - | bc) [ $((COLLISIONS > 10000)) = 0 ] || { echo >&2 "Too many collisions" false } else echo > "bc missing: Skip collisions test" fi $JF count --bf-size 3M --bf-fp 0.001 -t $nCPUs -o ${pref}_3m.jf -s 1M -m 40 seq1m_0.fa seq1m_1.fa seq1m_0.fa seq1m_2.fa $JF histo ${pref}_3m.jf > ${pref}_3m.histo if bc < /dev/null 2> /dev/null; then COLLISIONS=$(cut -d\ -f2 ${pref}_3m.histo | paste -sd+ - | bc) [ $((COLLISIONS - 1000000 > 20000)) = 0 ] || { echo >&2 "Too many collisions" false } else echo "bc missing: Skip collisions test" fi Jellyfish-2.2.8/tests/compat.sh.in000066400000000000000000000011351323712541700170470ustar00rootroot00000000000000if [ -z "$nCPUs" ]; then nCPUs=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null || sysctl -n hw.ncpu) fi pref=$(basename $0 .sh) DIR=../bin JF="$DIR/jellyfish" [ -n "$VALGRIND" ] && JF="valgrind $JF" SRCDIR=@abs_top_srcdir@ BUILDDIR=@abs_top_builddir@ check () { cut -d\ -f 2 $1 | xargs @MD5@ | sed 's/ \*/ /' | sort -k2,2 | diff -w $DIFFFLAGS $1 - } ENABLE_RUBY_BINDING="@RUBY_EXT_LIB@" RUBY="@RUBY@" ENABLE_PYTHON_BINDING="@PYTHON@" PYTHON="@PYTHON@" ENABLE_PERL_BINDING="@PERL_EXT_LIB@" PERL="@PERL@" SAMTOOLS="@SAMTOOLS@" if [ -n "$DEBUG" ]; then set -x; DIFFFLAGS="-y" fi set -e Jellyfish-2.2.8/tests/from_stream.sh000066400000000000000000000013301323712541700174720ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo && \ echo "GCCATTTCGATTAAAGAATGAT TAGGCATGCAACGCTTCCCTTT" | $JF query ${pref}_0 > ${pref}.query && \ check ${pref}.md5sum RET=$? cat ${pref}.timing # [ -z "$NODEL" ] && \ # rm -f ${pref}_* ${pref}.histo ${pref}.query ${pref}.md5sum \ # ${pref}.timing exit $RET Jellyfish-2.2.8/tests/from_stream_fastq.sh000066400000000000000000000010341323712541700206710ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo && \ check ${pref}.md5sum RET=$? cat ${pref}.timing # [ -z "$NODEL" ] && \ # rm -f ${pref}_* ${pref}.histo ${pref}.md5sum ${pref}.timing exit $RET Jellyfish-2.2.8/tests/generate_fastq_sequence.sh000066400000000000000000000003101323712541700220310ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh ${DIR}/generate_sequence -v -q -o seq10m -m 19 -s 2718281828 10000000 ${DIR}/generate_sequence -v -q -o seq1m -s 3246465313 1000000 1000000 1000000 1000000 1000000 Jellyfish-2.2.8/tests/generate_sequence.sh000077500000000000000000000010111323712541700206350ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh ${DIR}/generate_sequence -v -o seq10m -m 10 -m 22 -s 3141592653 10000000 ${DIR}/generate_sequence -v -o seq1m -s 1040104553 1000000 1000000 1000000 1000000 1000000 for i in 0 1 2 3 4; do gzip -c seq1m_$i.fa > seq1m_$i.fa.gz done ${DIR}/generate_sequence -v -q -o seq10m -s 1473540700 10000000 ln -sf seq10m.fq seq10m.fastq ${DIR}/fastq2sam seq10m.fastq if [ -n "$SAMTOOLS" ]; then $SAMTOOLS view -b -o seq10m.bam seq10m.sam $SAMTOOLS view -C -o seq10m.cram seq10m.sam fi Jellyfish-2.2.8/tests/large_key.sh000066400000000000000000000014521323712541700171230ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_m100_2M_ordered head -n 10001 seq1m_0.fa | $JF count -t $nCPUs -o ${pref}_m100_2k.jf -s 2k -m 100 /dev/fd/0 $JF dump -c ${pref}_m100_2k.jf | cut -d\ -f 1 | sort > ${pref}_m100_2k_ordered head -n 10001 seq1m_0.fa | $JF count -t $nCPUs -o ${pref}_m100_2k_disk.jf -s 2k --disk -m 100 /dev/fd/0 $JF dump -c ${pref}_m100_2k_disk.jf | cut -d\ -f 1 | sort > ${pref}_m100_2k_disk_ordered check ${pref}.md5sum Jellyfish-2.2.8/tests/merge.sh000066400000000000000000000022421323712541700162560ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_m40_s16m.histo ls | grep "^${pref}_m40_s1m[0-9].*" | xargs rm -f echo $FILES | xargs $JF count -t $nCPUs -o ${pref}_m40_s1m -s 1M --disk --no-merge -C -m 40 $JF merge -o ${pref}_m40_s1m_merged.jf ${pref}_m40_s1m[0-9]* ls | grep "^${pref}_m40_s1m[0-9].*" | xargs rm -f echo $FILES | xargs $JF count -t $nCPUs -o ${pref}_automerge_m40_s1m.jf -s 1M --disk -C -m 40 echo $FILES | xargs $JF count -t $nCPUs -o ${pref}_m40_s1m_text.jf -s 1M --text --disk -C -m 40 $JF histo ${pref}_automerge_m40_s1m.jf > ${pref}_automerge_m40_s1m.histo $JF histo ${pref}_m40_s1m_merged.jf > ${pref}_m40_s1m_merged.histo $JF histo ${pref}_m40_s1m_text.jf > ${pref}_m40_s1m_text.histo check ${pref}.md5sum Jellyfish-2.2.8/tests/min_qual.sh000066400000000000000000000006531323712541700167700ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo && \ check ${pref}.md5sum RET=$? cat ${pref}.timing 2>/dev/null exit $RET Jellyfish-2.2.8/tests/multi_file.sh000066400000000000000000000023531323712541700173130ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_m15_s2M.histo cat > ${pref}_gunzip_cmds <> ${pref}_gunzip_cmds $JF count -t $nCPUs -g ${pref}_gunzip_cmds -G 2 -C -m 15 -s 2M -o ${pref}_m15_s2M_zip.jf seq10m.fa $JF histo ${pref}_m15_s2M_zip.jf > ${pref}_m15_s2M_zip.histo # Test failure of generator echo false > ${pref}_fail_cmds STATUS= $JF count -t $nCPUs -g ${pref}_fail_cmds -G 2 -C -m 15 -s 2M -o ${pref}_fail.jf || STATUS=$? if [ -z "$STATUS" ]; then echo >&2 "Jellyfish did not report failure in generator command" false fi # Test failure to open file STATUS= $JF count -t $nCPUs -C -m 15 -s 2M -o ${pref}_fail.jf non_existent_sequence.fa || STATUS=$? if [ -z "$STATUS" ]; then echo >&2 "Jellyfish did not report failure in opening a file" false fi check ${pref}.md5sum Jellyfish-2.2.8/tests/multi_file_fastq.sh000066400000000000000000000010051323712541700205020ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo && \ check ${pref}.md5sum RET=$? cat ${pref}.timing # [ -z "$NODEL" ] && \ # rm -f ${pref}_* ${pref}.md5sum ${pref}.histo ${pref}.timing exit $RET Jellyfish-2.2.8/tests/parallel_direct_indexing.sh000077500000000000000000000015401323712541700221750ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_S $JF count --matrix seq10m_matrix_10 -m 10 -t $nCPUs \ -o ${pref}_LU -s 10M -C -L 2 -U 4 seq1m_0.fa $JF histo ${pref}_0 > ${pref}.histo $JF histo ${pref}_S > ${pref}_S.histo $JF histo ${pref}_LU_0 > ${pref}_LU.histo check ${pref}.md5sum cat ${pref}.timing Jellyfish-2.2.8/tests/parallel_fastq_direct_indexing.sh000066400000000000000000000014031323712541700233660ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo $JF histo ${pref}_Q_0 > ${pref}_Q.histo $JF histo ${pref}_LU_0 > ${pref}_LU.histo check ${pref}.md5sum cat ${pref}.timing Jellyfish-2.2.8/tests/parallel_fastq_hashing.sh000066400000000000000000000011321323712541700216470ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo $JF qdump -c -L 0.035 -U 0.905 ${pref}_0 | wc -l | awk '{ print $1 }' > ${pref}_lines.dump check ${pref}.md5sum cat ${pref}.timing Jellyfish-2.2.8/tests/parallel_fastq_sequence_hashing.sh000066400000000000000000000010021323712541700235330ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo && \ check ${pref}.md5sum RET=$? cat ${pref}.timing # [ -z "$NODEL" ] && \ # rm ${pref}.md5sum ${pref}.histo ${pref}_* ${pref}.timing exit $RET Jellyfish-2.2.8/tests/parallel_hashing.sh000077500000000000000000000066441323712541700204710ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_m15_s2M.histo $JF stats ${pref}_m15_s2M.jf > ${pref}_m15.stats # Count without size doubling $JF count -t $nCPUs -o ${pref}_m15_s16M.jf -s 16M -C -m 15 seq10m.fa $JF histo ${pref}_m15_s16M.jf > ${pref}_m15_s16M.histo # Count large merges in binary and text. Should agree $JF count -m 40 -t $nCPUs -o ${pref}_text.jf -s 2M --text seq1m_0.fa $JF count -m 40 -t $nCPUs -o ${pref}_binary.jf -s 2M seq1m_0.fa $JF histo ${pref}_text.jf > ${pref}_text.histo $JF stats ${pref}_text.jf > ${pref}_text.stats $JF histo ${pref}_binary.jf > ${pref}_binary.histo $JF stats ${pref}_binary.jf > ${pref}_binary.stats $JF dump -c ${pref}_text.jf | sort > ${pref}_text.dump $JF dump -c ${pref}_binary.jf | sort > ${pref}_binary.dump # Check the lower and upper count without merging $JF count -t $nCPUs -o ${pref}_m15_s2M_L2_U3.jf -s 2M -C -m 15 -L2 -U3 seq10m.fa $JF histo ${pref}_m15_s2M_L2_U3.jf > ${pref}_m15_s2M_L2_U3.histo # Check the lower and upper count limits with merging $JF count -t $nCPUs -o ${pref}_m15_s2M_L2_U3_automerge.jf -s 2M -C -m 15 -L2 -U3 --disk seq10m.fa $JF histo ${pref}_m15_s2M_L2_U3_automerge.jf > ${pref}_m15_s2M_L2_U3_automerge.histo # Check query $JF query ${pref}_binary.jf -s seq1m_0.fa | grep ' 1$' | wc -l | sed -e 's/ //g' > ${pref}_query_one_count # $JF query ${pref}_binary.jf -s seq1m_0.fa -C | grep ' 1$' | wc -l | sed -e 's/ //g' > ${pref}_query_canonical_one_count # $JF count -m 40 -t $nCPUs -o ${pref}_text -s 2M --text seq1m_0.fa # $JF info -s ${pref}_text0 | sort > ${pref}_text0_dump # $JF count -m 40 -t $nCPUs -o ${pref}_bin -s 2M seq1m_0.fa # $JF dump -c ${pref}_bin0 | sort > ${pref}_bin0_dump # $JF histo ${pref}_bin0 > ${pref}.histo # Count all k-mers # $JF count --matrix seq10m_matrix_22 -m 22 -t $nCPUs -o $pref \ # -s 10000000 --timing ${pref}.timing --stats ${pref}.stats seq10m.fa # # Output only counts >= 2 # $JF count --matrix seq10m_matrix_22 -m 22 -t $nCPUs -o ${pref}_L \ # -s 10000000 --timing ${pref}.timing -L 2 seq10m.fa # # Stream output # $JF count --matrix seq10m_matrix_22 -m 22 -t $nCPUs -o /dev/fd/1 -O \ # -s 10000000 --timing ${pref}.timing --stats ${pref}.stats seq10m.fa | \ # cat > ${pref}_S # $JF histo -f ${pref}_0 > ${pref}.histo # $JF dump -c ${pref}_L_0 > ${pref}_L.dump # $JF dump -c -L 2 ${pref}_0 > ${pref}.dump # cat ${pref}_0 | $JF dump -c -L 2 /dev/fd/0 > ${pref}_stream.dump # echo "GCCATTTCGATTAAAGAATGAT TAGGCATGCAACGCTTCCCTTT" | $JF query ${pref}_0 > ${pref}.query # $JF dump -c ${pref}_0 > ${pref}_all.dump # $JF dump -c ${pref}_S > ${pref}_S_all.dump check ${pref}.md5sum # cat ${pref}.timing Jellyfish-2.2.8/tests/parsers.sh000066400000000000000000000004321323712541700166350ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_double_fifo.stats && echo "Test read parser" && $DIR/test_read_parser seq10m.fa > ${pref}_read_parser_fa.dump RET=$? exit $RET Jellyfish-2.2.8/tests/quality_filter.sh000066400000000000000000000015261323712541700202200ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < $PREFIX.histo } count_histo ${pref} count_histo ${pref}_q@ -Q '@' count_histo ${pref}_qi -Q 'i' count_histo ${pref}_qC -Q 'C' count_histo ${pref}_q33 --min-quality 0 count_histo ${pref}_q105 --min-quality 41 count_histo ${pref}_q67 --min-quality 34 --quality-start 33 check ${pref}.md5sum Jellyfish-2.2.8/tests/raw_hash.sh000066400000000000000000000015041323712541700167530ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.stats && \ $JF dump -c -L 2 ${pref}_0 > ${pref}_L.dump && \ $JF histo -f ${pref}_0 > ${pref}.histo && echo "GCCATTTCGATTAAAGAATGAT TAGGCATGCAACGCTTCCCTTT" | $JF query ${pref}_0 > ${pref}.query && \ check ${pref}.md5sum RET=$? cat ${pref}.timing # [ -z "$NODEL" ] && \ # rm -f ${pref}_* ${pref}.md5sum ${pref}.timing ${pref}.stats exit $RET Jellyfish-2.2.8/tests/sam.sh000066400000000000000000000022771323712541700157470ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh if ! grep -q '#define HAVE_HTSLIB' ../config.h; then echo "Skip SAM/BAM/CRAM file format test" exit 77 fi sort -k2,2 > ${pref}.md5sum < ${pref}_${suffix}.histo $JF count -t $nCPUs -m 20 -s 10M -o ${pref}_${suffix}_qual.jf -C -Q D --sam seq10m.${suffix} $JF histo ${pref}_${suffix}_qual.jf > ${pref}_${suffix}_qual.histo } comp_histo sam if [ -f seq10m.bam ]; then comp_histo bam else cp ${pref}_sam.histo ${pref}_bam.histo cp ${pref}_sam_qual.histo ${pref}_bam_qual.histo fi if [ -f seq10m.cram ]; then comp_histo cram else cp ${pref}_sam.histo ${pref}_cram.histo cp ${pref}_sam_qual.histo ${pref}_cram_qual.histo fi check ${pref}.md5sum Jellyfish-2.2.8/tests/serial_direct_indexing.sh000077500000000000000000000006201323712541700216560ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.md5sum < ${pref}.histo && \ check ${pref}.md5sum RET=$? cat ${pref}.timing # [ -z "$NODEL" ] && rm -f ${pref}_* ${pref}.timing ${pref}.md5sum* ${pref}.histo exit $RET Jellyfish-2.2.8/tests/small.sh000077500000000000000000000010011323712541700162620ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}.histo && \ check ${pref}.md5sum RET=$? echo "Small timing"; cat ${pref}.timing exit $RET Jellyfish-2.2.8/tests/subset_hashing.sh000066400000000000000000000012351323712541700201660ustar00rootroot00000000000000#! /bin/sh cd tests/ . ./compat.sh sort -k2,2 > ${pref}.md5sum < ${pref}_m35_s2M_if.histo # Idem with 10-mers $JF count -t $nCPUs -o ${pref}_m10_s2M_if.jf -s 6M -C -m 10 --if seq1m_0.fa --if seq1m_2.fa seq1m_1.fa seq1m_0.fa seq1m_3.fa seq1m_2.fa $JF histo ${pref}_m10_s2M_if.jf > ${pref}_m10_s2M_if.histo check ${pref}.md5sum Jellyfish-2.2.8/tests/swig_perl.sh000066400000000000000000000007751323712541700171630ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh [ -z "$ENABLE_PERL_BINDING" ] && exit 77 LOADPATH="$BUILDDIR/swig/perl5" K=$($PERL -e 'print(int(rand(16)) + 6)') I=$($PERL -e 'print(int(rand(5)))') $JF count -m $K -s 10M -t $nCPUs -C -o ${pref}.jf seq1m_$I.fa $JF dump -c ${pref}.jf > ${pref}.dump $JF histo ${pref}.jf > ${pref}.histo for i in test_mer_file.t test_hash_counter.t test_string_mers.t; do echo Test $i $PERL "-I$LOADPATH/.libs" "-I$LOADPATH" "-I$SRCDIR/swig/perl5" "$SRCDIR/swig/perl5/t/$i" . done Jellyfish-2.2.8/tests/swig_python.sh000066400000000000000000000010701323712541700175270ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh [ -z "$ENABLE_PYTHON_BINDING" ] && exit 77 export PYTHONPATH="$BUILDDIR/swig/python/.libs:$BUILDDIR/swig/python${PYTHONPATH+:$PYTHONPATH}" K=$($PYTHON -c 'import random; print(random.randint(6, 20))') I=$($PYTHON -c 'import random; print(random.randint(0, 4))') $JF count -m $K -s 10M -t $nCPUs -C -o ${pref}.jf seq1m_$I.fa $JF dump -c ${pref}.jf > ${pref}.dump $JF histo ${pref}.jf > ${pref}.histo for i in test_mer_file.py test_hash_counter.py test_string_mers.py; do echo Test $i $PYTHON "$SRCDIR/swig/python/$i" . done Jellyfish-2.2.8/tests/swig_ruby.sh000066400000000000000000000007171323712541700171760ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh [ -z "$ENABLE_RUBY_BINDING" ] && exit 77 LOADPATH="$BUILDDIR/swig/ruby/.libs" K=$($RUBY -e 'print(rand(15) + 6)') I=$($RUBY -e 'print(rand(5))') $JF count -m $K -s 10M -t $nCPUs -C -o ${pref}.jf seq1m_$I.fa $JF dump -c ${pref}.jf > ${pref}.dump $JF histo ${pref}.jf > ${pref}.histo for i in test_mer_file.rb test_hash_counter.rb test_string_mers.rb; do echo Test $i $RUBY "-I$LOADPATH" "$SRCDIR/swig/ruby/$i" . done Jellyfish-2.2.8/unit_tests/000077500000000000000000000000001323712541700156625ustar00rootroot00000000000000Jellyfish-2.2.8/unit_tests/Makefile000066400000000000000000000046151323712541700173300ustar00rootroot00000000000000# SYNOPSIS: # # make [all] - makes everything. # make TARGET - makes the given target. # make clean - removes all files generated by make. # Points to the root of Google Test, relative to where this file is. # Remember to tweak this if you move this file. GTEST_DIR = gtest-1.4.0 # Where to find user code. UPDIR = $(realpath ..) USER_DIR = $(UPDIR) VPATH = $(USER_DIR) CC = g++ # Flags passed to the preprocessor. CPPFLAGS += -I. -I$(GTEST_DIR) -I$(GTEST_DIR)/include $(patsubst %,-I%,$(USER_DIR)) -D__STDC_FORMAT_MACROS -D__STDC_CONSTANT_MACROS -DHAVE_SSE # Flags passed to the C++ compiler. # For profiling -fprofile-arcs -ftest-coverage -O0 # TODO: remove lax-vector-conversions CXXFLAGS += -g -Wall -Wextra -Werror -DSSE -march=native -msse -msse2 -O3 LDFLAGS = -lpthread -lrt -lm # All tests produced by this Makefile. Remember to add new tests you # created to the list. #TESTS = test_large_block test_mutex test_cond test_packed_key_value_array test_square_binary_matrix test_misc test_offsets_key_value TESTS = test_offsets_key_value SOURCES = $(patsubst %,%.cc,$(TESTS)) # All Google Test headers. Usually you shouldn't change this # definition. GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ $(GTEST_DIR)/include/gtest/internal/*.h # House-keeping build targets. %.d: %.cc $(CC) -M -MM -MG -MP $(CPPFLAGS) $< > $@.tmp sed -e 's/$*.o/& $@/g' $@.tmp > $@ && rm $@.tmp all : $(TESTS) run: all @for i in $(TESTS); do ./$$i; done clean : rm -f $(TESTS) gtest.a gtest_main.a *.o $(TESTS): gtest_main.a # Some extra dependencies test_packed_key_value_array: storage.o test_square_binary_matrix: square_binary_matrix.o # Builds gtest.a and gtest_main.a. # Usually you shouldn't tweak such internal variables, indicated by a # trailing _. GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) # For simplicity and to avoid depending on Google Test's # implementation details, the dependencies specified below are # conservative and not optimized. This is fine as Google Test # compiles fast and for ordinary users its source rarely changes. gtest-all.o : $(GTEST_SRCS_) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest-all.cc gtest_main.o : $(GTEST_SRCS_) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest_main.cc gtest.a : gtest-all.o $(AR) $(ARFLAGS) $@ $^ gtest_main.a : gtest-all.o gtest_main.o $(AR) $(ARFLAGS) $@ $^ include $(SOURCES:.cc=.d) Jellyfish-2.2.8/unit_tests/gtest/000077500000000000000000000000001323712541700170105ustar00rootroot00000000000000Jellyfish-2.2.8/unit_tests/gtest/gtest.h000066400000000000000000031261431323712541700203210ustar00rootroot00000000000000// Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // // The Google C++ Testing Framework (Google Test) // // This header file defines the public API for Google Test. It should be // included by any test program that uses Google Test. // // IMPORTANT NOTE: Due to limitation of the C++ language, we have to // leave some internal implementation details in this header file. // They are clearly marked by comments like this: // // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // // Such code is NOT meant to be used by a user directly, and is subject // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user // program! // // Acknowledgment: Google Test borrowed the idea of automatic test // registration from Barthelemy Dagenais' (barthelemy@prologique.com) // easyUnit framework. #ifndef GTEST_INCLUDE_GTEST_GTEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_H_ #include #include #include // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) // // The Google C++ Testing Framework (Google Test) // // This header file declares functions and macros used internally by // Google Test. They are subject to change without notice. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: wan@google.com (Zhanyong Wan) // // Low-level types and utilities for porting Google Test to various // platforms. They are subject to change without notice. DO NOT USE // THEM IN USER CODE. // // This file is fundamental to Google Test. All other Google Test source // files are expected to #include this. Therefore, it cannot #include // any other Google Test header. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ // The user can define the following macros in the build script to // control Google Test's behavior. If the user doesn't define a macro // in this list, Google Test will define it. // // GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2) // is/isn't available. // GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions // are enabled. // GTEST_HAS_GLOBAL_STRING - Define it to 1/0 to indicate that ::string // is/isn't available (some systems define // ::string, which is different to std::string). // GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string // is/isn't available (some systems define // ::wstring, which is different to std::wstring). // GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular // expressions are/aren't available. // GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that // is/isn't available. // GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't // enabled. // GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that // std::wstring does/doesn't work (Google Test can // be used where std::wstring is unavailable). // GTEST_HAS_TR1_TUPLE - Define it to 1/0 to indicate tr1::tuple // is/isn't available. // GTEST_HAS_SEH - Define it to 1/0 to indicate whether the // compiler supports Microsoft's "Structured // Exception Handling". // GTEST_HAS_STREAM_REDIRECTION // - Define it to 1/0 to indicate whether the // platform supports I/O stream redirection using // dup() and dup2(). // GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google // Test's own tr1 tuple implementation should be // used. Unused when the user sets // GTEST_HAS_TR1_TUPLE to 0. // GTEST_LANG_CXX11 - Define it to 1/0 to indicate that Google Test // is building in C++11/C++98 mode. // GTEST_LINKED_AS_SHARED_LIBRARY // - Define to 1 when compiling tests that use // Google Test as a shared library (known as // DLL on Windows). // GTEST_CREATE_SHARED_LIBRARY // - Define to 1 when compiling Google Test itself // as a shared library. // This header defines the following utilities: // // Macros indicating the current platform (defined to 1 if compiled on // the given platform; otherwise undefined): // GTEST_OS_AIX - IBM AIX // GTEST_OS_CYGWIN - Cygwin // GTEST_OS_HPUX - HP-UX // GTEST_OS_LINUX - Linux // GTEST_OS_LINUX_ANDROID - Google Android // GTEST_OS_MAC - Mac OS X // GTEST_OS_IOS - iOS // GTEST_OS_IOS_SIMULATOR - iOS simulator // GTEST_OS_NACL - Google Native Client (NaCl) // GTEST_OS_OPENBSD - OpenBSD // GTEST_OS_QNX - QNX // GTEST_OS_SOLARIS - Sun Solaris // GTEST_OS_SYMBIAN - Symbian // GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile) // GTEST_OS_WINDOWS_DESKTOP - Windows Desktop // GTEST_OS_WINDOWS_MINGW - MinGW // GTEST_OS_WINDOWS_MOBILE - Windows Mobile // GTEST_OS_ZOS - z/OS // // Among the platforms, Cygwin, Linux, Max OS X, and Windows have the // most stable support. Since core members of the Google Test project // don't have access to other platforms, support for them may be less // stable. If you notice any problems on your platform, please notify // googletestframework@googlegroups.com (patches for fixing them are // even more welcome!). // // Note that it is possible that none of the GTEST_OS_* macros are defined. // // Macros indicating available Google Test features (defined to 1 if // the corresponding feature is supported; otherwise undefined): // GTEST_HAS_COMBINE - the Combine() function (for value-parameterized // tests) // GTEST_HAS_DEATH_TEST - death tests // GTEST_HAS_PARAM_TEST - value-parameterized tests // GTEST_HAS_TYPED_TEST - typed tests // GTEST_HAS_TYPED_TEST_P - type-parameterized tests // GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with // GTEST_HAS_POSIX_RE (see above) which users can // define themselves. // GTEST_USES_SIMPLE_RE - our own simple regex is used; // the above two are mutually exclusive. // GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ(). // // Macros for basic C++ coding: // GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. // GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a // variable don't have to be used. // GTEST_DISALLOW_ASSIGN_ - disables operator=. // GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. // GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. // // Synchronization: // Mutex, MutexLock, ThreadLocal, GetThreadCount() // - synchronization primitives. // GTEST_IS_THREADSAFE - defined to 1 to indicate that the above // synchronization primitives have real implementations // and Google Test is thread-safe; or 0 otherwise. // // Template meta programming: // is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only. // IteratorTraits - partial implementation of std::iterator_traits, which // is not available in libCstd when compiled with Sun C++. // // Smart pointers: // scoped_ptr - as in TR2. // // Regular expressions: // RE - a simple regular expression class using the POSIX // Extended Regular Expression syntax on UNIX-like // platforms, or a reduced regular exception syntax on // other platforms, including Windows. // // Logging: // GTEST_LOG_() - logs messages at the specified severity level. // LogToStderr() - directs all log messages to stderr. // FlushInfoLog() - flushes informational log messages. // // Stdout and stderr capturing: // CaptureStdout() - starts capturing stdout. // GetCapturedStdout() - stops capturing stdout and returns the captured // string. // CaptureStderr() - starts capturing stderr. // GetCapturedStderr() - stops capturing stderr and returns the captured // string. // // Integer types: // TypeWithSize - maps an integer to a int type. // Int32, UInt32, Int64, UInt64, TimeInMillis // - integers of known sizes. // BiggestInt - the biggest signed integer type. // // Command-line utilities: // GTEST_FLAG() - references a flag. // GTEST_DECLARE_*() - declares a flag. // GTEST_DEFINE_*() - defines a flag. // GetInjectableArgvs() - returns the command line as a vector of strings. // // Environment variable utilities: // GetEnv() - gets the value of an environment variable. // BoolFromGTestEnv() - parses a bool environment variable. // Int32FromGTestEnv() - parses an Int32 environment variable. // StringFromGTestEnv() - parses a string environment variable. #include // for isspace, etc #include // for ptrdiff_t #include #include #include #ifndef _WIN32_WCE # include # include #endif // !_WIN32_WCE #if defined __APPLE__ # include # include #endif #include // NOLINT #include // NOLINT #include // NOLINT #define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" #define GTEST_FLAG_PREFIX_ "gtest_" #define GTEST_FLAG_PREFIX_DASH_ "gtest-" #define GTEST_FLAG_PREFIX_UPPER_ "GTEST_" #define GTEST_NAME_ "Google Test" #define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/" // Determines the version of gcc that is used to compile this. #ifdef __GNUC__ // 40302 means version 4.3.2. # define GTEST_GCC_VER_ \ (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) #endif // __GNUC__ // Determines the platform on which Google Test is compiled. #ifdef __CYGWIN__ # define GTEST_OS_CYGWIN 1 #elif defined __SYMBIAN32__ # define GTEST_OS_SYMBIAN 1 #elif defined _WIN32 # define GTEST_OS_WINDOWS 1 # ifdef _WIN32_WCE # define GTEST_OS_WINDOWS_MOBILE 1 # elif defined(__MINGW__) || defined(__MINGW32__) # define GTEST_OS_WINDOWS_MINGW 1 # else # define GTEST_OS_WINDOWS_DESKTOP 1 # endif // _WIN32_WCE #elif defined __APPLE__ # define GTEST_OS_MAC 1 # if TARGET_OS_IPHONE # define GTEST_OS_IOS 1 # if TARGET_IPHONE_SIMULATOR # define GTEST_OS_IOS_SIMULATOR 1 # endif # endif #elif defined __linux__ # define GTEST_OS_LINUX 1 # if defined __ANDROID__ # define GTEST_OS_LINUX_ANDROID 1 # endif #elif defined __MVS__ # define GTEST_OS_ZOS 1 #elif defined(__sun) && defined(__SVR4) # define GTEST_OS_SOLARIS 1 #elif defined(_AIX) # define GTEST_OS_AIX 1 #elif defined(__hpux) # define GTEST_OS_HPUX 1 #elif defined __native_client__ # define GTEST_OS_NACL 1 #elif defined __OpenBSD__ # define GTEST_OS_OPENBSD 1 #elif defined __QNX__ # define GTEST_OS_QNX 1 #endif // __CYGWIN__ #ifndef GTEST_LANG_CXX11 // gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when // -std={c,gnu}++{0x,11} is passed. The C++11 standard specifies a // value for __cplusplus, and recent versions of clang, gcc, and // probably other compilers set that too in C++11 mode. # if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L // Compiling in at least C++11 mode. # define GTEST_LANG_CXX11 1 # else # define GTEST_LANG_CXX11 0 # endif #endif // Brings in definitions for functions used in the testing::internal::posix // namespace (read, write, close, chdir, isatty, stat). We do not currently // use them on Windows Mobile. #if !GTEST_OS_WINDOWS // This assumes that non-Windows OSes provide unistd.h. For OSes where this // is not the case, we need to include headers that provide the functions // mentioned above. # include # include #elif !GTEST_OS_WINDOWS_MOBILE # include # include #endif #if GTEST_OS_LINUX_ANDROID // Used to define __ANDROID_API__ matching the target NDK API level. # include // NOLINT #endif // Defines this to true iff Google Test can use POSIX regular expressions. #ifndef GTEST_HAS_POSIX_RE # if GTEST_OS_LINUX_ANDROID // On Android, is only available starting with Gingerbread. # define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) # else # define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) # endif #endif #if GTEST_HAS_POSIX_RE // On some platforms, needs someone to define size_t, and // won't compile otherwise. We can #include it here as we already // included , which is guaranteed to define size_t through // . # include // NOLINT # define GTEST_USES_POSIX_RE 1 #elif GTEST_OS_WINDOWS // is not available on Windows. Use our own simple regex // implementation instead. # define GTEST_USES_SIMPLE_RE 1 #else // may not be available on this platform. Use our own // simple regex implementation instead. # define GTEST_USES_SIMPLE_RE 1 #endif // GTEST_HAS_POSIX_RE #ifndef GTEST_HAS_EXCEPTIONS // The user didn't tell us whether exceptions are enabled, so we need // to figure it out. # if defined(_MSC_VER) || defined(__BORLANDC__) // MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS // macro to enable exceptions, so we'll do the same. // Assumes that exceptions are enabled by default. # ifndef _HAS_EXCEPTIONS # define _HAS_EXCEPTIONS 1 # endif // _HAS_EXCEPTIONS # define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS # elif defined(__GNUC__) && __EXCEPTIONS // gcc defines __EXCEPTIONS to 1 iff exceptions are enabled. # define GTEST_HAS_EXCEPTIONS 1 # elif defined(__SUNPRO_CC) // Sun Pro CC supports exceptions. However, there is no compile-time way of // detecting whether they are enabled or not. Therefore, we assume that // they are enabled unless the user tells us otherwise. # define GTEST_HAS_EXCEPTIONS 1 # elif defined(__IBMCPP__) && __EXCEPTIONS // xlC defines __EXCEPTIONS to 1 iff exceptions are enabled. # define GTEST_HAS_EXCEPTIONS 1 # elif defined(__HP_aCC) // Exception handling is in effect by default in HP aCC compiler. It has to // be turned of by +noeh compiler option if desired. # define GTEST_HAS_EXCEPTIONS 1 # else // For other compilers, we assume exceptions are disabled to be // conservative. # define GTEST_HAS_EXCEPTIONS 0 # endif // defined(_MSC_VER) || defined(__BORLANDC__) #endif // GTEST_HAS_EXCEPTIONS #if !defined(GTEST_HAS_STD_STRING) // Even though we don't use this macro any longer, we keep it in case // some clients still depend on it. # define GTEST_HAS_STD_STRING 1 #elif !GTEST_HAS_STD_STRING // The user told us that ::std::string isn't available. # error "Google Test cannot be used where ::std::string isn't available." #endif // !defined(GTEST_HAS_STD_STRING) #ifndef GTEST_HAS_GLOBAL_STRING // The user didn't tell us whether ::string is available, so we need // to figure it out. # define GTEST_HAS_GLOBAL_STRING 0 #endif // GTEST_HAS_GLOBAL_STRING #ifndef GTEST_HAS_STD_WSTRING // The user didn't tell us whether ::std::wstring is available, so we need // to figure it out. // TODO(wan@google.com): uses autoconf to detect whether ::std::wstring // is available. // Cygwin 1.7 and below doesn't support ::std::wstring. // Solaris' libc++ doesn't support it either. Android has // no support for it at least as recent as Froyo (2.2). # define GTEST_HAS_STD_WSTRING \ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS)) #endif // GTEST_HAS_STD_WSTRING #ifndef GTEST_HAS_GLOBAL_WSTRING // The user didn't tell us whether ::wstring is available, so we need // to figure it out. # define GTEST_HAS_GLOBAL_WSTRING \ (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING) #endif // GTEST_HAS_GLOBAL_WSTRING // Determines whether RTTI is available. #ifndef GTEST_HAS_RTTI // The user didn't tell us whether RTTI is enabled, so we need to // figure it out. # ifdef _MSC_VER # ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled. # define GTEST_HAS_RTTI 1 # else # define GTEST_HAS_RTTI 0 # endif // Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled. # elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302) # ifdef __GXX_RTTI // When building against STLport with the Android NDK and with // -frtti -fno-exceptions, the build fails at link time with undefined // references to __cxa_bad_typeid. Note sure if STL or toolchain bug, // so disable RTTI when detected. # if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \ !defined(__EXCEPTIONS) # define GTEST_HAS_RTTI 0 # else # define GTEST_HAS_RTTI 1 # endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS # else # define GTEST_HAS_RTTI 0 # endif // __GXX_RTTI // Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends // using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the // first version with C++ support. # elif defined(__clang__) # define GTEST_HAS_RTTI __has_feature(cxx_rtti) // Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if // both the typeid and dynamic_cast features are present. # elif defined(__IBMCPP__) && (__IBMCPP__ >= 900) # ifdef __RTTI_ALL__ # define GTEST_HAS_RTTI 1 # else # define GTEST_HAS_RTTI 0 # endif # else // For all other compilers, we assume RTTI is enabled. # define GTEST_HAS_RTTI 1 # endif // _MSC_VER #endif // GTEST_HAS_RTTI // It's this header's responsibility to #include when RTTI // is enabled. #if GTEST_HAS_RTTI # include #endif // Determines whether Google Test can use the pthreads library. #ifndef GTEST_HAS_PTHREAD // The user didn't tell us explicitly, so we assume pthreads support is // available on Linux and Mac. // // To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 // to your compiler flags. # define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \ || GTEST_OS_QNX) #endif // GTEST_HAS_PTHREAD #if GTEST_HAS_PTHREAD // gtest-port.h guarantees to #include when GTEST_HAS_PTHREAD is // true. # include // NOLINT // For timespec and nanosleep, used below. # include // NOLINT #endif // Determines whether Google Test can use tr1/tuple. You can define // this macro to 0 to prevent Google Test from using tuple (any // feature depending on tuple with be disabled in this mode). #ifndef GTEST_HAS_TR1_TUPLE # if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) // STLport, provided with the Android NDK, has neither or . # define GTEST_HAS_TR1_TUPLE 0 # else // The user didn't tell us not to do it, so we assume it's OK. # define GTEST_HAS_TR1_TUPLE 1 # endif #endif // GTEST_HAS_TR1_TUPLE // Determines whether Google Test's own tr1 tuple implementation // should be used. #ifndef GTEST_USE_OWN_TR1_TUPLE // The user didn't tell us, so we need to figure it out. // We use our own TR1 tuple if we aren't sure the user has an // implementation of it already. At this time, libstdc++ 4.0.0+ and // MSVC 2010 are the only mainstream standard libraries that come // with a TR1 tuple implementation. NVIDIA's CUDA NVCC compiler // pretends to be GCC by defining __GNUC__ and friends, but cannot // compile GCC's tuple implementation. MSVC 2008 (9.0) provides TR1 // tuple in a 323 MB Feature Pack download, which we cannot assume the // user has. QNX's QCC compiler is a modified GCC but it doesn't // support TR1 tuple. libc++ only provides std::tuple, in C++11 mode, // and it can be used with some compilers that define __GNUC__. # if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \ && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600 # define GTEST_ENV_HAS_TR1_TUPLE_ 1 # endif // C++11 specifies that provides std::tuple. Use that if gtest is used // in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6 // can build with clang but need to use gcc4.2's libstdc++). # if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325) # define GTEST_ENV_HAS_STD_TUPLE_ 1 # endif # if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_ # define GTEST_USE_OWN_TR1_TUPLE 0 # else # define GTEST_USE_OWN_TR1_TUPLE 1 # endif #endif // GTEST_USE_OWN_TR1_TUPLE // To avoid conditional compilation everywhere, we make it // gtest-port.h's responsibility to #include the header implementing // tr1/tuple. #if GTEST_HAS_TR1_TUPLE # if GTEST_USE_OWN_TR1_TUPLE // This file was GENERATED by command: // pump.py gtest-tuple.h.pump // DO NOT EDIT BY HAND!!! // Copyright 2009 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // Implements a subset of TR1 tuple needed by Google Test and Google Mock. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ #include // For ::std::pair. // The compiler used in Symbian has a bug that prevents us from declaring the // tuple template as a friend (it complains that tuple is redefined). This // hack bypasses the bug by declaring the members that should otherwise be // private as public. // Sun Studio versions < 12 also have the above bug. #if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590) # define GTEST_DECLARE_TUPLE_AS_FRIEND_ public: #else # define GTEST_DECLARE_TUPLE_AS_FRIEND_ \ template friend class tuple; \ private: #endif // GTEST_n_TUPLE_(T) is the type of an n-tuple. #define GTEST_0_TUPLE_(T) tuple<> #define GTEST_1_TUPLE_(T) tuple #define GTEST_2_TUPLE_(T) tuple #define GTEST_3_TUPLE_(T) tuple #define GTEST_4_TUPLE_(T) tuple #define GTEST_5_TUPLE_(T) tuple #define GTEST_6_TUPLE_(T) tuple #define GTEST_7_TUPLE_(T) tuple #define GTEST_8_TUPLE_(T) tuple #define GTEST_9_TUPLE_(T) tuple #define GTEST_10_TUPLE_(T) tuple // GTEST_n_TYPENAMES_(T) declares a list of n typenames. #define GTEST_0_TYPENAMES_(T) #define GTEST_1_TYPENAMES_(T) typename T##0 #define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1 #define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2 #define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3 #define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3, typename T##4 #define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3, typename T##4, typename T##5 #define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3, typename T##4, typename T##5, typename T##6 #define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3, typename T##4, typename T##5, typename T##6, typename T##7 #define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3, typename T##4, typename T##5, typename T##6, \ typename T##7, typename T##8 #define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \ typename T##3, typename T##4, typename T##5, typename T##6, \ typename T##7, typename T##8, typename T##9 // In theory, defining stuff in the ::std namespace is undefined // behavior. We can do this as we are playing the role of a standard // library vendor. namespace std { namespace tr1 { template class tuple; // Anything in namespace gtest_internal is Google Test's INTERNAL // IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code. namespace gtest_internal { // ByRef::type is T if T is a reference; otherwise it's const T&. template struct ByRef { typedef const T& type; }; // NOLINT template struct ByRef { typedef T& type; }; // NOLINT // A handy wrapper for ByRef. #define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef::type // AddRef::type is T if T is a reference; otherwise it's T&. This // is the same as tr1::add_reference::type. template struct AddRef { typedef T& type; }; // NOLINT template struct AddRef { typedef T& type; }; // NOLINT // A handy wrapper for AddRef. #define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef::type // A helper for implementing get(). template class Get; // A helper for implementing tuple_element. kIndexValid is true // iff k < the number of fields in tuple type T. template struct TupleElement; template struct TupleElement { typedef T0 type; }; template struct TupleElement { typedef T1 type; }; template struct TupleElement { typedef T2 type; }; template struct TupleElement { typedef T3 type; }; template struct TupleElement { typedef T4 type; }; template struct TupleElement { typedef T5 type; }; template struct TupleElement { typedef T6 type; }; template struct TupleElement { typedef T7 type; }; template struct TupleElement { typedef T8 type; }; template struct TupleElement { typedef T9 type; }; } // namespace gtest_internal template <> class tuple<> { public: tuple() {} tuple(const tuple& /* t */) {} tuple& operator=(const tuple& /* t */) { return *this; } }; template class GTEST_1_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_() {} explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {} tuple(const tuple& t) : f0_(t.f0_) {} template tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_1_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) { f0_ = t.f0_; return *this; } T0 f0_; }; template class GTEST_2_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0), f1_(f1) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {} template tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {} template tuple(const ::std::pair& p) : f0_(p.first), f1_(p.second) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_2_TUPLE_(U)& t) { return CopyFrom(t); } template tuple& operator=(const ::std::pair& p) { f0_ = p.first; f1_ = p.second; return *this; } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; return *this; } T0 f0_; T1 f1_; }; template class GTEST_3_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} template tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_3_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; return *this; } T0 f0_; T1 f1_; T2 f2_; }; template class GTEST_4_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2), f3_(f3) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} template tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_4_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; }; template class GTEST_5_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_) {} template tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_5_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; f4_ = t.f4_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; T4 f4_; }; template class GTEST_6_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), f5_(f5) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} template tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_6_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; f4_ = t.f4_; f5_ = t.f5_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; T4 f4_; T5 f5_; }; template class GTEST_7_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), f5_(f5), f6_(f6) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} template tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_7_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; f4_ = t.f4_; f5_ = t.f5_; f6_ = t.f6_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; T4 f4_; T5 f5_; T6 f6_; }; template class GTEST_8_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} template tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_8_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; f4_ = t.f4_; f5_ = t.f5_; f6_ = t.f6_; f7_ = t.f7_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; T4 f4_; T5 f5_; T6 f6_; T7 f7_; }; template class GTEST_9_TUPLE_(T) { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} template tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_9_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; f4_ = t.f4_; f5_ = t.f5_; f6_ = t.f6_; f7_ = t.f7_; f8_ = t.f8_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; T4 f4_; T5 f5_; T6 f6_; T7 f7_; T8 f8_; }; template class tuple { public: template friend class gtest_internal::Get; tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(), f9_() {} explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1, GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4, GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7, GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {} tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} template tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {} tuple& operator=(const tuple& t) { return CopyFrom(t); } template tuple& operator=(const GTEST_10_TUPLE_(U)& t) { return CopyFrom(t); } GTEST_DECLARE_TUPLE_AS_FRIEND_ template tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) { f0_ = t.f0_; f1_ = t.f1_; f2_ = t.f2_; f3_ = t.f3_; f4_ = t.f4_; f5_ = t.f5_; f6_ = t.f6_; f7_ = t.f7_; f8_ = t.f8_; f9_ = t.f9_; return *this; } T0 f0_; T1 f1_; T2 f2_; T3 f3_; T4 f4_; T5 f5_; T6 f6_; T7 f7_; T8 f8_; T9 f9_; }; // 6.1.3.2 Tuple creation functions. // Known limitations: we don't support passing an // std::tr1::reference_wrapper to make_tuple(). And we don't // implement tie(). inline tuple<> make_tuple() { return tuple<>(); } template inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) { return GTEST_1_TUPLE_(T)(f0); } template inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) { return GTEST_2_TUPLE_(T)(f0, f1); } template inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) { return GTEST_3_TUPLE_(T)(f0, f1, f2); } template inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3) { return GTEST_4_TUPLE_(T)(f0, f1, f2, f3); } template inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3, const T4& f4) { return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4); } template inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3, const T4& f4, const T5& f5) { return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5); } template inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3, const T4& f4, const T5& f5, const T6& f6) { return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6); } template inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) { return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7); } template inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, const T8& f8) { return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8); } template inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2, const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7, const T8& f8, const T9& f9) { return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9); } // 6.1.3.3 Tuple helper classes. template struct tuple_size; template struct tuple_size { static const int value = 0; }; template struct tuple_size { static const int value = 1; }; template struct tuple_size { static const int value = 2; }; template struct tuple_size { static const int value = 3; }; template struct tuple_size { static const int value = 4; }; template struct tuple_size { static const int value = 5; }; template struct tuple_size { static const int value = 6; }; template struct tuple_size { static const int value = 7; }; template struct tuple_size { static const int value = 8; }; template struct tuple_size { static const int value = 9; }; template struct tuple_size { static const int value = 10; }; template struct tuple_element { typedef typename gtest_internal::TupleElement< k < (tuple_size::value), k, Tuple>::type type; }; #define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element::type // 6.1.3.4 Element access. namespace gtest_internal { template <> class Get<0> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) Field(Tuple& t) { return t.f0_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple)) ConstField(const Tuple& t) { return t.f0_; } }; template <> class Get<1> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) Field(Tuple& t) { return t.f1_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple)) ConstField(const Tuple& t) { return t.f1_; } }; template <> class Get<2> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) Field(Tuple& t) { return t.f2_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple)) ConstField(const Tuple& t) { return t.f2_; } }; template <> class Get<3> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) Field(Tuple& t) { return t.f3_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple)) ConstField(const Tuple& t) { return t.f3_; } }; template <> class Get<4> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) Field(Tuple& t) { return t.f4_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple)) ConstField(const Tuple& t) { return t.f4_; } }; template <> class Get<5> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) Field(Tuple& t) { return t.f5_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple)) ConstField(const Tuple& t) { return t.f5_; } }; template <> class Get<6> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) Field(Tuple& t) { return t.f6_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple)) ConstField(const Tuple& t) { return t.f6_; } }; template <> class Get<7> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) Field(Tuple& t) { return t.f7_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple)) ConstField(const Tuple& t) { return t.f7_; } }; template <> class Get<8> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) Field(Tuple& t) { return t.f8_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple)) ConstField(const Tuple& t) { return t.f8_; } }; template <> class Get<9> { public: template static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) Field(Tuple& t) { return t.f9_; } // NOLINT template static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple)) ConstField(const Tuple& t) { return t.f9_; } }; } // namespace gtest_internal template GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) get(GTEST_10_TUPLE_(T)& t) { return gtest_internal::Get::Field(t); } template GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T))) get(const GTEST_10_TUPLE_(T)& t) { return gtest_internal::Get::ConstField(t); } // 6.1.3.5 Relational operators // We only implement == and !=, as we don't have a need for the rest yet. namespace gtest_internal { // SameSizeTuplePrefixComparator::Eq(t1, t2) returns true if the // first k fields of t1 equals the first k fields of t2. // SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if // k1 != k2. template struct SameSizeTuplePrefixComparator; template <> struct SameSizeTuplePrefixComparator<0, 0> { template static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) { return true; } }; template struct SameSizeTuplePrefixComparator { template static bool Eq(const Tuple1& t1, const Tuple2& t2) { return SameSizeTuplePrefixComparator::Eq(t1, t2) && ::std::tr1::get(t1) == ::std::tr1::get(t2); } }; } // namespace gtest_internal template inline bool operator==(const GTEST_10_TUPLE_(T)& t, const GTEST_10_TUPLE_(U)& u) { return gtest_internal::SameSizeTuplePrefixComparator< tuple_size::value, tuple_size::value>::Eq(t, u); } template inline bool operator!=(const GTEST_10_TUPLE_(T)& t, const GTEST_10_TUPLE_(U)& u) { return !(t == u); } // 6.1.4 Pairs. // Unimplemented. } // namespace tr1 } // namespace std #undef GTEST_0_TUPLE_ #undef GTEST_1_TUPLE_ #undef GTEST_2_TUPLE_ #undef GTEST_3_TUPLE_ #undef GTEST_4_TUPLE_ #undef GTEST_5_TUPLE_ #undef GTEST_6_TUPLE_ #undef GTEST_7_TUPLE_ #undef GTEST_8_TUPLE_ #undef GTEST_9_TUPLE_ #undef GTEST_10_TUPLE_ #undef GTEST_0_TYPENAMES_ #undef GTEST_1_TYPENAMES_ #undef GTEST_2_TYPENAMES_ #undef GTEST_3_TYPENAMES_ #undef GTEST_4_TYPENAMES_ #undef GTEST_5_TYPENAMES_ #undef GTEST_6_TYPENAMES_ #undef GTEST_7_TYPENAMES_ #undef GTEST_8_TYPENAMES_ #undef GTEST_9_TYPENAMES_ #undef GTEST_10_TYPENAMES_ #undef GTEST_DECLARE_TUPLE_AS_FRIEND_ #undef GTEST_BY_REF_ #undef GTEST_ADD_REF_ #undef GTEST_TUPLE_ELEMENT_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_ # elif GTEST_ENV_HAS_STD_TUPLE_ # include // C++11 puts its tuple into the ::std namespace rather than // ::std::tr1. gtest expects tuple to live in ::std::tr1, so put it there. // This causes undefined behavior, but supported compilers react in // the way we intend. namespace std { namespace tr1 { using ::std::get; using ::std::make_tuple; using ::std::tuple; using ::std::tuple_element; using ::std::tuple_size; } } # elif GTEST_OS_SYMBIAN // On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to // use STLport's tuple implementation, which unfortunately doesn't // work as the copy of STLport distributed with Symbian is incomplete. // By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to // use its own tuple implementation. # ifdef BOOST_HAS_TR1_TUPLE # undef BOOST_HAS_TR1_TUPLE # endif // BOOST_HAS_TR1_TUPLE // This prevents , which defines // BOOST_HAS_TR1_TUPLE, from being #included by Boost's . # define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED # include # elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000) // GCC 4.0+ implements tr1/tuple in the header. This does // not conform to the TR1 spec, which requires the header to be . # if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 // Until version 4.3.2, gcc has a bug that causes , // which is #included by , to not compile when RTTI is // disabled. _TR1_FUNCTIONAL is the header guard for // . Hence the following #define is a hack to prevent // from being included. # define _TR1_FUNCTIONAL 1 # include # undef _TR1_FUNCTIONAL // Allows the user to #include // if he chooses to. # else # include // NOLINT # endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302 # else // If the compiler is not GCC 4.0+, we assume the user is using a // spec-conforming TR1 implementation. # include // NOLINT # endif // GTEST_USE_OWN_TR1_TUPLE #endif // GTEST_HAS_TR1_TUPLE // Determines whether clone(2) is supported. // Usually it will only be available on Linux, excluding // Linux on the Itanium architecture. // Also see http://linux.die.net/man/2/clone. #ifndef GTEST_HAS_CLONE // The user didn't tell us, so we need to figure it out. # if GTEST_OS_LINUX && !defined(__ia64__) # if GTEST_OS_LINUX_ANDROID // On Android, clone() is only available on ARM starting with Gingerbread. # if defined(__arm__) && __ANDROID_API__ >= 9 # define GTEST_HAS_CLONE 1 # else # define GTEST_HAS_CLONE 0 # endif # else # define GTEST_HAS_CLONE 1 # endif # else # define GTEST_HAS_CLONE 0 # endif // GTEST_OS_LINUX && !defined(__ia64__) #endif // GTEST_HAS_CLONE // Determines whether to support stream redirection. This is used to test // output correctness and to implement death tests. #ifndef GTEST_HAS_STREAM_REDIRECTION // By default, we assume that stream redirection is supported on all // platforms except known mobile ones. # if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN # define GTEST_HAS_STREAM_REDIRECTION 0 # else # define GTEST_HAS_STREAM_REDIRECTION 1 # endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN #endif // GTEST_HAS_STREAM_REDIRECTION // Determines whether to support death tests. // Google Test does not support death tests for VC 7.1 and earlier as // abort() in a VC 7.1 application compiled as GUI in debug config // pops up a dialog window that cannot be suppressed programmatically. #if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \ (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \ GTEST_OS_OPENBSD || GTEST_OS_QNX) # define GTEST_HAS_DEATH_TEST 1 # include // NOLINT #endif // We don't support MSVC 7.1 with exceptions disabled now. Therefore // all the compilers we care about are adequate for supporting // value-parameterized tests. #define GTEST_HAS_PARAM_TEST 1 // Determines whether to support type-driven tests. // Typed tests need and variadic macros, which GCC, VC++ 8.0, // Sun Pro CC, IBM Visual Age, and HP aCC support. #if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \ defined(__IBMCPP__) || defined(__HP_aCC) # define GTEST_HAS_TYPED_TEST 1 # define GTEST_HAS_TYPED_TEST_P 1 #endif // Determines whether to support Combine(). This only makes sense when // value-parameterized tests are enabled. The implementation doesn't // work on Sun Studio since it doesn't understand templated conversion // operators. #if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC) # define GTEST_HAS_COMBINE 1 #endif // Determines whether the system compiler uses UTF-16 for encoding wide strings. #define GTEST_WIDE_STRING_USES_UTF16_ \ (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX) // Determines whether test results can be streamed to a socket. #if GTEST_OS_LINUX # define GTEST_CAN_STREAM_RESULTS_ 1 #endif // Defines some utility macros. // The GNU compiler emits a warning if nested "if" statements are followed by // an "else" statement and braces are not used to explicitly disambiguate the // "else" binding. This leads to problems with code like: // // if (gate) // ASSERT_*(condition) << "Some message"; // // The "switch (0) case 0:" idiom is used to suppress this. #ifdef __INTEL_COMPILER # define GTEST_AMBIGUOUS_ELSE_BLOCKER_ #else # define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT #endif // Use this annotation at the end of a struct/class definition to // prevent the compiler from optimizing away instances that are never // used. This is useful when all interesting logic happens inside the // c'tor and / or d'tor. Example: // // struct Foo { // Foo() { ... } // } GTEST_ATTRIBUTE_UNUSED_; // // Also use it after a variable or parameter declaration to tell the // compiler the variable/parameter does not have to be used. #if defined(__GNUC__) && !defined(COMPILER_ICC) # define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused)) #else # define GTEST_ATTRIBUTE_UNUSED_ #endif // A macro to disallow operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_ASSIGN_(type)\ void operator=(type const &) // A macro to disallow copy constructor and operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\ type(type const &);\ GTEST_DISALLOW_ASSIGN_(type) // Tell the compiler to warn about unused return values for functions declared // with this macro. The macro should be used on function declarations // following the argument list: // // Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_; #if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC) # define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result)) #else # define GTEST_MUST_USE_RESULT_ #endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC // Determine whether the compiler supports Microsoft's Structured Exception // Handling. This is supported by several Windows compilers but generally // does not exist on any other system. #ifndef GTEST_HAS_SEH // The user didn't tell us, so we need to figure it out. # if defined(_MSC_VER) || defined(__BORLANDC__) // These two compilers are known to support SEH. # define GTEST_HAS_SEH 1 # else // Assume no SEH. # define GTEST_HAS_SEH 0 # endif #endif // GTEST_HAS_SEH #ifdef _MSC_VER # if GTEST_LINKED_AS_SHARED_LIBRARY # define GTEST_API_ __declspec(dllimport) # elif GTEST_CREATE_SHARED_LIBRARY # define GTEST_API_ __declspec(dllexport) # endif #endif // _MSC_VER #ifndef GTEST_API_ # define GTEST_API_ #endif #ifdef __GNUC__ // Ask the compiler to never inline a given function. # define GTEST_NO_INLINE_ __attribute__((noinline)) #else # define GTEST_NO_INLINE_ #endif // _LIBCPP_VERSION is defined by the libc++ library from the LLVM project. #if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) # define GTEST_HAS_CXXABI_H_ 1 #else # define GTEST_HAS_CXXABI_H_ 0 #endif namespace testing { class Message; namespace internal { // A secret type that Google Test users don't know about. It has no // definition on purpose. Therefore it's impossible to create a // Secret object, which is what we want. class Secret; // The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time // expression is true. For example, you could use it to verify the // size of a static array: // // GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, // content_type_names_incorrect_size); // // or to make sure a struct is smaller than a certain size: // // GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large); // // The second argument to the macro is the name of the variable. If // the expression is false, most compilers will issue a warning/error // containing the name of the variable. template struct CompileAssert { }; #define GTEST_COMPILE_ASSERT_(expr, msg) \ typedef ::testing::internal::CompileAssert<(static_cast(expr))> \ msg[static_cast(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_ // Implementation details of GTEST_COMPILE_ASSERT_: // // - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1 // elements (and thus is invalid) when the expression is false. // // - The simpler definition // // #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1] // // does not work, as gcc supports variable-length arrays whose sizes // are determined at run-time (this is gcc's extension and not part // of the C++ standard). As a result, gcc fails to reject the // following code with the simple definition: // // int foo; // GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is // // not a compile-time constant. // // - By using the type CompileAssert<(bool(expr))>, we ensures that // expr is a compile-time constant. (Template arguments must be // determined at compile-time.) // // - The outter parentheses in CompileAssert<(bool(expr))> are necessary // to work around a bug in gcc 3.4.4 and 4.0.1. If we had written // // CompileAssert // // instead, these compilers will refuse to compile // // GTEST_COMPILE_ASSERT_(5 > 0, some_message); // // (They seem to think the ">" in "5 > 0" marks the end of the // template argument list.) // // - The array size is (bool(expr) ? 1 : -1), instead of simply // // ((expr) ? 1 : -1). // // This is to avoid running into a bug in MS VC 7.1, which // causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. // StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h. // // This template is declared, but intentionally undefined. template struct StaticAssertTypeEqHelper; template struct StaticAssertTypeEqHelper {}; #if GTEST_HAS_GLOBAL_STRING typedef ::string string; #else typedef ::std::string string; #endif // GTEST_HAS_GLOBAL_STRING #if GTEST_HAS_GLOBAL_WSTRING typedef ::wstring wstring; #elif GTEST_HAS_STD_WSTRING typedef ::std::wstring wstring; #endif // GTEST_HAS_GLOBAL_WSTRING // A helper for suppressing warnings on constant condition. It just // returns 'condition'. GTEST_API_ bool IsTrue(bool condition); // Defines scoped_ptr. // This implementation of scoped_ptr is PARTIAL - it only contains // enough stuff to satisfy Google Test's need. template class scoped_ptr { public: typedef T element_type; explicit scoped_ptr(T* p = NULL) : ptr_(p) {} ~scoped_ptr() { reset(); } T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } T* get() const { return ptr_; } T* release() { T* const ptr = ptr_; ptr_ = NULL; return ptr; } void reset(T* p = NULL) { if (p != ptr_) { if (IsTrue(sizeof(T) > 0)) { // Makes sure T is a complete type. delete ptr_; } ptr_ = p; } } private: T* ptr_; GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr); }; // Defines RE. // A simple C++ wrapper for . It uses the POSIX Extended // Regular Expression syntax. class GTEST_API_ RE { public: // A copy constructor is required by the Standard to initialize object // references from r-values. RE(const RE& other) { Init(other.pattern()); } // Constructs an RE from a string. RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT #if GTEST_HAS_GLOBAL_STRING RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT #endif // GTEST_HAS_GLOBAL_STRING RE(const char* regex) { Init(regex); } // NOLINT ~RE(); // Returns the string representation of the regex. const char* pattern() const { return pattern_; } // FullMatch(str, re) returns true iff regular expression re matches // the entire str. // PartialMatch(str, re) returns true iff regular expression re // matches a substring of str (including str itself). // // TODO(wan@google.com): make FullMatch() and PartialMatch() work // when str contains NUL characters. static bool FullMatch(const ::std::string& str, const RE& re) { return FullMatch(str.c_str(), re); } static bool PartialMatch(const ::std::string& str, const RE& re) { return PartialMatch(str.c_str(), re); } #if GTEST_HAS_GLOBAL_STRING static bool FullMatch(const ::string& str, const RE& re) { return FullMatch(str.c_str(), re); } static bool PartialMatch(const ::string& str, const RE& re) { return PartialMatch(str.c_str(), re); } #endif // GTEST_HAS_GLOBAL_STRING static bool FullMatch(const char* str, const RE& re); static bool PartialMatch(const char* str, const RE& re); private: void Init(const char* regex); // We use a const char* instead of an std::string, as Google Test used to be // used where std::string is not available. TODO(wan@google.com): change to // std::string. const char* pattern_; bool is_valid_; #if GTEST_USES_POSIX_RE regex_t full_regex_; // For FullMatch(). regex_t partial_regex_; // For PartialMatch(). #else // GTEST_USES_SIMPLE_RE const char* full_pattern_; // For FullMatch(); #endif GTEST_DISALLOW_ASSIGN_(RE); }; // Formats a source file path and a line number as they would appear // in an error message from the compiler used to compile this code. GTEST_API_ ::std::string FormatFileLocation(const char* file, int line); // Formats a file location for compiler-independent XML output. // Although this function is not platform dependent, we put it next to // FormatFileLocation in order to contrast the two functions. GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file, int line); // Defines logging utilities: // GTEST_LOG_(severity) - logs messages at the specified severity level. The // message itself is streamed into the macro. // LogToStderr() - directs all log messages to stderr. // FlushInfoLog() - flushes informational log messages. enum GTestLogSeverity { GTEST_INFO, GTEST_WARNING, GTEST_ERROR, GTEST_FATAL }; // Formats log entry severity, provides a stream object for streaming the // log message, and terminates the message with a newline when going out of // scope. class GTEST_API_ GTestLog { public: GTestLog(GTestLogSeverity severity, const char* file, int line); // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. ~GTestLog(); ::std::ostream& GetStream() { return ::std::cerr; } private: const GTestLogSeverity severity_; GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog); }; #define GTEST_LOG_(severity) \ ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \ __FILE__, __LINE__).GetStream() inline void LogToStderr() {} inline void FlushInfoLog() { fflush(NULL); } // INTERNAL IMPLEMENTATION - DO NOT USE. // // GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition // is not satisfied. // Synopsys: // GTEST_CHECK_(boolean_condition); // or // GTEST_CHECK_(boolean_condition) << "Additional message"; // // This checks the condition and if the condition is not satisfied // it prints message about the condition violation, including the // condition itself, plus additional message streamed into it, if any, // and then it aborts the program. It aborts the program irrespective of // whether it is built in the debug mode or not. #define GTEST_CHECK_(condition) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::IsTrue(condition)) \ ; \ else \ GTEST_LOG_(FATAL) << "Condition " #condition " failed. " // An all-mode assert to verify that the given POSIX-style function // call returns 0 (indicating success). Known limitation: this // doesn't expand to a balanced 'if' statement, so enclose the macro // in {} if you need to use it as the only statement in an 'if' // branch. #define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \ if (const int gtest_error = (posix_call)) \ GTEST_LOG_(FATAL) << #posix_call << "failed with error " \ << gtest_error // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Use ImplicitCast_ as a safe version of static_cast for upcasting in // the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a // const Foo*). When you use ImplicitCast_, the compiler checks that // the cast is safe. Such explicit ImplicitCast_s are necessary in // surprisingly many situations where C++ demands an exact type match // instead of an argument type convertable to a target type. // // The syntax for using ImplicitCast_ is the same as for static_cast: // // ImplicitCast_(expr) // // ImplicitCast_ would have been part of the C++ standard library, // but the proposal was submitted too late. It will probably make // its way into the language in the future. // // This relatively ugly name is intentional. It prevents clashes with // similar functions users may have (e.g., implicit_cast). The internal // namespace alone is not enough because the function can be found by ADL. template inline To ImplicitCast_(To x) { return x; } // When you upcast (that is, cast a pointer from type Foo to type // SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts // always succeed. When you downcast (that is, cast a pointer from // type Foo to type SubclassOfFoo), static_cast<> isn't safe, because // how do you know the pointer is really of type SubclassOfFoo? It // could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, // when you downcast, you should use this macro. In debug mode, we // use dynamic_cast<> to double-check the downcast is legal (we die // if it's not). In normal mode, we do the efficient static_cast<> // instead. Thus, it's important to test in debug mode to make sure // the cast is legal! // This is the only place in the code we should use dynamic_cast<>. // In particular, you SHOULDN'T be using dynamic_cast<> in order to // do RTTI (eg code like this: // if (dynamic_cast(foo)) HandleASubclass1Object(foo); // if (dynamic_cast(foo)) HandleASubclass2Object(foo); // You should design the code some other way not to need this. // // This relatively ugly name is intentional. It prevents clashes with // similar functions users may have (e.g., down_cast). The internal // namespace alone is not enough because the function can be found by ADL. template // use like this: DownCast_(foo); inline To DownCast_(From* f) { // so we only accept pointers // Ensures that To is a sub-type of From *. This test is here only // for compile-time type checking, and has no overhead in an // optimized build at run-time, as it will be optimized away // completely. if (false) { const To to = NULL; ::testing::internal::ImplicitCast_(to); } #if GTEST_HAS_RTTI // RTTI: debug mode only! GTEST_CHECK_(f == NULL || dynamic_cast(f) != NULL); #endif return static_cast(f); } // Downcasts the pointer of type Base to Derived. // Derived must be a subclass of Base. The parameter MUST // point to a class of type Derived, not any subclass of it. // When RTTI is available, the function performs a runtime // check to enforce this. template Derived* CheckedDowncastToActualType(Base* base) { #if GTEST_HAS_RTTI GTEST_CHECK_(typeid(*base) == typeid(Derived)); return dynamic_cast(base); // NOLINT #else return static_cast(base); // Poor man's downcast. #endif } #if GTEST_HAS_STREAM_REDIRECTION // Defines the stderr capturer: // CaptureStdout - starts capturing stdout. // GetCapturedStdout - stops capturing stdout and returns the captured string. // CaptureStderr - starts capturing stderr. // GetCapturedStderr - stops capturing stderr and returns the captured string. // GTEST_API_ void CaptureStdout(); GTEST_API_ std::string GetCapturedStdout(); GTEST_API_ void CaptureStderr(); GTEST_API_ std::string GetCapturedStderr(); #endif // GTEST_HAS_STREAM_REDIRECTION #if GTEST_HAS_DEATH_TEST const ::std::vector& GetInjectableArgvs(); void SetInjectableArgvs(const ::std::vector* new_argvs); // A copy of all command line arguments. Set by InitGoogleTest(). extern ::std::vector g_argvs; #endif // GTEST_HAS_DEATH_TEST // Defines synchronization primitives. #if GTEST_HAS_PTHREAD // Sleeps for (roughly) n milli-seconds. This function is only for // testing Google Test's own constructs. Don't use it in user tests, // either directly or indirectly. inline void SleepMilliseconds(int n) { const timespec time = { 0, // 0 seconds. n * 1000L * 1000L, // And n ms. }; nanosleep(&time, NULL); } // Allows a controller thread to pause execution of newly created // threads until notified. Instances of this class must be created // and destroyed in the controller thread. // // This class is only for testing Google Test's own constructs. Do not // use it in user tests, either directly or indirectly. class Notification { public: Notification() : notified_(false) { GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); } ~Notification() { pthread_mutex_destroy(&mutex_); } // Notifies all threads created with this notification to start. Must // be called from the controller thread. void Notify() { pthread_mutex_lock(&mutex_); notified_ = true; pthread_mutex_unlock(&mutex_); } // Blocks until the controller thread notifies. Must be called from a test // thread. void WaitForNotification() { for (;;) { pthread_mutex_lock(&mutex_); const bool notified = notified_; pthread_mutex_unlock(&mutex_); if (notified) break; SleepMilliseconds(10); } } private: pthread_mutex_t mutex_; bool notified_; GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification); }; // As a C-function, ThreadFuncWithCLinkage cannot be templated itself. // Consequently, it cannot select a correct instantiation of ThreadWithParam // in order to call its Run(). Introducing ThreadWithParamBase as a // non-templated base class for ThreadWithParam allows us to bypass this // problem. class ThreadWithParamBase { public: virtual ~ThreadWithParamBase() {} virtual void Run() = 0; }; // pthread_create() accepts a pointer to a function type with the C linkage. // According to the Standard (7.5/1), function types with different linkages // are different even if they are otherwise identical. Some compilers (for // example, SunStudio) treat them as different types. Since class methods // cannot be defined with C-linkage we need to define a free C-function to // pass into pthread_create(). extern "C" inline void* ThreadFuncWithCLinkage(void* thread) { static_cast(thread)->Run(); return NULL; } // Helper class for testing Google Test's multi-threading constructs. // To use it, write: // // void ThreadFunc(int param) { /* Do things with param */ } // Notification thread_can_start; // ... // // The thread_can_start parameter is optional; you can supply NULL. // ThreadWithParam thread(&ThreadFunc, 5, &thread_can_start); // thread_can_start.Notify(); // // These classes are only for testing Google Test's own constructs. Do // not use them in user tests, either directly or indirectly. template class ThreadWithParam : public ThreadWithParamBase { public: typedef void (*UserThreadFunc)(T); ThreadWithParam( UserThreadFunc func, T param, Notification* thread_can_start) : func_(func), param_(param), thread_can_start_(thread_can_start), finished_(false) { ThreadWithParamBase* const base = this; // The thread can be created only after all fields except thread_ // have been initialized. GTEST_CHECK_POSIX_SUCCESS_( pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base)); } ~ThreadWithParam() { Join(); } void Join() { if (!finished_) { GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0)); finished_ = true; } } virtual void Run() { if (thread_can_start_ != NULL) thread_can_start_->WaitForNotification(); func_(param_); } private: const UserThreadFunc func_; // User-supplied thread function. const T param_; // User-supplied parameter to the thread function. // When non-NULL, used to block execution until the controller thread // notifies. Notification* const thread_can_start_; bool finished_; // true iff we know that the thread function has finished. pthread_t thread_; // The native thread object. GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam); }; // MutexBase and Mutex implement mutex on pthreads-based platforms. They // are used in conjunction with class MutexLock: // // Mutex mutex; // ... // MutexLock lock(&mutex); // Acquires the mutex and releases it at the end // // of the current scope. // // MutexBase implements behavior for both statically and dynamically // allocated mutexes. Do not use MutexBase directly. Instead, write // the following to define a static mutex: // // GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex); // // You can forward declare a static mutex like this: // // GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex); // // To create a dynamic mutex, just define an object of type Mutex. class MutexBase { public: // Acquires this mutex. void Lock() { GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_)); owner_ = pthread_self(); has_owner_ = true; } // Releases this mutex. void Unlock() { // Since the lock is being released the owner_ field should no longer be // considered valid. We don't protect writing to has_owner_ here, as it's // the caller's responsibility to ensure that the current thread holds the // mutex when this is called. has_owner_ = false; GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_)); } // Does nothing if the current thread holds the mutex. Otherwise, crashes // with high probability. void AssertHeld() const { GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self())) << "The current thread is not holding the mutex @" << this; } // A static mutex may be used before main() is entered. It may even // be used before the dynamic initialization stage. Therefore we // must be able to initialize a static mutex object at link time. // This means MutexBase has to be a POD and its member variables // have to be public. public: pthread_mutex_t mutex_; // The underlying pthread mutex. // has_owner_ indicates whether the owner_ field below contains a valid thread // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All // accesses to the owner_ field should be protected by a check of this field. // An alternative might be to memset() owner_ to all zeros, but there's no // guarantee that a zero'd pthread_t is necessarily invalid or even different // from pthread_self(). bool has_owner_; pthread_t owner_; // The thread holding the mutex. }; // Forward-declares a static mutex. # define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ extern ::testing::internal::MutexBase mutex // Defines and statically (i.e. at link time) initializes a static mutex. // The initialization list here does not explicitly initialize each field, // instead relying on default initialization for the unspecified fields. In // particular, the owner_ field (a pthread_t) is not explicitly initialized. // This allows initialization to work whether pthread_t is a scalar or struct. // The flag -Wmissing-field-initializers must not be specified for this to work. # define GTEST_DEFINE_STATIC_MUTEX_(mutex) \ ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false } // The Mutex class can only be used for mutexes created at runtime. It // shares its API with MutexBase otherwise. class Mutex : public MutexBase { public: Mutex() { GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL)); has_owner_ = false; } ~Mutex() { GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_)); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex); }; // We cannot name this class MutexLock as the ctor declaration would // conflict with a macro named MutexLock, which is defined on some // platforms. Hence the typedef trick below. class GTestMutexLock { public: explicit GTestMutexLock(MutexBase* mutex) : mutex_(mutex) { mutex_->Lock(); } ~GTestMutexLock() { mutex_->Unlock(); } private: MutexBase* const mutex_; GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock); }; typedef GTestMutexLock MutexLock; // Helpers for ThreadLocal. // pthread_key_create() requires DeleteThreadLocalValue() to have // C-linkage. Therefore it cannot be templatized to access // ThreadLocal. Hence the need for class // ThreadLocalValueHolderBase. class ThreadLocalValueHolderBase { public: virtual ~ThreadLocalValueHolderBase() {} }; // Called by pthread to delete thread-local data stored by // pthread_setspecific(). extern "C" inline void DeleteThreadLocalValue(void* value_holder) { delete static_cast(value_holder); } // Implements thread-local storage on pthreads-based systems. // // // Thread 1 // ThreadLocal tl(100); // 100 is the default value for each thread. // // // Thread 2 // tl.set(150); // Changes the value for thread 2 only. // EXPECT_EQ(150, tl.get()); // // // Thread 1 // EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value. // tl.set(200); // EXPECT_EQ(200, tl.get()); // // The template type argument T must have a public copy constructor. // In addition, the default ThreadLocal constructor requires T to have // a public default constructor. // // An object managed for a thread by a ThreadLocal instance is deleted // when the thread exits. Or, if the ThreadLocal instance dies in // that thread, when the ThreadLocal dies. It's the user's // responsibility to ensure that all other threads using a ThreadLocal // have exited when it dies, or the per-thread objects for those // threads will not be deleted. // // Google Test only uses global ThreadLocal objects. That means they // will die after main() has returned. Therefore, no per-thread // object managed by Google Test will be leaked as long as all threads // using Google Test have exited when main() returns. template class ThreadLocal { public: ThreadLocal() : key_(CreateKey()), default_() {} explicit ThreadLocal(const T& value) : key_(CreateKey()), default_(value) {} ~ThreadLocal() { // Destroys the managed object for the current thread, if any. DeleteThreadLocalValue(pthread_getspecific(key_)); // Releases resources associated with the key. This will *not* // delete managed objects for other threads. GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_)); } T* pointer() { return GetOrCreateValue(); } const T* pointer() const { return GetOrCreateValue(); } const T& get() const { return *pointer(); } void set(const T& value) { *pointer() = value; } private: // Holds a value of type T. class ValueHolder : public ThreadLocalValueHolderBase { public: explicit ValueHolder(const T& value) : value_(value) {} T* pointer() { return &value_; } private: T value_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder); }; static pthread_key_t CreateKey() { pthread_key_t key; // When a thread exits, DeleteThreadLocalValue() will be called on // the object managed for that thread. GTEST_CHECK_POSIX_SUCCESS_( pthread_key_create(&key, &DeleteThreadLocalValue)); return key; } T* GetOrCreateValue() const { ThreadLocalValueHolderBase* const holder = static_cast(pthread_getspecific(key_)); if (holder != NULL) { return CheckedDowncastToActualType(holder)->pointer(); } ValueHolder* const new_holder = new ValueHolder(default_); ThreadLocalValueHolderBase* const holder_base = new_holder; GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base)); return new_holder->pointer(); } // A key pthreads uses for looking up per-thread values. const pthread_key_t key_; const T default_; // The default value for each thread. GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal); }; # define GTEST_IS_THREADSAFE 1 #else // GTEST_HAS_PTHREAD // A dummy implementation of synchronization primitives (mutex, lock, // and thread-local variable). Necessary for compiling Google Test where // mutex is not supported - using Google Test in multiple threads is not // supported on such platforms. class Mutex { public: Mutex() {} void Lock() {} void Unlock() {} void AssertHeld() const {} }; # define GTEST_DECLARE_STATIC_MUTEX_(mutex) \ extern ::testing::internal::Mutex mutex # define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex class GTestMutexLock { public: explicit GTestMutexLock(Mutex*) {} // NOLINT }; typedef GTestMutexLock MutexLock; template class ThreadLocal { public: ThreadLocal() : value_() {} explicit ThreadLocal(const T& value) : value_(value) {} T* pointer() { return &value_; } const T* pointer() const { return &value_; } const T& get() const { return value_; } void set(const T& value) { value_ = value; } private: T value_; }; // The above synchronization primitives have dummy implementations. // Therefore Google Test is not thread-safe. # define GTEST_IS_THREADSAFE 0 #endif // GTEST_HAS_PTHREAD // Returns the number of threads running in the process, or 0 to indicate that // we cannot detect it. GTEST_API_ size_t GetThreadCount(); // Passing non-POD classes through ellipsis (...) crashes the ARM // compiler and generates a warning in Sun Studio. The Nokia Symbian // and the IBM XL C/C++ compiler try to instantiate a copy constructor // for objects passed through ellipsis (...), failing for uncopyable // objects. We define this to ensure that only POD is passed through // ellipsis on these systems. #if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC) // We lose support for NULL detection where the compiler doesn't like // passing non-POD classes through ellipsis (...). # define GTEST_ELLIPSIS_NEEDS_POD_ 1 #else # define GTEST_CAN_COMPARE_NULL 1 #endif // The Nokia Symbian and IBM XL C/C++ compilers cannot decide between // const T& and const T* in a function template. These compilers // _can_ decide between class template specializations for T and T*, // so a tr1::type_traits-like is_pointer works. #if defined(__SYMBIAN32__) || defined(__IBMCPP__) # define GTEST_NEEDS_IS_POINTER_ 1 #endif template struct bool_constant { typedef bool_constant type; static const bool value = bool_value; }; template const bool bool_constant::value; typedef bool_constant false_type; typedef bool_constant true_type; template struct is_pointer : public false_type {}; template struct is_pointer : public true_type {}; template struct IteratorTraits { typedef typename Iterator::value_type value_type; }; template struct IteratorTraits { typedef T value_type; }; template struct IteratorTraits { typedef T value_type; }; #if GTEST_OS_WINDOWS # define GTEST_PATH_SEP_ "\\" # define GTEST_HAS_ALT_PATH_SEP_ 1 // The biggest signed integer type the compiler supports. typedef __int64 BiggestInt; #else # define GTEST_PATH_SEP_ "/" # define GTEST_HAS_ALT_PATH_SEP_ 0 typedef long long BiggestInt; // NOLINT #endif // GTEST_OS_WINDOWS // Utilities for char. // isspace(int ch) and friends accept an unsigned char or EOF. char // may be signed, depending on the compiler (or compiler flags). // Therefore we need to cast a char to unsigned char before calling // isspace(), etc. inline bool IsAlpha(char ch) { return isalpha(static_cast(ch)) != 0; } inline bool IsAlNum(char ch) { return isalnum(static_cast(ch)) != 0; } inline bool IsDigit(char ch) { return isdigit(static_cast(ch)) != 0; } inline bool IsLower(char ch) { return islower(static_cast(ch)) != 0; } inline bool IsSpace(char ch) { return isspace(static_cast(ch)) != 0; } inline bool IsUpper(char ch) { return isupper(static_cast(ch)) != 0; } inline bool IsXDigit(char ch) { return isxdigit(static_cast(ch)) != 0; } inline bool IsXDigit(wchar_t ch) { const unsigned char low_byte = static_cast(ch); return ch == low_byte && isxdigit(low_byte) != 0; } inline char ToLower(char ch) { return static_cast(tolower(static_cast(ch))); } inline char ToUpper(char ch) { return static_cast(toupper(static_cast(ch))); } // The testing::internal::posix namespace holds wrappers for common // POSIX functions. These wrappers hide the differences between // Windows/MSVC and POSIX systems. Since some compilers define these // standard functions as macros, the wrapper cannot have the same name // as the wrapped function. namespace posix { // Functions with a different name on Windows. #if GTEST_OS_WINDOWS typedef struct _stat StatStruct; # ifdef __BORLANDC__ inline int IsATTY(int fd) { return isatty(fd); } inline int StrCaseCmp(const char* s1, const char* s2) { return stricmp(s1, s2); } inline char* StrDup(const char* src) { return strdup(src); } # else // !__BORLANDC__ # if GTEST_OS_WINDOWS_MOBILE inline int IsATTY(int /* fd */) { return 0; } # else inline int IsATTY(int fd) { return _isatty(fd); } # endif // GTEST_OS_WINDOWS_MOBILE inline int StrCaseCmp(const char* s1, const char* s2) { return _stricmp(s1, s2); } inline char* StrDup(const char* src) { return _strdup(src); } # endif // __BORLANDC__ # if GTEST_OS_WINDOWS_MOBILE inline int FileNo(FILE* file) { return reinterpret_cast(_fileno(file)); } // Stat(), RmDir(), and IsDir() are not needed on Windows CE at this // time and thus not defined there. # else inline int FileNo(FILE* file) { return _fileno(file); } inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); } inline int RmDir(const char* dir) { return _rmdir(dir); } inline bool IsDir(const StatStruct& st) { return (_S_IFDIR & st.st_mode) != 0; } # endif // GTEST_OS_WINDOWS_MOBILE #else typedef struct stat StatStruct; inline int FileNo(FILE* file) { return fileno(file); } inline int IsATTY(int fd) { return isatty(fd); } inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } inline int StrCaseCmp(const char* s1, const char* s2) { return strcasecmp(s1, s2); } inline char* StrDup(const char* src) { return strdup(src); } inline int RmDir(const char* dir) { return rmdir(dir); } inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } #endif // GTEST_OS_WINDOWS // Functions deprecated by MSVC 8.0. #ifdef _MSC_VER // Temporarily disable warning 4996 (deprecated function). # pragma warning(push) # pragma warning(disable:4996) #endif inline const char* StrNCpy(char* dest, const char* src, size_t n) { return strncpy(dest, src, n); } // ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and // StrError() aren't needed on Windows CE at this time and thus not // defined there. #if !GTEST_OS_WINDOWS_MOBILE inline int ChDir(const char* dir) { return chdir(dir); } #endif inline FILE* FOpen(const char* path, const char* mode) { return fopen(path, mode); } #if !GTEST_OS_WINDOWS_MOBILE inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { return freopen(path, mode, stream); } inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); } #endif inline int FClose(FILE* fp) { return fclose(fp); } #if !GTEST_OS_WINDOWS_MOBILE inline int Read(int fd, void* buf, unsigned int count) { return static_cast(read(fd, buf, count)); } inline int Write(int fd, const void* buf, unsigned int count) { return static_cast(write(fd, buf, count)); } inline int Close(int fd) { return close(fd); } inline const char* StrError(int errnum) { return strerror(errnum); } #endif inline const char* GetEnv(const char* name) { #if GTEST_OS_WINDOWS_MOBILE // We are on Windows CE, which has no environment variables. return NULL; #elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) // Environment variables which we programmatically clear will be set to the // empty string rather than unset (NULL). Handle that case. const char* const env = getenv(name); return (env != NULL && env[0] != '\0') ? env : NULL; #else return getenv(name); #endif } #ifdef _MSC_VER # pragma warning(pop) // Restores the warning state. #endif #if GTEST_OS_WINDOWS_MOBILE // Windows CE has no C library. The abort() function is used in // several places in Google Test. This implementation provides a reasonable // imitation of standard behaviour. void Abort(); #else inline void Abort() { abort(); } #endif // GTEST_OS_WINDOWS_MOBILE } // namespace posix // MSVC "deprecates" snprintf and issues warnings wherever it is used. In // order to avoid these warnings, we need to use _snprintf or _snprintf_s on // MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate // function in order to achieve that. We use macro definition here because // snprintf is a variadic function. #if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE // MSVC 2005 and above support variadic macros. # define GTEST_SNPRINTF_(buffer, size, format, ...) \ _snprintf_s(buffer, size, size, format, __VA_ARGS__) #elif defined(_MSC_VER) // Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't // complain about _snprintf. # define GTEST_SNPRINTF_ _snprintf #else # define GTEST_SNPRINTF_ snprintf #endif // The maximum number a BiggestInt can represent. This definition // works no matter BiggestInt is represented in one's complement or // two's complement. // // We cannot rely on numeric_limits in STL, as __int64 and long long // are not part of standard C++ and numeric_limits doesn't need to be // defined for them. const BiggestInt kMaxBiggestInt = ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); // This template class serves as a compile-time function from size to // type. It maps a size in bytes to a primitive type with that // size. e.g. // // TypeWithSize<4>::UInt // // is typedef-ed to be unsigned int (unsigned integer made up of 4 // bytes). // // Such functionality should belong to STL, but I cannot find it // there. // // Google Test uses this class in the implementation of floating-point // comparison. // // For now it only handles UInt (unsigned int) as that's all Google Test // needs. Other types can be easily added in the future if need // arises. template class TypeWithSize { public: // This prevents the user from using TypeWithSize with incorrect // values of N. typedef void UInt; }; // The specialization for size 4. template <> class TypeWithSize<4> { public: // unsigned int has size 4 in both gcc and MSVC. // // As base/basictypes.h doesn't compile on Windows, we cannot use // uint32, uint64, and etc here. typedef int Int; typedef unsigned int UInt; }; // The specialization for size 8. template <> class TypeWithSize<8> { public: #if GTEST_OS_WINDOWS typedef __int64 Int; typedef unsigned __int64 UInt; #else typedef long long Int; // NOLINT typedef unsigned long long UInt; // NOLINT #endif // GTEST_OS_WINDOWS }; // Integer types of known sizes. typedef TypeWithSize<4>::Int Int32; typedef TypeWithSize<4>::UInt UInt32; typedef TypeWithSize<8>::Int Int64; typedef TypeWithSize<8>::UInt UInt64; typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Utilities for command line flags and environment variables. // Macro for referencing flags. #define GTEST_FLAG(name) FLAGS_gtest_##name // Macros for declaring flags. #define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) #define GTEST_DECLARE_int32_(name) \ GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) #define GTEST_DECLARE_string_(name) \ GTEST_API_ extern ::std::string GTEST_FLAG(name) // Macros for defining flags. #define GTEST_DEFINE_bool_(name, default_val, doc) \ GTEST_API_ bool GTEST_FLAG(name) = (default_val) #define GTEST_DEFINE_int32_(name, default_val, doc) \ GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) #define GTEST_DEFINE_string_(name, default_val, doc) \ GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) // Thread annotations #define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks) #define GTEST_LOCK_EXCLUDED_(locks) // Parses 'str' for a 32-bit signed integer. If successful, writes the result // to *value and returns true; otherwise leaves *value unchanged and returns // false. // TODO(chandlerc): Find a better way to refactor flag and environment parsing // out of both gtest-port.cc and gtest.cc to avoid exporting this utility // function. bool ParseInt32(const Message& src_text, const char* str, Int32* value); // Parses a bool/Int32/string from the environment variable // corresponding to the given Google Test flag. bool BoolFromGTestEnv(const char* flag, bool default_val); GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); const char* StringFromGTestEnv(const char* flag, const char* default_val); } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ #if GTEST_OS_LINUX # include # include # include # include #endif // GTEST_OS_LINUX #if GTEST_HAS_EXCEPTIONS # include #endif #include #include #include #include #include #include // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // // The Google C++ Testing Framework (Google Test) // // This header file defines the Message class. // // IMPORTANT NOTE: Due to limitation of the C++ language, we have to // leave some internal implementation details in this header file. // They are clearly marked by comments like this: // // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // // Such code is NOT meant to be used by a user directly, and is subject // to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user // program! #ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #include // Ensures that there is at least one operator<< in the global namespace. // See Message& operator<<(...) below for why. void operator<<(const testing::internal::Secret&, int); namespace testing { // The Message class works like an ostream repeater. // // Typical usage: // // 1. You stream a bunch of values to a Message object. // It will remember the text in a stringstream. // 2. Then you stream the Message object to an ostream. // This causes the text in the Message to be streamed // to the ostream. // // For example; // // testing::Message foo; // foo << 1 << " != " << 2; // std::cout << foo; // // will print "1 != 2". // // Message is not intended to be inherited from. In particular, its // destructor is not virtual. // // Note that stringstream behaves differently in gcc and in MSVC. You // can stream a NULL char pointer to it in the former, but not in the // latter (it causes an access violation if you do). The Message // class hides this difference by treating a NULL char pointer as // "(null)". class GTEST_API_ Message { private: // The type of basic IO manipulators (endl, ends, and flush) for // narrow streams. typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&); public: // Constructs an empty Message. Message(); // Copy constructor. Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT *ss_ << msg.GetString(); } // Constructs a Message from a C-string. explicit Message(const char* str) : ss_(new ::std::stringstream) { *ss_ << str; } #if GTEST_OS_SYMBIAN // Streams a value (either a pointer or not) to this object. template inline Message& operator <<(const T& value) { StreamHelper(typename internal::is_pointer::type(), value); return *this; } #else // Streams a non-pointer value to this object. template inline Message& operator <<(const T& val) { // Some libraries overload << for STL containers. These // overloads are defined in the global namespace instead of ::std. // // C++'s symbol lookup rule (i.e. Koenig lookup) says that these // overloads are visible in either the std namespace or the global // namespace, but not other namespaces, including the testing // namespace which Google Test's Message class is in. // // To allow STL containers (and other types that has a << operator // defined in the global namespace) to be used in Google Test // assertions, testing::Message must access the custom << operator // from the global namespace. With this using declaration, // overloads of << defined in the global namespace and those // visible via Koenig lookup are both exposed in this function. using ::operator <<; *ss_ << val; return *this; } // Streams a pointer value to this object. // // This function is an overload of the previous one. When you // stream a pointer to a Message, this definition will be used as it // is more specialized. (The C++ Standard, section // [temp.func.order].) If you stream a non-pointer, then the // previous definition will be used. // // The reason for this overload is that streaming a NULL pointer to // ostream is undefined behavior. Depending on the compiler, you // may get "0", "(nil)", "(null)", or an access violation. To // ensure consistent result across compilers, we always treat NULL // as "(null)". template inline Message& operator <<(T* const& pointer) { // NOLINT if (pointer == NULL) { *ss_ << "(null)"; } else { *ss_ << pointer; } return *this; } #endif // GTEST_OS_SYMBIAN // Since the basic IO manipulators are overloaded for both narrow // and wide streams, we have to provide this specialized definition // of operator <<, even though its body is the same as the // templatized version above. Without this definition, streaming // endl or other basic IO manipulators to Message will confuse the // compiler. Message& operator <<(BasicNarrowIoManip val) { *ss_ << val; return *this; } // Instead of 1/0, we want to see true/false for bool values. Message& operator <<(bool b) { return *this << (b ? "true" : "false"); } // These two overloads allow streaming a wide C string to a Message // using the UTF-8 encoding. Message& operator <<(const wchar_t* wide_c_str); Message& operator <<(wchar_t* wide_c_str); #if GTEST_HAS_STD_WSTRING // Converts the given wide string to a narrow string using the UTF-8 // encoding, and streams the result to this Message object. Message& operator <<(const ::std::wstring& wstr); #endif // GTEST_HAS_STD_WSTRING #if GTEST_HAS_GLOBAL_WSTRING // Converts the given wide string to a narrow string using the UTF-8 // encoding, and streams the result to this Message object. Message& operator <<(const ::wstring& wstr); #endif // GTEST_HAS_GLOBAL_WSTRING // Gets the text streamed to this object so far as an std::string. // Each '\0' character in the buffer is replaced with "\\0". // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. std::string GetString() const; private: #if GTEST_OS_SYMBIAN // These are needed as the Nokia Symbian Compiler cannot decide between // const T& and const T* in a function template. The Nokia compiler _can_ // decide between class template specializations for T and T*, so a // tr1::type_traits-like is_pointer works, and we can overload on that. template inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) { if (pointer == NULL) { *ss_ << "(null)"; } else { *ss_ << pointer; } } template inline void StreamHelper(internal::false_type /*is_pointer*/, const T& value) { // See the comments in Message& operator <<(const T&) above for why // we need this using statement. using ::operator <<; *ss_ << value; } #endif // GTEST_OS_SYMBIAN // We'll hold the text streamed to this object here. const internal::scoped_ptr< ::std::stringstream> ss_; // We declare (but don't implement) this to prevent the compiler // from implementing the assignment operator. void operator=(const Message&); }; // Streams a Message to an ostream. inline std::ostream& operator <<(std::ostream& os, const Message& sb) { return os << sb.GetString(); } namespace internal { // Converts a streamable value to an std::string. A NULL pointer is // converted to "(null)". When the input value is a ::string, // ::std::string, ::wstring, or ::std::wstring object, each NUL // character in it is replaced with "\\0". template std::string StreamableToString(const T& streamable) { return (Message() << streamable).GetString(); } } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) // // The Google C++ Testing Framework (Google Test) // // This header file declares the String class and functions used internally by // Google Test. They are subject to change without notice. They should not used // by code external to Google Test. // // This header file is #included by . // It should not be #included by other files. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #ifdef __BORLANDC__ // string.h is not guaranteed to provide strcpy on C++ Builder. # include #endif #include #include namespace testing { namespace internal { // String - an abstract class holding static string utilities. class GTEST_API_ String { public: // Static utility methods // Clones a 0-terminated C string, allocating memory using new. The // caller is responsible for deleting the return value using // delete[]. Returns the cloned string, or NULL if the input is // NULL. // // This is different from strdup() in string.h, which allocates // memory using malloc(). static const char* CloneCString(const char* c_str); #if GTEST_OS_WINDOWS_MOBILE // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be // able to pass strings to Win32 APIs on CE we need to convert them // to 'Unicode', UTF-16. // Creates a UTF-16 wide string from the given ANSI string, allocating // memory using new. The caller is responsible for deleting the return // value using delete[]. Returns the wide string, or NULL if the // input is NULL. // // The wide string is created using the ANSI codepage (CP_ACP) to // match the behaviour of the ANSI versions of Win32 calls and the // C runtime. static LPCWSTR AnsiToUtf16(const char* c_str); // Creates an ANSI string from the given wide string, allocating // memory using new. The caller is responsible for deleting the return // value using delete[]. Returns the ANSI string, or NULL if the // input is NULL. // // The returned string is created using the ANSI codepage (CP_ACP) to // match the behaviour of the ANSI versions of Win32 calls and the // C runtime. static const char* Utf16ToAnsi(LPCWSTR utf16_str); #endif // Compares two C strings. Returns true iff they have the same content. // // Unlike strcmp(), this function can handle NULL argument(s). A // NULL C string is considered different to any non-NULL C string, // including the empty string. static bool CStringEquals(const char* lhs, const char* rhs); // Converts a wide C string to a String using the UTF-8 encoding. // NULL will be converted to "(null)". If an error occurred during // the conversion, "(failed to convert from wide string)" is // returned. static std::string ShowWideCString(const wchar_t* wide_c_str); // Compares two wide C strings. Returns true iff they have the same // content. // // Unlike wcscmp(), this function can handle NULL argument(s). A // NULL C string is considered different to any non-NULL C string, // including the empty string. static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); // Compares two C strings, ignoring case. Returns true iff they // have the same content. // // Unlike strcasecmp(), this function can handle NULL argument(s). // A NULL C string is considered different to any non-NULL C string, // including the empty string. static bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs); // Compares two wide C strings, ignoring case. Returns true iff they // have the same content. // // Unlike wcscasecmp(), this function can handle NULL argument(s). // A NULL C string is considered different to any non-NULL wide C string, // including the empty string. // NB: The implementations on different platforms slightly differ. // On windows, this method uses _wcsicmp which compares according to LC_CTYPE // environment variable. On GNU platform this method uses wcscasecmp // which compares according to LC_CTYPE category of the current locale. // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the // current locale. static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs, const wchar_t* rhs); // Returns true iff the given string ends with the given suffix, ignoring // case. Any string is considered to end with an empty suffix. static bool EndsWithCaseInsensitive( const std::string& str, const std::string& suffix); // Formats an int value as "%02d". static std::string FormatIntWidth2(int value); // "%02d" for width == 2 // Formats an int value as "%X". static std::string FormatHexInt(int value); // Formats a byte as "%02X". static std::string FormatByte(unsigned char value); private: String(); // Not meant to be instantiated. }; // class String // Gets the content of the stringstream's buffer as an std::string. Each '\0' // character in the buffer is replaced with "\\0". GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: keith.ray@gmail.com (Keith Ray) // // Google Test filepath utilities // // This header file declares classes and functions used internally by // Google Test. They are subject to change without notice. // // This file is #included in . // Do not include this header file separately! #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ namespace testing { namespace internal { // FilePath - a class for file and directory pathname manipulation which // handles platform-specific conventions (like the pathname separator). // Used for helper functions for naming files in a directory for xml output. // Except for Set methods, all methods are const or static, which provides an // "immutable value object" -- useful for peace of mind. // A FilePath with a value ending in a path separator ("like/this/") represents // a directory, otherwise it is assumed to represent a file. In either case, // it may or may not represent an actual file or directory in the file system. // Names are NOT checked for syntax correctness -- no checking for illegal // characters, malformed paths, etc. class GTEST_API_ FilePath { public: FilePath() : pathname_("") { } FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { } explicit FilePath(const std::string& pathname) : pathname_(pathname) { Normalize(); } FilePath& operator=(const FilePath& rhs) { Set(rhs); return *this; } void Set(const FilePath& rhs) { pathname_ = rhs.pathname_; } const std::string& string() const { return pathname_; } const char* c_str() const { return pathname_.c_str(); } // Returns the current working directory, or "" if unsuccessful. static FilePath GetCurrentDir(); // Given directory = "dir", base_name = "test", number = 0, // extension = "xml", returns "dir/test.xml". If number is greater // than zero (e.g., 12), returns "dir/test_12.xml". // On Windows platform, uses \ as the separator rather than /. static FilePath MakeFileName(const FilePath& directory, const FilePath& base_name, int number, const char* extension); // Given directory = "dir", relative_path = "test.xml", // returns "dir/test.xml". // On Windows, uses \ as the separator rather than /. static FilePath ConcatPaths(const FilePath& directory, const FilePath& relative_path); // Returns a pathname for a file that does not currently exist. The pathname // will be directory/base_name.extension or // directory/base_name_.extension if directory/base_name.extension // already exists. The number will be incremented until a pathname is found // that does not already exist. // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. // There could be a race condition if two or more processes are calling this // function at the same time -- they could both pick the same filename. static FilePath GenerateUniqueFileName(const FilePath& directory, const FilePath& base_name, const char* extension); // Returns true iff the path is "". bool IsEmpty() const { return pathname_.empty(); } // If input name has a trailing separator character, removes it and returns // the name, otherwise return the name string unmodified. // On Windows platform, uses \ as the separator, other platforms use /. FilePath RemoveTrailingPathSeparator() const; // Returns a copy of the FilePath with the directory part removed. // Example: FilePath("path/to/file").RemoveDirectoryName() returns // FilePath("file"). If there is no directory part ("just_a_file"), it returns // the FilePath unmodified. If there is no file part ("just_a_dir/") it // returns an empty FilePath (""). // On Windows platform, '\' is the path separator, otherwise it is '/'. FilePath RemoveDirectoryName() const; // RemoveFileName returns the directory path with the filename removed. // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". // If the FilePath is "a_file" or "/a_file", RemoveFileName returns // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does // not have a file, like "just/a/dir/", it returns the FilePath unmodified. // On Windows platform, '\' is the path separator, otherwise it is '/'. FilePath RemoveFileName() const; // Returns a copy of the FilePath with the case-insensitive extension removed. // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns // FilePath("dir/file"). If a case-insensitive extension is not // found, returns a copy of the original FilePath. FilePath RemoveExtension(const char* extension) const; // Creates directories so that path exists. Returns true if successful or if // the directories already exist; returns false if unable to create // directories for any reason. Will also return false if the FilePath does // not represent a directory (that is, it doesn't end with a path separator). bool CreateDirectoriesRecursively() const; // Create the directory so that path exists. Returns true if successful or // if the directory already exists; returns false if unable to create the // directory for any reason, including if the parent directory does not // exist. Not named "CreateDirectory" because that's a macro on Windows. bool CreateFolder() const; // Returns true if FilePath describes something in the file-system, // either a file, directory, or whatever, and that something exists. bool FileOrDirectoryExists() const; // Returns true if pathname describes a directory in the file-system // that exists. bool DirectoryExists() const; // Returns true if FilePath ends with a path separator, which indicates that // it is intended to represent a directory. Returns false otherwise. // This does NOT check that a directory (or file) actually exists. bool IsDirectory() const; // Returns true if pathname describes a root directory. (Windows has one // root directory per disk drive.) bool IsRootDirectory() const; // Returns true if pathname describes an absolute path. bool IsAbsolutePath() const; private: // Replaces multiple consecutive separators with a single separator. // For example, "bar///foo" becomes "bar/foo". Does not eliminate other // redundancies that might be in a pathname involving "." or "..". // // A pathname with multiple consecutive separators may occur either through // user error or as a result of some scripts or APIs that generate a pathname // with a trailing separator. On other platforms the same API or script // may NOT generate a pathname with a trailing "/". Then elsewhere that // pathname may have another "/" and pathname components added to it, // without checking for the separator already being there. // The script language and operating system may allow paths like "foo//bar" // but some of the functions in FilePath will not handle that correctly. In // particular, RemoveTrailingPathSeparator() only removes one separator, and // it is called in CreateDirectoriesRecursively() assuming that it will change // a pathname from directory syntax (trailing separator) to filename syntax. // // On Windows this method also replaces the alternate path separator '/' with // the primary path separator '\\', so that for example "bar\\/\\foo" becomes // "bar\\foo". void Normalize(); // Returns a pointer to the last occurence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FindLastPathSeparator() const; std::string pathname_; }; // class FilePath } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ // This file was GENERATED by command: // pump.py gtest-type-util.h.pump // DO NOT EDIT BY HAND!!! // Copyright 2008 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // Type utilities needed for implementing typed and type-parameterized // tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! // // Currently we support at most 50 types in a list, and at most 50 // type-parameterized tests in one type-parameterized test case. // Please contact googletestframework@googlegroups.com if you need // more. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ // #ifdef __GNUC__ is too general here. It is possible to use gcc without using // libstdc++ (which is where cxxabi.h comes from). # if GTEST_HAS_CXXABI_H_ # include # elif defined(__HP_aCC) # include # endif // GTEST_HASH_CXXABI_H_ namespace testing { namespace internal { // GetTypeName() returns a human-readable name of type T. // NB: This function is also used in Google Mock, so don't move it inside of // the typed-test-only section below. template std::string GetTypeName() { # if GTEST_HAS_RTTI const char* const name = typeid(T).name(); # if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) int status = 0; // gcc's implementation of typeid(T).name() mangles the type name, // so we have to demangle it. # if GTEST_HAS_CXXABI_H_ using abi::__cxa_demangle; # endif // GTEST_HAS_CXXABI_H_ char* const readable_name = __cxa_demangle(name, 0, 0, &status); const std::string name_str(status == 0 ? readable_name : name); free(readable_name); return name_str; # else return name; # endif // GTEST_HAS_CXXABI_H_ || __HP_aCC # else return ""; # endif // GTEST_HAS_RTTI } #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P // AssertyTypeEq::type is defined iff T1 and T2 are the same // type. This can be used as a compile-time assertion to ensure that // two types are equal. template struct AssertTypeEq; template struct AssertTypeEq { typedef bool type; }; // A unique type used as the default value for the arguments of class // template Types. This allows us to simulate variadic templates // (e.g. Types, Type, and etc), which C++ doesn't // support directly. struct None {}; // The following family of struct and struct templates are used to // represent type lists. In particular, TypesN // represents a type list with N types (T1, T2, ..., and TN) in it. // Except for Types0, every struct in the family has two member types: // Head for the first type in the list, and Tail for the rest of the // list. // The empty type list. struct Types0 {}; // Type lists of length 1, 2, 3, and so on. template struct Types1 { typedef T1 Head; typedef Types0 Tail; }; template struct Types2 { typedef T1 Head; typedef Types1 Tail; }; template struct Types3 { typedef T1 Head; typedef Types2 Tail; }; template struct Types4 { typedef T1 Head; typedef Types3 Tail; }; template struct Types5 { typedef T1 Head; typedef Types4 Tail; }; template struct Types6 { typedef T1 Head; typedef Types5 Tail; }; template struct Types7 { typedef T1 Head; typedef Types6 Tail; }; template struct Types8 { typedef T1 Head; typedef Types7 Tail; }; template struct Types9 { typedef T1 Head; typedef Types8 Tail; }; template struct Types10 { typedef T1 Head; typedef Types9 Tail; }; template struct Types11 { typedef T1 Head; typedef Types10 Tail; }; template struct Types12 { typedef T1 Head; typedef Types11 Tail; }; template struct Types13 { typedef T1 Head; typedef Types12 Tail; }; template struct Types14 { typedef T1 Head; typedef Types13 Tail; }; template struct Types15 { typedef T1 Head; typedef Types14 Tail; }; template struct Types16 { typedef T1 Head; typedef Types15 Tail; }; template struct Types17 { typedef T1 Head; typedef Types16 Tail; }; template struct Types18 { typedef T1 Head; typedef Types17 Tail; }; template struct Types19 { typedef T1 Head; typedef Types18 Tail; }; template struct Types20 { typedef T1 Head; typedef Types19 Tail; }; template struct Types21 { typedef T1 Head; typedef Types20 Tail; }; template struct Types22 { typedef T1 Head; typedef Types21 Tail; }; template struct Types23 { typedef T1 Head; typedef Types22 Tail; }; template struct Types24 { typedef T1 Head; typedef Types23 Tail; }; template struct Types25 { typedef T1 Head; typedef Types24 Tail; }; template struct Types26 { typedef T1 Head; typedef Types25 Tail; }; template struct Types27 { typedef T1 Head; typedef Types26 Tail; }; template struct Types28 { typedef T1 Head; typedef Types27 Tail; }; template struct Types29 { typedef T1 Head; typedef Types28 Tail; }; template struct Types30 { typedef T1 Head; typedef Types29 Tail; }; template struct Types31 { typedef T1 Head; typedef Types30 Tail; }; template struct Types32 { typedef T1 Head; typedef Types31 Tail; }; template struct Types33 { typedef T1 Head; typedef Types32 Tail; }; template struct Types34 { typedef T1 Head; typedef Types33 Tail; }; template struct Types35 { typedef T1 Head; typedef Types34 Tail; }; template struct Types36 { typedef T1 Head; typedef Types35 Tail; }; template struct Types37 { typedef T1 Head; typedef Types36 Tail; }; template struct Types38 { typedef T1 Head; typedef Types37 Tail; }; template struct Types39 { typedef T1 Head; typedef Types38 Tail; }; template struct Types40 { typedef T1 Head; typedef Types39 Tail; }; template struct Types41 { typedef T1 Head; typedef Types40 Tail; }; template struct Types42 { typedef T1 Head; typedef Types41 Tail; }; template struct Types43 { typedef T1 Head; typedef Types42 Tail; }; template struct Types44 { typedef T1 Head; typedef Types43 Tail; }; template struct Types45 { typedef T1 Head; typedef Types44 Tail; }; template struct Types46 { typedef T1 Head; typedef Types45 Tail; }; template struct Types47 { typedef T1 Head; typedef Types46 Tail; }; template struct Types48 { typedef T1 Head; typedef Types47 Tail; }; template struct Types49 { typedef T1 Head; typedef Types48 Tail; }; template struct Types50 { typedef T1 Head; typedef Types49 Tail; }; } // namespace internal // We don't want to require the users to write TypesN<...> directly, // as that would require them to count the length. Types<...> is much // easier to write, but generates horrible messages when there is a // compiler error, as gcc insists on printing out each template // argument, even if it has the default value (this means Types // will appear as Types in the compiler // errors). // // Our solution is to combine the best part of the two approaches: a // user would write Types, and Google Test will translate // that to TypesN internally to make error messages // readable. The translation is done by the 'type' member of the // Types template. template struct Types { typedef internal::Types50 type; }; template <> struct Types { typedef internal::Types0 type; }; template struct Types { typedef internal::Types1 type; }; template struct Types { typedef internal::Types2 type; }; template struct Types { typedef internal::Types3 type; }; template struct Types { typedef internal::Types4 type; }; template struct Types { typedef internal::Types5 type; }; template struct Types { typedef internal::Types6 type; }; template struct Types { typedef internal::Types7 type; }; template struct Types { typedef internal::Types8 type; }; template struct Types { typedef internal::Types9 type; }; template struct Types { typedef internal::Types10 type; }; template struct Types { typedef internal::Types11 type; }; template struct Types { typedef internal::Types12 type; }; template struct Types { typedef internal::Types13 type; }; template struct Types { typedef internal::Types14 type; }; template struct Types { typedef internal::Types15 type; }; template struct Types { typedef internal::Types16 type; }; template struct Types { typedef internal::Types17 type; }; template struct Types { typedef internal::Types18 type; }; template struct Types { typedef internal::Types19 type; }; template struct Types { typedef internal::Types20 type; }; template struct Types { typedef internal::Types21 type; }; template struct Types { typedef internal::Types22 type; }; template struct Types { typedef internal::Types23 type; }; template struct Types { typedef internal::Types24 type; }; template struct Types { typedef internal::Types25 type; }; template struct Types { typedef internal::Types26 type; }; template struct Types { typedef internal::Types27 type; }; template struct Types { typedef internal::Types28 type; }; template struct Types { typedef internal::Types29 type; }; template struct Types { typedef internal::Types30 type; }; template struct Types { typedef internal::Types31 type; }; template struct Types { typedef internal::Types32 type; }; template struct Types { typedef internal::Types33 type; }; template struct Types { typedef internal::Types34 type; }; template struct Types { typedef internal::Types35 type; }; template struct Types { typedef internal::Types36 type; }; template struct Types { typedef internal::Types37 type; }; template struct Types { typedef internal::Types38 type; }; template struct Types { typedef internal::Types39 type; }; template struct Types { typedef internal::Types40 type; }; template struct Types { typedef internal::Types41 type; }; template struct Types { typedef internal::Types42 type; }; template struct Types { typedef internal::Types43 type; }; template struct Types { typedef internal::Types44 type; }; template struct Types { typedef internal::Types45 type; }; template struct Types { typedef internal::Types46 type; }; template struct Types { typedef internal::Types47 type; }; template struct Types { typedef internal::Types48 type; }; template struct Types { typedef internal::Types49 type; }; namespace internal { # define GTEST_TEMPLATE_ template class // The template "selector" struct TemplateSel is used to // represent Tmpl, which must be a class template with one type // parameter, as a type. TemplateSel::Bind::type is defined // as the type Tmpl. This allows us to actually instantiate the // template "selected" by TemplateSel. // // This trick is necessary for simulating typedef for class templates, // which C++ doesn't support directly. template struct TemplateSel { template struct Bind { typedef Tmpl type; }; }; # define GTEST_BIND_(TmplSel, T) \ TmplSel::template Bind::type // A unique struct template used as the default value for the // arguments of class template Templates. This allows us to simulate // variadic templates (e.g. Templates, Templates, // and etc), which C++ doesn't support directly. template struct NoneT {}; // The following family of struct and struct templates are used to // represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except // for Templates0, every struct in the family has two member types: // Head for the selector of the first template in the list, and Tail // for the rest of the list. // The empty template list. struct Templates0 {}; // Template lists of length 1, 2, 3, and so on. template struct Templates1 { typedef TemplateSel Head; typedef Templates0 Tail; }; template struct Templates2 { typedef TemplateSel Head; typedef Templates1 Tail; }; template struct Templates3 { typedef TemplateSel Head; typedef Templates2 Tail; }; template struct Templates4 { typedef TemplateSel Head; typedef Templates3 Tail; }; template struct Templates5 { typedef TemplateSel Head; typedef Templates4 Tail; }; template struct Templates6 { typedef TemplateSel Head; typedef Templates5 Tail; }; template struct Templates7 { typedef TemplateSel Head; typedef Templates6 Tail; }; template struct Templates8 { typedef TemplateSel Head; typedef Templates7 Tail; }; template struct Templates9 { typedef TemplateSel Head; typedef Templates8 Tail; }; template struct Templates10 { typedef TemplateSel Head; typedef Templates9 Tail; }; template struct Templates11 { typedef TemplateSel Head; typedef Templates10 Tail; }; template struct Templates12 { typedef TemplateSel Head; typedef Templates11 Tail; }; template struct Templates13 { typedef TemplateSel Head; typedef Templates12 Tail; }; template struct Templates14 { typedef TemplateSel Head; typedef Templates13 Tail; }; template struct Templates15 { typedef TemplateSel Head; typedef Templates14 Tail; }; template struct Templates16 { typedef TemplateSel Head; typedef Templates15 Tail; }; template struct Templates17 { typedef TemplateSel Head; typedef Templates16 Tail; }; template struct Templates18 { typedef TemplateSel Head; typedef Templates17 Tail; }; template struct Templates19 { typedef TemplateSel Head; typedef Templates18 Tail; }; template struct Templates20 { typedef TemplateSel Head; typedef Templates19 Tail; }; template struct Templates21 { typedef TemplateSel Head; typedef Templates20 Tail; }; template struct Templates22 { typedef TemplateSel Head; typedef Templates21 Tail; }; template struct Templates23 { typedef TemplateSel Head; typedef Templates22 Tail; }; template struct Templates24 { typedef TemplateSel Head; typedef Templates23 Tail; }; template struct Templates25 { typedef TemplateSel Head; typedef Templates24 Tail; }; template struct Templates26 { typedef TemplateSel Head; typedef Templates25 Tail; }; template struct Templates27 { typedef TemplateSel Head; typedef Templates26 Tail; }; template struct Templates28 { typedef TemplateSel Head; typedef Templates27 Tail; }; template struct Templates29 { typedef TemplateSel Head; typedef Templates28 Tail; }; template struct Templates30 { typedef TemplateSel Head; typedef Templates29 Tail; }; template struct Templates31 { typedef TemplateSel Head; typedef Templates30 Tail; }; template struct Templates32 { typedef TemplateSel Head; typedef Templates31 Tail; }; template struct Templates33 { typedef TemplateSel Head; typedef Templates32 Tail; }; template struct Templates34 { typedef TemplateSel Head; typedef Templates33 Tail; }; template struct Templates35 { typedef TemplateSel Head; typedef Templates34 Tail; }; template struct Templates36 { typedef TemplateSel Head; typedef Templates35 Tail; }; template struct Templates37 { typedef TemplateSel Head; typedef Templates36 Tail; }; template struct Templates38 { typedef TemplateSel Head; typedef Templates37 Tail; }; template struct Templates39 { typedef TemplateSel Head; typedef Templates38 Tail; }; template struct Templates40 { typedef TemplateSel Head; typedef Templates39 Tail; }; template struct Templates41 { typedef TemplateSel Head; typedef Templates40 Tail; }; template struct Templates42 { typedef TemplateSel Head; typedef Templates41 Tail; }; template struct Templates43 { typedef TemplateSel Head; typedef Templates42 Tail; }; template struct Templates44 { typedef TemplateSel Head; typedef Templates43 Tail; }; template struct Templates45 { typedef TemplateSel Head; typedef Templates44 Tail; }; template struct Templates46 { typedef TemplateSel Head; typedef Templates45 Tail; }; template struct Templates47 { typedef TemplateSel Head; typedef Templates46 Tail; }; template struct Templates48 { typedef TemplateSel Head; typedef Templates47 Tail; }; template struct Templates49 { typedef TemplateSel Head; typedef Templates48 Tail; }; template struct Templates50 { typedef TemplateSel Head; typedef Templates49 Tail; }; // We don't want to require the users to write TemplatesN<...> directly, // as that would require them to count the length. Templates<...> is much // easier to write, but generates horrible messages when there is a // compiler error, as gcc insists on printing out each template // argument, even if it has the default value (this means Templates // will appear as Templates in the compiler // errors). // // Our solution is to combine the best part of the two approaches: a // user would write Templates, and Google Test will translate // that to TemplatesN internally to make error messages // readable. The translation is done by the 'type' member of the // Templates template. template struct Templates { typedef Templates50 type; }; template <> struct Templates { typedef Templates0 type; }; template struct Templates { typedef Templates1 type; }; template struct Templates { typedef Templates2 type; }; template struct Templates { typedef Templates3 type; }; template struct Templates { typedef Templates4 type; }; template struct Templates { typedef Templates5 type; }; template struct Templates { typedef Templates6 type; }; template struct Templates { typedef Templates7 type; }; template struct Templates { typedef Templates8 type; }; template struct Templates { typedef Templates9 type; }; template struct Templates { typedef Templates10 type; }; template struct Templates { typedef Templates11 type; }; template struct Templates { typedef Templates12 type; }; template struct Templates { typedef Templates13 type; }; template struct Templates { typedef Templates14 type; }; template struct Templates { typedef Templates15 type; }; template struct Templates { typedef Templates16 type; }; template struct Templates { typedef Templates17 type; }; template struct Templates { typedef Templates18 type; }; template struct Templates { typedef Templates19 type; }; template struct Templates { typedef Templates20 type; }; template struct Templates { typedef Templates21 type; }; template struct Templates { typedef Templates22 type; }; template struct Templates { typedef Templates23 type; }; template struct Templates { typedef Templates24 type; }; template struct Templates { typedef Templates25 type; }; template struct Templates { typedef Templates26 type; }; template struct Templates { typedef Templates27 type; }; template struct Templates { typedef Templates28 type; }; template struct Templates { typedef Templates29 type; }; template struct Templates { typedef Templates30 type; }; template struct Templates { typedef Templates31 type; }; template struct Templates { typedef Templates32 type; }; template struct Templates { typedef Templates33 type; }; template struct Templates { typedef Templates34 type; }; template struct Templates { typedef Templates35 type; }; template struct Templates { typedef Templates36 type; }; template struct Templates { typedef Templates37 type; }; template struct Templates { typedef Templates38 type; }; template struct Templates { typedef Templates39 type; }; template struct Templates { typedef Templates40 type; }; template struct Templates { typedef Templates41 type; }; template struct Templates { typedef Templates42 type; }; template struct Templates { typedef Templates43 type; }; template struct Templates { typedef Templates44 type; }; template struct Templates { typedef Templates45 type; }; template struct Templates { typedef Templates46 type; }; template struct Templates { typedef Templates47 type; }; template struct Templates { typedef Templates48 type; }; template struct Templates { typedef Templates49 type; }; // The TypeList template makes it possible to use either a single type // or a Types<...> list in TYPED_TEST_CASE() and // INSTANTIATE_TYPED_TEST_CASE_P(). template struct TypeList { typedef Types1 type; }; template struct TypeList > { typedef typename Types::type type; }; #endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ // Due to C++ preprocessor weirdness, we need double indirection to // concatenate two tokens when one of them is __LINE__. Writing // // foo ## __LINE__ // // will result in the token foo__LINE__, instead of foo followed by // the current line number. For more details, see // http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 #define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar class ProtocolMessage; namespace proto2 { class Message; } namespace testing { // Forward declarations. class AssertionResult; // Result of an assertion. class Message; // Represents a failure message. class Test; // Represents a test. class TestInfo; // Information about a test. class TestPartResult; // Result of a test part. class UnitTest; // A collection of test cases. template ::std::string PrintToString(const T& value); namespace internal { struct TraceInfo; // Information about a trace point. class ScopedTrace; // Implements scoped trace. class TestInfoImpl; // Opaque implementation of TestInfo class UnitTestImpl; // Opaque implementation of UnitTest // How many times InitGoogleTest() has been called. GTEST_API_ extern int g_init_gtest_count; // The text used in failure messages to indicate the start of the // stack trace. GTEST_API_ extern const char kStackTraceMarker[]; // Two overloaded helpers for checking at compile time whether an // expression is a null pointer literal (i.e. NULL or any 0-valued // compile-time integral constant). Their return values have // different sizes, so we can use sizeof() to test which version is // picked by the compiler. These helpers have no implementations, as // we only need their signatures. // // Given IsNullLiteralHelper(x), the compiler will pick the first // version if x can be implicitly converted to Secret*, and pick the // second version otherwise. Since Secret is a secret and incomplete // type, the only expression a user can write that has type Secret* is // a null pointer literal. Therefore, we know that x is a null // pointer literal if and only if the first version is picked by the // compiler. char IsNullLiteralHelper(Secret* p); char (&IsNullLiteralHelper(...))[2]; // NOLINT // A compile-time bool constant that is true if and only if x is a // null pointer literal (i.e. NULL or any 0-valued compile-time // integral constant). #ifdef GTEST_ELLIPSIS_NEEDS_POD_ // We lose support for NULL detection where the compiler doesn't like // passing non-POD classes through ellipsis (...). # define GTEST_IS_NULL_LITERAL_(x) false #else # define GTEST_IS_NULL_LITERAL_(x) \ (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1) #endif // GTEST_ELLIPSIS_NEEDS_POD_ // Appends the user-supplied message to the Google-Test-generated message. GTEST_API_ std::string AppendUserMessage( const std::string& gtest_msg, const Message& user_msg); #if GTEST_HAS_EXCEPTIONS // This exception is thrown by (and only by) a failed Google Test // assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions // are enabled). We derive it from std::runtime_error, which is for // errors presumably detectable only at run time. Since // std::runtime_error inherits from std::exception, many testing // frameworks know how to extract and print the message inside it. class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error { public: explicit GoogleTestFailureException(const TestPartResult& failure); }; #endif // GTEST_HAS_EXCEPTIONS // A helper class for creating scoped traces in user programs. class GTEST_API_ ScopedTrace { public: // The c'tor pushes the given source file location and message onto // a trace stack maintained by Google Test. ScopedTrace(const char* file, int line, const Message& message); // The d'tor pops the info pushed by the c'tor. // // Note that the d'tor is not virtual in order to be efficient. // Don't inherit from ScopedTrace! ~ScopedTrace(); private: GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace); } GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its // c'tor and d'tor. Therefore it doesn't // need to be used otherwise. // Constructs and returns the message for an equality assertion // (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. // // The first four parameters are the expressions used in the assertion // and their values, as strings. For example, for ASSERT_EQ(foo, bar) // where foo is 5 and bar is 6, we have: // // expected_expression: "foo" // actual_expression: "bar" // expected_value: "5" // actual_value: "6" // // The ignoring_case parameter is true iff the assertion is a // *_STRCASEEQ*. When it's true, the string " (ignoring case)" will // be inserted into the message. GTEST_API_ AssertionResult EqFailure(const char* expected_expression, const char* actual_expression, const std::string& expected_value, const std::string& actual_value, bool ignoring_case); // Constructs a failure message for Boolean assertions such as EXPECT_TRUE. GTEST_API_ std::string GetBoolAssertionFailureMessage( const AssertionResult& assertion_result, const char* expression_text, const char* actual_predicate_value, const char* expected_predicate_value); // This template class represents an IEEE floating-point number // (either single-precision or double-precision, depending on the // template parameters). // // The purpose of this class is to do more sophisticated number // comparison. (Due to round-off error, etc, it's very unlikely that // two floating-points will be equal exactly. Hence a naive // comparison by the == operation often doesn't work.) // // Format of IEEE floating-point: // // The most-significant bit being the leftmost, an IEEE // floating-point looks like // // sign_bit exponent_bits fraction_bits // // Here, sign_bit is a single bit that designates the sign of the // number. // // For float, there are 8 exponent bits and 23 fraction bits. // // For double, there are 11 exponent bits and 52 fraction bits. // // More details can be found at // http://en.wikipedia.org/wiki/IEEE_floating-point_standard. // // Template parameter: // // RawType: the raw floating-point type (either float or double) template class FloatingPoint { public: // Defines the unsigned integer type that has the same size as the // floating point number. typedef typename TypeWithSize::UInt Bits; // Constants. // # of bits in a number. static const size_t kBitCount = 8*sizeof(RawType); // # of fraction bits in a number. static const size_t kFractionBitCount = std::numeric_limits::digits - 1; // # of exponent bits in a number. static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount; // The mask for the sign bit. static const Bits kSignBitMask = static_cast(1) << (kBitCount - 1); // The mask for the fraction bits. static const Bits kFractionBitMask = ~static_cast(0) >> (kExponentBitCount + 1); // The mask for the exponent bits. static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask); // How many ULP's (Units in the Last Place) we want to tolerate when // comparing two numbers. The larger the value, the more error we // allow. A 0 value means that two numbers must be exactly the same // to be considered equal. // // The maximum error of a single floating-point operation is 0.5 // units in the last place. On Intel CPU's, all floating-point // calculations are done with 80-bit precision, while double has 64 // bits. Therefore, 4 should be enough for ordinary use. // // See the following article for more details on ULP: // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ static const size_t kMaxUlps = 4; // Constructs a FloatingPoint from a raw floating-point number. // // On an Intel CPU, passing a non-normalized NAN (Not a Number) // around may change its bits, although the new value is guaranteed // to be also a NAN. Therefore, don't expect this constructor to // preserve the bits in x when x is a NAN. explicit FloatingPoint(const RawType& x) { u_.value_ = x; } // Static methods // Reinterprets a bit pattern as a floating-point number. // // This function is needed to test the AlmostEquals() method. static RawType ReinterpretBits(const Bits bits) { FloatingPoint fp(0); fp.u_.bits_ = bits; return fp.u_.value_; } // Returns the floating-point number that represent positive infinity. static RawType Infinity() { return ReinterpretBits(kExponentBitMask); } // Returns the maximum representable finite floating-point number. static RawType Max(); // Non-static methods // Returns the bits that represents this number. const Bits &bits() const { return u_.bits_; } // Returns the exponent bits of this number. Bits exponent_bits() const { return kExponentBitMask & u_.bits_; } // Returns the fraction bits of this number. Bits fraction_bits() const { return kFractionBitMask & u_.bits_; } // Returns the sign bit of this number. Bits sign_bit() const { return kSignBitMask & u_.bits_; } // Returns true iff this is NAN (not a number). bool is_nan() const { // It's a NAN if the exponent bits are all ones and the fraction // bits are not entirely zeros. return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0); } // Returns true iff this number is at most kMaxUlps ULP's away from // rhs. In particular, this function: // // - returns false if either number is (or both are) NAN. // - treats really large numbers as almost equal to infinity. // - thinks +0.0 and -0.0 are 0 DLP's apart. bool AlmostEquals(const FloatingPoint& rhs) const { // The IEEE standard says that any comparison operation involving // a NAN must return false. if (is_nan() || rhs.is_nan()) return false; return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_) <= kMaxUlps; } private: // The data type used to store the actual floating-point number. union FloatingPointUnion { RawType value_; // The raw floating-point number. Bits bits_; // The bits that represent the number. }; // Converts an integer from the sign-and-magnitude representation to // the biased representation. More precisely, let N be 2 to the // power of (kBitCount - 1), an integer x is represented by the // unsigned number x + N. // // For instance, // // -N + 1 (the most negative number representable using // sign-and-magnitude) is represented by 1; // 0 is represented by N; and // N - 1 (the biggest number representable using // sign-and-magnitude) is represented by 2N - 1. // // Read http://en.wikipedia.org/wiki/Signed_number_representations // for more details on signed number representations. static Bits SignAndMagnitudeToBiased(const Bits &sam) { if (kSignBitMask & sam) { // sam represents a negative number. return ~sam + 1; } else { // sam represents a positive number. return kSignBitMask | sam; } } // Given two numbers in the sign-and-magnitude representation, // returns the distance between them as an unsigned number. static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1, const Bits &sam2) { const Bits biased1 = SignAndMagnitudeToBiased(sam1); const Bits biased2 = SignAndMagnitudeToBiased(sam2); return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1); } FloatingPointUnion u_; }; // We cannot use std::numeric_limits::max() as it clashes with the max() // macro defined by . template <> inline float FloatingPoint::Max() { return FLT_MAX; } template <> inline double FloatingPoint::Max() { return DBL_MAX; } // Typedefs the instances of the FloatingPoint template class that we // care to use. typedef FloatingPoint Float; typedef FloatingPoint Double; // In order to catch the mistake of putting tests that use different // test fixture classes in the same test case, we need to assign // unique IDs to fixture classes and compare them. The TypeId type is // used to hold such IDs. The user should treat TypeId as an opaque // type: the only operation allowed on TypeId values is to compare // them for equality using the == operator. typedef const void* TypeId; template class TypeIdHelper { public: // dummy_ must not have a const type. Otherwise an overly eager // compiler (e.g. MSVC 7.1 & 8.0) may try to merge // TypeIdHelper::dummy_ for different Ts as an "optimization". static bool dummy_; }; template bool TypeIdHelper::dummy_ = false; // GetTypeId() returns the ID of type T. Different values will be // returned for different types. Calling the function twice with the // same type argument is guaranteed to return the same ID. template TypeId GetTypeId() { // The compiler is required to allocate a different // TypeIdHelper::dummy_ variable for each T used to instantiate // the template. Therefore, the address of dummy_ is guaranteed to // be unique. return &(TypeIdHelper::dummy_); } // Returns the type ID of ::testing::Test. Always call this instead // of GetTypeId< ::testing::Test>() to get the type ID of // ::testing::Test, as the latter may give the wrong result due to a // suspected linker bug when compiling Google Test as a Mac OS X // framework. GTEST_API_ TypeId GetTestTypeId(); // Defines the abstract factory interface that creates instances // of a Test object. class TestFactoryBase { public: virtual ~TestFactoryBase() {} // Creates a test instance to run. The instance is both created and destroyed // within TestInfoImpl::Run() virtual Test* CreateTest() = 0; protected: TestFactoryBase() {} private: GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase); }; // This class provides implementation of TeastFactoryBase interface. // It is used in TEST and TEST_F macros. template class TestFactoryImpl : public TestFactoryBase { public: virtual Test* CreateTest() { return new TestClass; } }; #if GTEST_OS_WINDOWS // Predicate-formatters for implementing the HRESULT checking macros // {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED} // We pass a long instead of HRESULT to avoid causing an // include dependency for the HRESULT type. GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr, long hr); // NOLINT GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr, long hr); // NOLINT #endif // GTEST_OS_WINDOWS // Types of SetUpTestCase() and TearDownTestCase() functions. typedef void (*SetUpTestCaseFunc)(); typedef void (*TearDownTestCaseFunc)(); // Creates a new TestInfo object and registers it with Google Test; // returns the created object. // // Arguments: // // test_case_name: name of the test case // name: name of the test // type_param the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. // value_param text representation of the test's value parameter, // or NULL if this is not a type-parameterized test. // fixture_class_id: ID of the test fixture class // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case // factory: pointer to the factory that creates a test object. // The newly created TestInfo instance will assume // ownership of the factory object. GTEST_API_ TestInfo* MakeAndRegisterTestInfo( const char* test_case_name, const char* name, const char* type_param, const char* value_param, TypeId fixture_class_id, SetUpTestCaseFunc set_up_tc, TearDownTestCaseFunc tear_down_tc, TestFactoryBase* factory); // If *pstr starts with the given prefix, modifies *pstr to be right // past the prefix and returns true; otherwise leaves *pstr unchanged // and returns false. None of pstr, *pstr, and prefix can be NULL. GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P // State of the definition of a type-parameterized test case. class GTEST_API_ TypedTestCasePState { public: TypedTestCasePState() : registered_(false) {} // Adds the given test name to defined_test_names_ and return true // if the test case hasn't been registered; otherwise aborts the // program. bool AddTestName(const char* file, int line, const char* case_name, const char* test_name) { if (registered_) { fprintf(stderr, "%s Test %s must be defined before " "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n", FormatFileLocation(file, line).c_str(), test_name, case_name); fflush(stderr); posix::Abort(); } defined_test_names_.insert(test_name); return true; } // Verifies that registered_tests match the test names in // defined_test_names_; returns registered_tests if successful, or // aborts the program otherwise. const char* VerifyRegisteredTestNames( const char* file, int line, const char* registered_tests); private: bool registered_; ::std::set defined_test_names_; }; // Skips to the first non-space char after the first comma in 'str'; // returns NULL if no comma is found in 'str'. inline const char* SkipComma(const char* str) { const char* comma = strchr(str, ','); if (comma == NULL) { return NULL; } while (IsSpace(*(++comma))) {} return comma; } // Returns the prefix of 'str' before the first comma in it; returns // the entire string if it contains no comma. inline std::string GetPrefixUntilComma(const char* str) { const char* comma = strchr(str, ','); return comma == NULL ? str : std::string(str, comma); } // TypeParameterizedTest::Register() // registers a list of type-parameterized tests with Google Test. The // return value is insignificant - we just need to return something // such that we can call this function in a namespace scope. // // Implementation note: The GTEST_TEMPLATE_ macro declares a template // template parameter. It's defined in gtest-type-util.h. template class TypeParameterizedTest { public: // 'index' is the index of the test in the type list 'Types' // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, // Types). Valid values for 'index' are [0, N - 1] where N is the // length of Types. static bool Register(const char* prefix, const char* case_name, const char* test_names, int index) { typedef typename Types::Head Type; typedef Fixture FixtureClass; typedef typename GTEST_BIND_(TestSel, Type) TestClass; // First, registers the first type-parameterized test in the type // list. MakeAndRegisterTestInfo( (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" + StreamableToString(index)).c_str(), GetPrefixUntilComma(test_names).c_str(), GetTypeName().c_str(), NULL, // No value parameter. GetTypeId(), TestClass::SetUpTestCase, TestClass::TearDownTestCase, new TestFactoryImpl); // Next, recurses (at compile time) with the tail of the type list. return TypeParameterizedTest ::Register(prefix, case_name, test_names, index + 1); } }; // The base case for the compile time recursion. template class TypeParameterizedTest { public: static bool Register(const char* /*prefix*/, const char* /*case_name*/, const char* /*test_names*/, int /*index*/) { return true; } }; // TypeParameterizedTestCase::Register() // registers *all combinations* of 'Tests' and 'Types' with Google // Test. The return value is insignificant - we just need to return // something such that we can call this function in a namespace scope. template class TypeParameterizedTestCase { public: static bool Register(const char* prefix, const char* case_name, const char* test_names) { typedef typename Tests::Head Head; // First, register the first test in 'Test' for each type in 'Types'. TypeParameterizedTest::Register( prefix, case_name, test_names, 0); // Next, recurses (at compile time) with the tail of the test list. return TypeParameterizedTestCase ::Register(prefix, case_name, SkipComma(test_names)); } }; // The base case for the compile time recursion. template class TypeParameterizedTestCase { public: static bool Register(const char* /*prefix*/, const char* /*case_name*/, const char* /*test_names*/) { return true; } }; #endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P // Returns the current OS stack trace as an std::string. // // The maximum number of stack frames to be included is specified by // the gtest_stack_trace_depth flag. The skip_count parameter // specifies the number of top frames to be skipped, which doesn't // count against the number of frames to be included. // // For example, if Foo() calls Bar(), which in turn calls // GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in // the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. GTEST_API_ std::string GetCurrentOsStackTraceExceptTop( UnitTest* unit_test, int skip_count); // Helpers for suppressing warnings on unreachable code or constant // condition. // Always returns true. GTEST_API_ bool AlwaysTrue(); // Always returns false. inline bool AlwaysFalse() { return !AlwaysTrue(); } // Helper for suppressing false warning from Clang on a const char* // variable declared in a conditional expression always being NULL in // the else branch. struct GTEST_API_ ConstCharPtr { ConstCharPtr(const char* str) : value(str) {} operator bool() const { return true; } const char* value; }; // A simple Linear Congruential Generator for generating random // numbers with a uniform distribution. Unlike rand() and srand(), it // doesn't use global state (and therefore can't interfere with user // code). Unlike rand_r(), it's portable. An LCG isn't very random, // but it's good enough for our purposes. class GTEST_API_ Random { public: static const UInt32 kMaxRange = 1u << 31; explicit Random(UInt32 seed) : state_(seed) {} void Reseed(UInt32 seed) { state_ = seed; } // Generates a random number from [0, range). Crashes if 'range' is // 0 or greater than kMaxRange. UInt32 Generate(UInt32 range); private: UInt32 state_; GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); }; // Defining a variable of type CompileAssertTypesEqual will cause a // compiler error iff T1 and T2 are different types. template struct CompileAssertTypesEqual; template struct CompileAssertTypesEqual { }; // Removes the reference from a type if it is a reference type, // otherwise leaves it unchanged. This is the same as // tr1::remove_reference, which is not widely available yet. template struct RemoveReference { typedef T type; }; // NOLINT template struct RemoveReference { typedef T type; }; // NOLINT // A handy wrapper around RemoveReference that works when the argument // T depends on template parameters. #define GTEST_REMOVE_REFERENCE_(T) \ typename ::testing::internal::RemoveReference::type // Removes const from a type if it is a const type, otherwise leaves // it unchanged. This is the same as tr1::remove_const, which is not // widely available yet. template struct RemoveConst { typedef T type; }; // NOLINT template struct RemoveConst { typedef T type; }; // NOLINT // MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above // definition to fail to remove the const in 'const int[3]' and 'const // char[3][4]'. The following specialization works around the bug. template struct RemoveConst { typedef typename RemoveConst::type type[N]; }; #if defined(_MSC_VER) && _MSC_VER < 1400 // This is the only specialization that allows VC++ 7.1 to remove const in // 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC // and thus needs to be conditionally compiled. template struct RemoveConst { typedef typename RemoveConst::type type[N]; }; #endif // A handy wrapper around RemoveConst that works when the argument // T depends on template parameters. #define GTEST_REMOVE_CONST_(T) \ typename ::testing::internal::RemoveConst::type // Turns const U&, U&, const U, and U all into U. #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T)) // Adds reference to a type if it is not a reference type, // otherwise leaves it unchanged. This is the same as // tr1::add_reference, which is not widely available yet. template struct AddReference { typedef T& type; }; // NOLINT template struct AddReference { typedef T& type; }; // NOLINT // A handy wrapper around AddReference that works when the argument T // depends on template parameters. #define GTEST_ADD_REFERENCE_(T) \ typename ::testing::internal::AddReference::type // Adds a reference to const on top of T as necessary. For example, // it transforms // // char ==> const char& // const char ==> const char& // char& ==> const char& // const char& ==> const char& // // The argument T must depend on some template parameters. #define GTEST_REFERENCE_TO_CONST_(T) \ GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T)) // ImplicitlyConvertible::value is a compile-time bool // constant that's true iff type From can be implicitly converted to // type To. template class ImplicitlyConvertible { private: // We need the following helper functions only for their types. // They have no implementations. // MakeFrom() is an expression whose type is From. We cannot simply // use From(), as the type From may not have a public default // constructor. static From MakeFrom(); // These two functions are overloaded. Given an expression // Helper(x), the compiler will pick the first version if x can be // implicitly converted to type To; otherwise it will pick the // second version. // // The first version returns a value of size 1, and the second // version returns a value of size 2. Therefore, by checking the // size of Helper(x), which can be done at compile time, we can tell // which version of Helper() is used, and hence whether x can be // implicitly converted to type To. static char Helper(To); static char (&Helper(...))[2]; // NOLINT // We have to put the 'public' section after the 'private' section, // or MSVC refuses to compile the code. public: // MSVC warns about implicitly converting from double to int for // possible loss of data, so we need to temporarily disable the // warning. #ifdef _MSC_VER # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4244) // Temporarily disables warning 4244. static const bool value = sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; # pragma warning(pop) // Restores the warning state. #elif defined(__BORLANDC__) // C++Builder cannot use member overload resolution during template // instantiation. The simplest workaround is to use its C++0x type traits // functions (C++Builder 2009 and above only). static const bool value = __is_convertible(From, To); #else static const bool value = sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; #endif // _MSV_VER }; template const bool ImplicitlyConvertible::value; // IsAProtocolMessage::value is a compile-time bool constant that's // true iff T is type ProtocolMessage, proto2::Message, or a subclass // of those. template struct IsAProtocolMessage : public bool_constant< ImplicitlyConvertible::value || ImplicitlyConvertible::value> { }; // When the compiler sees expression IsContainerTest(0), if C is an // STL-style container class, the first overload of IsContainerTest // will be viable (since both C::iterator* and C::const_iterator* are // valid types and NULL can be implicitly converted to them). It will // be picked over the second overload as 'int' is a perfect match for // the type of argument 0. If C::iterator or C::const_iterator is not // a valid type, the first overload is not viable, and the second // overload will be picked. Therefore, we can determine whether C is // a container class by checking the type of IsContainerTest(0). // The value of the expression is insignificant. // // Note that we look for both C::iterator and C::const_iterator. The // reason is that C++ injects the name of a class as a member of the // class itself (e.g. you can refer to class iterator as either // 'iterator' or 'iterator::iterator'). If we look for C::iterator // only, for example, we would mistakenly think that a class named // iterator is an STL container. // // Also note that the simpler approach of overloading // IsContainerTest(typename C::const_iterator*) and // IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++. typedef int IsContainer; template IsContainer IsContainerTest(int /* dummy */, typename C::iterator* /* it */ = NULL, typename C::const_iterator* /* const_it */ = NULL) { return 0; } typedef char IsNotContainer; template IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; } // EnableIf::type is void when 'Cond' is true, and // undefined when 'Cond' is false. To use SFINAE to make a function // overload only apply when a particular expression is true, add // "typename EnableIf::type* = 0" as the last parameter. template struct EnableIf; template<> struct EnableIf { typedef void type; }; // NOLINT // Utilities for native arrays. // ArrayEq() compares two k-dimensional native arrays using the // elements' operator==, where k can be any integer >= 0. When k is // 0, ArrayEq() degenerates into comparing a single pair of values. template bool ArrayEq(const T* lhs, size_t size, const U* rhs); // This generic version is used when k is 0. template inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } // This overload is used when k >= 1. template inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { return internal::ArrayEq(lhs, N, rhs); } // This helper reduces code bloat. If we instead put its logic inside // the previous ArrayEq() function, arrays with different sizes would // lead to different copies of the template code. template bool ArrayEq(const T* lhs, size_t size, const U* rhs) { for (size_t i = 0; i != size; i++) { if (!internal::ArrayEq(lhs[i], rhs[i])) return false; } return true; } // Finds the first element in the iterator range [begin, end) that // equals elem. Element may be a native array type itself. template Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { for (Iter it = begin; it != end; ++it) { if (internal::ArrayEq(*it, elem)) return it; } return end; } // CopyArray() copies a k-dimensional native array using the elements' // operator=, where k can be any integer >= 0. When k is 0, // CopyArray() degenerates into copying a single value. template void CopyArray(const T* from, size_t size, U* to); // This generic version is used when k is 0. template inline void CopyArray(const T& from, U* to) { *to = from; } // This overload is used when k >= 1. template inline void CopyArray(const T(&from)[N], U(*to)[N]) { internal::CopyArray(from, N, *to); } // This helper reduces code bloat. If we instead put its logic inside // the previous CopyArray() function, arrays with different sizes // would lead to different copies of the template code. template void CopyArray(const T* from, size_t size, U* to) { for (size_t i = 0; i != size; i++) { internal::CopyArray(from[i], to + i); } } // The relation between an NativeArray object (see below) and the // native array it represents. enum RelationToSource { kReference, // The NativeArray references the native array. kCopy // The NativeArray makes a copy of the native array and // owns the copy. }; // Adapts a native array to a read-only STL-style container. Instead // of the complete STL container concept, this adaptor only implements // members useful for Google Mock's container matchers. New members // should be added as needed. To simplify the implementation, we only // support Element being a raw type (i.e. having no top-level const or // reference modifier). It's the client's responsibility to satisfy // this requirement. Element can be an array type itself (hence // multi-dimensional arrays are supported). template class NativeArray { public: // STL-style container typedefs. typedef Element value_type; typedef Element* iterator; typedef const Element* const_iterator; // Constructs from a native array. NativeArray(const Element* array, size_t count, RelationToSource relation) { Init(array, count, relation); } // Copy constructor. NativeArray(const NativeArray& rhs) { Init(rhs.array_, rhs.size_, rhs.relation_to_source_); } ~NativeArray() { // Ensures that the user doesn't instantiate NativeArray with a // const or reference type. static_cast(StaticAssertTypeEqHelper()); if (relation_to_source_ == kCopy) delete[] array_; } // STL-style container methods. size_t size() const { return size_; } const_iterator begin() const { return array_; } const_iterator end() const { return array_ + size_; } bool operator==(const NativeArray& rhs) const { return size() == rhs.size() && ArrayEq(begin(), size(), rhs.begin()); } private: // Initializes this object; makes a copy of the input array if // 'relation' is kCopy. void Init(const Element* array, size_t a_size, RelationToSource relation) { if (relation == kReference) { array_ = array; } else { Element* const copy = new Element[a_size]; CopyArray(array, a_size, copy); array_ = copy; } size_ = a_size; relation_to_source_ = relation; } const Element* array_; size_t size_; RelationToSource relation_to_source_; GTEST_DISALLOW_ASSIGN_(NativeArray); }; } // namespace internal } // namespace testing #define GTEST_MESSAGE_AT_(file, line, message, result_type) \ ::testing::internal::AssertHelper(result_type, file, line, message) \ = ::testing::Message() #define GTEST_MESSAGE_(message, result_type) \ GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) #define GTEST_FATAL_FAILURE_(message) \ return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) #define GTEST_NONFATAL_FAILURE_(message) \ GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure) #define GTEST_SUCCESS_(message) \ GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) // Suppresses MSVC warnings 4072 (unreachable code) for the code following // statement if it returns or throws (or doesn't return or throw in some // situations). #define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ if (::testing::internal::AlwaysTrue()) { statement; } #define GTEST_TEST_THROW_(statement, expected_exception, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::ConstCharPtr gtest_msg = "") { \ bool gtest_caught_expected = false; \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ catch (expected_exception const&) { \ gtest_caught_expected = true; \ } \ catch (...) { \ gtest_msg.value = \ "Expected: " #statement " throws an exception of type " \ #expected_exception ".\n Actual: it throws a different type."; \ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ } \ if (!gtest_caught_expected) { \ gtest_msg.value = \ "Expected: " #statement " throws an exception of type " \ #expected_exception ".\n Actual: it throws nothing."; \ goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ fail(gtest_msg.value) #define GTEST_TEST_NO_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ catch (...) { \ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ fail("Expected: " #statement " doesn't throw an exception.\n" \ " Actual: it throws.") #define GTEST_TEST_ANY_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \ bool gtest_caught_any = false; \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ catch (...) { \ gtest_caught_any = true; \ } \ if (!gtest_caught_any) { \ goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ fail("Expected: " #statement " throws an exception.\n" \ " Actual: it doesn't.") // Implements Boolean test assertions such as EXPECT_TRUE. expression can be // either a boolean expression or an AssertionResult. text is a textual // represenation of expression as it was passed into the EXPECT_TRUE. #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const ::testing::AssertionResult gtest_ar_ = \ ::testing::AssertionResult(expression)) \ ; \ else \ fail(::testing::internal::GetBoolAssertionFailureMessage(\ gtest_ar_, text, #actual, #expected).c_str()) #define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \ ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \ goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \ fail("Expected: " #statement " doesn't generate new fatal " \ "failures in the current thread.\n" \ " Actual: it does.") // Expands to the name of the class that implements the given test. #define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ test_case_name##_##test_name##_Test // Helper macro for defining tests. #define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ public:\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ private:\ virtual void TestBody();\ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\ GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\ };\ \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\ ::test_info_ =\ ::testing::internal::MakeAndRegisterTestInfo(\ #test_case_name, #test_name, NULL, NULL, \ (parent_id), \ parent_class::SetUpTestCase, \ parent_class::TearDownTestCase, \ new ::testing::internal::TestFactoryImpl<\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // // The Google C++ Testing Framework (Google Test) // // This header file defines the public API for death tests. It is // #included by gtest.h so a user doesn't need to include this // directly. #ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee) // // The Google C++ Testing Framework (Google Test) // // This header file defines internal utilities needed for implementing // death tests. They are subject to change without notice. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ #include namespace testing { namespace internal { GTEST_DECLARE_string_(internal_run_death_test); // Names of the flags (needed for parsing Google Test flags). const char kDeathTestStyleFlag[] = "death_test_style"; const char kDeathTestUseFork[] = "death_test_use_fork"; const char kInternalRunDeathTestFlag[] = "internal_run_death_test"; #if GTEST_HAS_DEATH_TEST // DeathTest is a class that hides much of the complexity of the // GTEST_DEATH_TEST_ macro. It is abstract; its static Create method // returns a concrete class that depends on the prevailing death test // style, as defined by the --gtest_death_test_style and/or // --gtest_internal_run_death_test flags. // In describing the results of death tests, these terms are used with // the corresponding definitions: // // exit status: The integer exit information in the format specified // by wait(2) // exit code: The integer code passed to exit(3), _exit(2), or // returned from main() class GTEST_API_ DeathTest { public: // Create returns false if there was an error determining the // appropriate action to take for the current death test; for example, // if the gtest_death_test_style flag is set to an invalid value. // The LastMessage method will return a more detailed message in that // case. Otherwise, the DeathTest pointer pointed to by the "test" // argument is set. If the death test should be skipped, the pointer // is set to NULL; otherwise, it is set to the address of a new concrete // DeathTest object that controls the execution of the current test. static bool Create(const char* statement, const RE* regex, const char* file, int line, DeathTest** test); DeathTest(); virtual ~DeathTest() { } // A helper class that aborts a death test when it's deleted. class ReturnSentinel { public: explicit ReturnSentinel(DeathTest* test) : test_(test) { } ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); } private: DeathTest* const test_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel); } GTEST_ATTRIBUTE_UNUSED_; // An enumeration of possible roles that may be taken when a death // test is encountered. EXECUTE means that the death test logic should // be executed immediately. OVERSEE means that the program should prepare // the appropriate environment for a child process to execute the death // test, then wait for it to complete. enum TestRole { OVERSEE_TEST, EXECUTE_TEST }; // An enumeration of the three reasons that a test might be aborted. enum AbortReason { TEST_ENCOUNTERED_RETURN_STATEMENT, TEST_THREW_EXCEPTION, TEST_DID_NOT_DIE }; // Assumes one of the above roles. virtual TestRole AssumeRole() = 0; // Waits for the death test to finish and returns its status. virtual int Wait() = 0; // Returns true if the death test passed; that is, the test process // exited during the test, its exit status matches a user-supplied // predicate, and its stderr output matches a user-supplied regular // expression. // The user-supplied predicate may be a macro expression rather // than a function pointer or functor, or else Wait and Passed could // be combined. virtual bool Passed(bool exit_status_ok) = 0; // Signals that the death test did not die as expected. virtual void Abort(AbortReason reason) = 0; // Returns a human-readable outcome message regarding the outcome of // the last death test. static const char* LastMessage(); static void set_last_death_test_message(const std::string& message); private: // A string containing a description of the outcome of the last death test. static std::string last_death_test_message_; GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest); }; // Factory interface for death tests. May be mocked out for testing. class DeathTestFactory { public: virtual ~DeathTestFactory() { } virtual bool Create(const char* statement, const RE* regex, const char* file, int line, DeathTest** test) = 0; }; // A concrete DeathTestFactory implementation for normal use. class DefaultDeathTestFactory : public DeathTestFactory { public: virtual bool Create(const char* statement, const RE* regex, const char* file, int line, DeathTest** test); }; // Returns true if exit_status describes a process that was terminated // by a signal, or exited normally with a nonzero exit code. GTEST_API_ bool ExitedUnsuccessfully(int exit_status); // Traps C++ exceptions escaping statement and reports them as test // failures. Note that trapping SEH exceptions is not implemented here. # if GTEST_HAS_EXCEPTIONS # define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } catch (const ::std::exception& gtest_exception) { \ fprintf(\ stderr, \ "\n%s: Caught std::exception-derived exception escaping the " \ "death test statement. Exception message: %s\n", \ ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \ gtest_exception.what()); \ fflush(stderr); \ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ } catch (...) { \ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \ } # else # define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) # endif // This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*, // ASSERT_EXIT*, and EXPECT_EXIT*. # define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \ const ::testing::internal::RE& gtest_regex = (regex); \ ::testing::internal::DeathTest* gtest_dt; \ if (!::testing::internal::DeathTest::Create(#statement, >est_regex, \ __FILE__, __LINE__, >est_dt)) { \ goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ } \ if (gtest_dt != NULL) { \ ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \ gtest_dt_ptr(gtest_dt); \ switch (gtest_dt->AssumeRole()) { \ case ::testing::internal::DeathTest::OVERSEE_TEST: \ if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \ goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \ } \ break; \ case ::testing::internal::DeathTest::EXECUTE_TEST: { \ ::testing::internal::DeathTest::ReturnSentinel \ gtest_sentinel(gtest_dt); \ GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \ gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \ break; \ } \ default: \ break; \ } \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \ fail(::testing::internal::DeathTest::LastMessage()) // The symbol "fail" here expands to something into which a message // can be streamed. // This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in // NDEBUG mode. In this case we need the statements to be executed, the regex is // ignored, and the macro must accept a streamed message even though the message // is never printed. # define GTEST_EXECUTE_STATEMENT_(statement, regex) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } else \ ::testing::Message() // A class representing the parsed contents of the // --gtest_internal_run_death_test flag, as it existed when // RUN_ALL_TESTS was called. class InternalRunDeathTestFlag { public: InternalRunDeathTestFlag(const std::string& a_file, int a_line, int an_index, int a_write_fd) : file_(a_file), line_(a_line), index_(an_index), write_fd_(a_write_fd) {} ~InternalRunDeathTestFlag() { if (write_fd_ >= 0) posix::Close(write_fd_); } const std::string& file() const { return file_; } int line() const { return line_; } int index() const { return index_; } int write_fd() const { return write_fd_; } private: std::string file_; int line_; int index_; int write_fd_; GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag); }; // Returns a newly created InternalRunDeathTestFlag object with fields // initialized from the GTEST_FLAG(internal_run_death_test) flag if // the flag is specified; otherwise returns NULL. InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); #else // GTEST_HAS_DEATH_TEST // This macro is used for implementing macros such as // EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where // death tests are not supported. Those macros must compile on such systems // iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on // systems that support death tests. This allows one to write such a macro // on a system that does not support death tests and be sure that it will // compile on a death-test supporting system. // // Parameters: // statement - A statement that a macro such as EXPECT_DEATH would test // for program termination. This macro has to make sure this // statement is compiled but not executed, to ensure that // EXPECT_DEATH_IF_SUPPORTED compiles with a certain // parameter iff EXPECT_DEATH compiles with it. // regex - A regex that a macro such as EXPECT_DEATH would use to test // the output of statement. This parameter has to be // compiled but not evaluated by this macro, to ensure that // this macro only accepts expressions that a macro such as // EXPECT_DEATH would accept. // terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED // and a return statement for ASSERT_DEATH_IF_SUPPORTED. // This ensures that ASSERT_DEATH_IF_SUPPORTED will not // compile inside functions where ASSERT_DEATH doesn't // compile. // // The branch that has an always false condition is used to ensure that // statement and regex are compiled (and thus syntactically correct) but // never executed. The unreachable code macro protects the terminator // statement from generating an 'unreachable code' warning in case // statement unconditionally returns or throws. The Message constructor at // the end allows the syntax of streaming additional messages into the // macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH. # define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (::testing::internal::AlwaysTrue()) { \ GTEST_LOG_(WARNING) \ << "Death tests are not supported on this platform.\n" \ << "Statement '" #statement "' cannot be verified."; \ } else if (::testing::internal::AlwaysFalse()) { \ ::testing::internal::RE::PartialMatch(".*", (regex)); \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ terminator; \ } else \ ::testing::Message() #endif // GTEST_HAS_DEATH_TEST } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ namespace testing { // This flag controls the style of death tests. Valid values are "threadsafe", // meaning that the death test child process will re-execute the test binary // from the start, running only a single death test, or "fast", // meaning that the child process will execute the test logic immediately // after forking. GTEST_DECLARE_string_(death_test_style); #if GTEST_HAS_DEATH_TEST namespace internal { // Returns a Boolean value indicating whether the caller is currently // executing in the context of the death test child process. Tools such as // Valgrind heap checkers may need this to modify their behavior in death // tests. IMPORTANT: This is an internal utility. Using it may break the // implementation of death tests. User code MUST NOT use it. GTEST_API_ bool InDeathTestChild(); } // namespace internal // The following macros are useful for writing death tests. // Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is // executed: // // 1. It generates a warning if there is more than one active // thread. This is because it's safe to fork() or clone() only // when there is a single thread. // // 2. The parent process clone()s a sub-process and runs the death // test in it; the sub-process exits with code 0 at the end of the // death test, if it hasn't exited already. // // 3. The parent process waits for the sub-process to terminate. // // 4. The parent process checks the exit code and error message of // the sub-process. // // Examples: // // ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number"); // for (int i = 0; i < 5; i++) { // EXPECT_DEATH(server.ProcessRequest(i), // "Invalid request .* in ProcessRequest()") // << "Failed to die on request " << i; // } // // ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting"); // // bool KilledBySIGHUP(int exit_code) { // return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP; // } // // ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); // // On the regular expressions used in death tests: // // On POSIX-compliant systems (*nix), we use the library, // which uses the POSIX extended regex syntax. // // On other platforms (e.g. Windows), we only support a simple regex // syntax implemented as part of Google Test. This limited // implementation should be enough most of the time when writing // death tests; though it lacks many features you can find in PCRE // or POSIX extended regex syntax. For example, we don't support // union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and // repetition count ("x{5,7}"), among others. // // Below is the syntax that we do support. We chose it to be a // subset of both PCRE and POSIX extended regex, so it's easy to // learn wherever you come from. In the following: 'A' denotes a // literal character, period (.), or a single \\ escape sequence; // 'x' and 'y' denote regular expressions; 'm' and 'n' are for // natural numbers. // // c matches any literal character c // \\d matches any decimal digit // \\D matches any character that's not a decimal digit // \\f matches \f // \\n matches \n // \\r matches \r // \\s matches any ASCII whitespace, including \n // \\S matches any character that's not a whitespace // \\t matches \t // \\v matches \v // \\w matches any letter, _, or decimal digit // \\W matches any character that \\w doesn't match // \\c matches any literal character c, which must be a punctuation // . matches any single character except \n // A? matches 0 or 1 occurrences of A // A* matches 0 or many occurrences of A // A+ matches 1 or many occurrences of A // ^ matches the beginning of a string (not that of each line) // $ matches the end of a string (not that of each line) // xy matches x followed by y // // If you accidentally use PCRE or POSIX extended regex features // not implemented by us, you will get a run-time failure. In that // case, please try to rewrite your regular expression within the // above syntax. // // This implementation is *not* meant to be as highly tuned or robust // as a compiled regex library, but should perform well enough for a // death test, which already incurs significant overhead by launching // a child process. // // Known caveats: // // A "threadsafe" style death test obtains the path to the test // program from argv[0] and re-executes it in the sub-process. For // simplicity, the current implementation doesn't search the PATH // when launching the sub-process. This means that the user must // invoke the test program via a path that contains at least one // path separator (e.g. path/to/foo_test and // /absolute/path/to/bar_test are fine, but foo_test is not). This // is rarely a problem as people usually don't put the test binary // directory in PATH. // // TODO(wan@google.com): make thread-safe death tests search the PATH. // Asserts that a given statement causes the program to exit, with an // integer exit status that satisfies predicate, and emitting error output // that matches regex. # define ASSERT_EXIT(statement, predicate, regex) \ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) // Like ASSERT_EXIT, but continues on to successive tests in the // test case, if any: # define EXPECT_EXIT(statement, predicate, regex) \ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) // Asserts that a given statement causes the program to exit, either by // explicitly exiting with a nonzero exit code or being killed by a // signal, and emitting error output that matches regex. # define ASSERT_DEATH(statement, regex) \ ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) // Like ASSERT_DEATH, but continues on to successive tests in the // test case, if any: # define EXPECT_DEATH(statement, regex) \ EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) // Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: // Tests that an exit code describes a normal exit with a given exit code. class GTEST_API_ ExitedWithCode { public: explicit ExitedWithCode(int exit_code); bool operator()(int exit_status) const; private: // No implementation - assignment is unsupported. void operator=(const ExitedWithCode& other); const int exit_code_; }; # if !GTEST_OS_WINDOWS // Tests that an exit code describes an exit due to termination by a // given signal. class GTEST_API_ KilledBySignal { public: explicit KilledBySignal(int signum); bool operator()(int exit_status) const; private: const int signum_; }; # endif // !GTEST_OS_WINDOWS // EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode. // The death testing framework causes this to have interesting semantics, // since the sideeffects of the call are only visible in opt mode, and not // in debug mode. // // In practice, this can be used to test functions that utilize the // LOG(DFATAL) macro using the following style: // // int DieInDebugOr12(int* sideeffect) { // if (sideeffect) { // *sideeffect = 12; // } // LOG(DFATAL) << "death"; // return 12; // } // // TEST(TestCase, TestDieOr12WorksInDgbAndOpt) { // int sideeffect = 0; // // Only asserts in dbg. // EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death"); // // #ifdef NDEBUG // // opt-mode has sideeffect visible. // EXPECT_EQ(12, sideeffect); // #else // // dbg-mode no visible sideeffect. // EXPECT_EQ(0, sideeffect); // #endif // } // // This will assert that DieInDebugReturn12InOpt() crashes in debug // mode, usually due to a DCHECK or LOG(DFATAL), but returns the // appropriate fallback value (12 in this case) in opt mode. If you // need to test that a function has appropriate side-effects in opt // mode, include assertions against the side-effects. A general // pattern for this is: // // EXPECT_DEBUG_DEATH({ // // Side-effects here will have an effect after this statement in // // opt mode, but none in debug mode. // EXPECT_EQ(12, DieInDebugOr12(&sideeffect)); // }, "death"); // # ifdef NDEBUG # define EXPECT_DEBUG_DEATH(statement, regex) \ GTEST_EXECUTE_STATEMENT_(statement, regex) # define ASSERT_DEBUG_DEATH(statement, regex) \ GTEST_EXECUTE_STATEMENT_(statement, regex) # else # define EXPECT_DEBUG_DEATH(statement, regex) \ EXPECT_DEATH(statement, regex) # define ASSERT_DEBUG_DEATH(statement, regex) \ ASSERT_DEATH(statement, regex) # endif // NDEBUG for EXPECT_DEBUG_DEATH #endif // GTEST_HAS_DEATH_TEST // EXPECT_DEATH_IF_SUPPORTED(statement, regex) and // ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if // death tests are supported; otherwise they just issue a warning. This is // useful when you are combining death test assertions with normal test // assertions in one test. #if GTEST_HAS_DEATH_TEST # define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ EXPECT_DEATH(statement, regex) # define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ ASSERT_DEATH(statement, regex) #else # define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \ GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, ) # define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \ GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return) #endif } // namespace testing #endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ // This file was GENERATED by command: // pump.py gtest-param-test.h.pump // DO NOT EDIT BY HAND!!! // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: vladl@google.com (Vlad Losev) // // Macros and functions for implementing parameterized tests // in Google C++ Testing Framework (Google Test) // // This file is generated by a SCRIPT. DO NOT EDIT BY HAND! // #ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ // Value-parameterized tests allow you to test your code with different // parameters without writing multiple copies of the same test. // // Here is how you use value-parameterized tests: #if 0 // To write value-parameterized tests, first you should define a fixture // class. It is usually derived from testing::TestWithParam (see below for // another inheritance scheme that's sometimes useful in more complicated // class hierarchies), where the type of your parameter values. // TestWithParam is itself derived from testing::Test. T can be any // copyable type. If it's a raw pointer, you are responsible for managing the // lifespan of the pointed values. class FooTest : public ::testing::TestWithParam { // You can implement all the usual class fixture members here. }; // Then, use the TEST_P macro to define as many parameterized tests // for this fixture as you want. The _P suffix is for "parameterized" // or "pattern", whichever you prefer to think. TEST_P(FooTest, DoesBlah) { // Inside a test, access the test parameter with the GetParam() method // of the TestWithParam class: EXPECT_TRUE(foo.Blah(GetParam())); ... } TEST_P(FooTest, HasBlahBlah) { ... } // Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test // case with any set of parameters you want. Google Test defines a number // of functions for generating test parameters. They return what we call // (surprise!) parameter generators. Here is a summary of them, which // are all in the testing namespace: // // // Range(begin, end [, step]) - Yields values {begin, begin+step, // begin+step+step, ...}. The values do not // include end. step defaults to 1. // Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}. // ValuesIn(container) - Yields values from a C-style array, an STL // ValuesIn(begin,end) container, or an iterator range [begin, end). // Bool() - Yields sequence {false, true}. // Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product // for the math savvy) of the values generated // by the N generators. // // For more details, see comments at the definitions of these functions below // in this file. // // The following statement will instantiate tests from the FooTest test case // each with parameter values "meeny", "miny", and "moe". INSTANTIATE_TEST_CASE_P(InstantiationName, FooTest, Values("meeny", "miny", "moe")); // To distinguish different instances of the pattern, (yes, you // can instantiate it more then once) the first argument to the // INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the // actual test case name. Remember to pick unique prefixes for different // instantiations. The tests from the instantiation above will have // these names: // // * InstantiationName/FooTest.DoesBlah/0 for "meeny" // * InstantiationName/FooTest.DoesBlah/1 for "miny" // * InstantiationName/FooTest.DoesBlah/2 for "moe" // * InstantiationName/FooTest.HasBlahBlah/0 for "meeny" // * InstantiationName/FooTest.HasBlahBlah/1 for "miny" // * InstantiationName/FooTest.HasBlahBlah/2 for "moe" // // You can use these names in --gtest_filter. // // This statement will instantiate all tests from FooTest again, each // with parameter values "cat" and "dog": const char* pets[] = {"cat", "dog"}; INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets)); // The tests from the instantiation above will have these names: // // * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat" // * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog" // * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat" // * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog" // // Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests // in the given test case, whether their definitions come before or // AFTER the INSTANTIATE_TEST_CASE_P statement. // // Please also note that generator expressions (including parameters to the // generators) are evaluated in InitGoogleTest(), after main() has started. // This allows the user on one hand, to adjust generator parameters in order // to dynamically determine a set of tests to run and on the other hand, // give the user a chance to inspect the generated tests with Google Test // reflection API before RUN_ALL_TESTS() is executed. // // You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc // for more examples. // // In the future, we plan to publish the API for defining new parameter // generators. But for now this interface remains part of the internal // implementation and is subject to change. // // // A parameterized test fixture must be derived from testing::Test and from // testing::WithParamInterface, where T is the type of the parameter // values. Inheriting from TestWithParam satisfies that requirement because // TestWithParam inherits from both Test and WithParamInterface. In more // complicated hierarchies, however, it is occasionally useful to inherit // separately from Test and WithParamInterface. For example: class BaseTest : public ::testing::Test { // You can inherit all the usual members for a non-parameterized test // fixture here. }; class DerivedTest : public BaseTest, public ::testing::WithParamInterface { // The usual test fixture members go here too. }; TEST_F(BaseTest, HasFoo) { // This is an ordinary non-parameterized test. } TEST_P(DerivedTest, DoesBlah) { // GetParam works just the same here as if you inherit from TestWithParam. EXPECT_TRUE(foo.Blah(GetParam())); } #endif // 0 #if !GTEST_OS_SYMBIAN # include #endif // scripts/fuse_gtest.py depends on gtest's own header being #included // *unconditionally*. Therefore these #includes cannot be moved // inside #if GTEST_HAS_PARAM_TEST. // Copyright 2008 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: vladl@google.com (Vlad Losev) // Type and function utilities for implementing parameterized tests. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #include #include #include // scripts/fuse_gtest.py depends on gtest's own header being #included // *unconditionally*. Therefore these #includes cannot be moved // inside #if GTEST_HAS_PARAM_TEST. // Copyright 2003 Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Dan Egnor (egnor@google.com) // // A "smart" pointer type with reference tracking. Every pointer to a // particular object is kept on a circular linked list. When the last pointer // to an object is destroyed or reassigned, the object is deleted. // // Used properly, this deletes the object when the last reference goes away. // There are several caveats: // - Like all reference counting schemes, cycles lead to leaks. // - Each smart pointer is actually two pointers (8 bytes instead of 4). // - Every time a pointer is assigned, the entire list of pointers to that // object is traversed. This class is therefore NOT SUITABLE when there // will often be more than two or three pointers to a particular object. // - References are only tracked as long as linked_ptr<> objects are copied. // If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS // will happen (double deletion). // // A good use of this class is storing object references in STL containers. // You can safely put linked_ptr<> in a vector<>. // Other uses may not be as good. // // Note: If you use an incomplete type with linked_ptr<>, the class // *containing* linked_ptr<> must have a constructor and destructor (even // if they do nothing!). // // Bill Gibbons suggested we use something like this. // // Thread Safety: // Unlike other linked_ptr implementations, in this implementation // a linked_ptr object is thread-safe in the sense that: // - it's safe to copy linked_ptr objects concurrently, // - it's safe to copy *from* a linked_ptr and read its underlying // raw pointer (e.g. via get()) concurrently, and // - it's safe to write to two linked_ptrs that point to the same // shared object concurrently. // TODO(wan@google.com): rename this to safe_linked_ptr to avoid // confusion with normal linked_ptr. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ #include #include namespace testing { namespace internal { // Protects copying of all linked_ptr objects. GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex); // This is used internally by all instances of linked_ptr<>. It needs to be // a non-template class because different types of linked_ptr<> can refer to // the same object (linked_ptr(obj) vs linked_ptr(obj)). // So, it needs to be possible for different types of linked_ptr to participate // in the same circular linked list, so we need a single class type here. // // DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr. class linked_ptr_internal { public: // Create a new circle that includes only this instance. void join_new() { next_ = this; } // Many linked_ptr operations may change p.link_ for some linked_ptr // variable p in the same circle as this object. Therefore we need // to prevent two such operations from occurring concurrently. // // Note that different types of linked_ptr objects can coexist in a // circle (e.g. linked_ptr, linked_ptr, and // linked_ptr). Therefore we must use a single mutex to // protect all linked_ptr objects. This can create serious // contention in production code, but is acceptable in a testing // framework. // Join an existing circle. void join(linked_ptr_internal const* ptr) GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { MutexLock lock(&g_linked_ptr_mutex); linked_ptr_internal const* p = ptr; while (p->next_ != ptr) p = p->next_; p->next_ = this; next_ = ptr; } // Leave whatever circle we're part of. Returns true if we were the // last member of the circle. Once this is done, you can join() another. bool depart() GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) { MutexLock lock(&g_linked_ptr_mutex); if (next_ == this) return true; linked_ptr_internal const* p = next_; while (p->next_ != this) p = p->next_; p->next_ = next_; return false; } private: mutable linked_ptr_internal const* next_; }; template class linked_ptr { public: typedef T element_type; // Take over ownership of a raw pointer. This should happen as soon as // possible after the object is created. explicit linked_ptr(T* ptr = NULL) { capture(ptr); } ~linked_ptr() { depart(); } // Copy an existing linked_ptr<>, adding ourselves to the list of references. template linked_ptr(linked_ptr const& ptr) { copy(&ptr); } linked_ptr(linked_ptr const& ptr) { // NOLINT assert(&ptr != this); copy(&ptr); } // Assignment releases the old value and acquires the new. template linked_ptr& operator=(linked_ptr const& ptr) { depart(); copy(&ptr); return *this; } linked_ptr& operator=(linked_ptr const& ptr) { if (&ptr != this) { depart(); copy(&ptr); } return *this; } // Smart pointer members. void reset(T* ptr = NULL) { depart(); capture(ptr); } T* get() const { return value_; } T* operator->() const { return value_; } T& operator*() const { return *value_; } bool operator==(T* p) const { return value_ == p; } bool operator!=(T* p) const { return value_ != p; } template bool operator==(linked_ptr const& ptr) const { return value_ == ptr.get(); } template bool operator!=(linked_ptr const& ptr) const { return value_ != ptr.get(); } private: template friend class linked_ptr; T* value_; linked_ptr_internal link_; void depart() { if (link_.depart()) delete value_; } void capture(T* ptr) { value_ = ptr; link_.join_new(); } template void copy(linked_ptr const* ptr) { value_ = ptr->get(); if (value_) link_.join(&ptr->link_); else link_.join_new(); } }; template inline bool operator==(T* ptr, const linked_ptr& x) { return ptr == x.get(); } template inline bool operator!=(T* ptr, const linked_ptr& x) { return ptr != x.get(); } // A function to convert T* into linked_ptr // Doing e.g. make_linked_ptr(new FooBarBaz(arg)) is a shorter notation // for linked_ptr >(new FooBarBaz(arg)) template linked_ptr make_linked_ptr(T* ptr) { return linked_ptr(ptr); } } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_ // Copyright 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // Google Test - The Google C++ Testing Framework // // This file implements a universal value printer that can print a // value of any type T: // // void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); // // A user can teach this function how to print a class type T by // defining either operator<<() or PrintTo() in the namespace that // defines T. More specifically, the FIRST defined function in the // following list will be used (assuming T is defined in namespace // foo): // // 1. foo::PrintTo(const T&, ostream*) // 2. operator<<(ostream&, const T&) defined in either foo or the // global namespace. // // If none of the above is defined, it will print the debug string of // the value if it is a protocol buffer, or print the raw bytes in the // value otherwise. // // To aid debugging: when T is a reference type, the address of the // value is also printed; when T is a (const) char pointer, both the // pointer value and the NUL-terminated string it points to are // printed. // // We also provide some convenient wrappers: // // // Prints a value to a string. For a (const or not) char // // pointer, the NUL-terminated string (but not the pointer) is // // printed. // std::string ::testing::PrintToString(const T& value); // // // Prints a value tersely: for a reference type, the referenced // // value (but not the address) is printed; for a (const or not) char // // pointer, the NUL-terminated string (but not the pointer) is // // printed. // void ::testing::internal::UniversalTersePrint(const T& value, ostream*); // // // Prints value using the type inferred by the compiler. The difference // // from UniversalTersePrint() is that this function prints both the // // pointer and the NUL-terminated string for a (const or not) char pointer. // void ::testing::internal::UniversalPrint(const T& value, ostream*); // // // Prints the fields of a tuple tersely to a string vector, one // // element for each field. Tuple support must be enabled in // // gtest-port.h. // std::vector UniversalTersePrintTupleFieldsToStrings( // const Tuple& value); // // Known limitation: // // The print primitives print the elements of an STL-style container // using the compiler-inferred type of *iter where iter is a // const_iterator of the container. When const_iterator is an input // iterator but not a forward iterator, this inferred type may not // match value_type, and the print output may be incorrect. In // practice, this is rarely a problem as for most containers // const_iterator is a forward iterator. We'll fix this if there's an // actual need for it. Note that this fix cannot rely on value_type // being defined as many user-defined container types don't have // value_type. #ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #include // NOLINT #include #include #include #include namespace testing { // Definitions in the 'internal' and 'internal2' name spaces are // subject to change without notice. DO NOT USE THEM IN USER CODE! namespace internal2 { // Prints the given number of bytes in the given object to the given // ostream. GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, ::std::ostream* os); // For selecting which printer to use when a given type has neither << // nor PrintTo(). enum TypeKind { kProtobuf, // a protobuf type kConvertibleToInteger, // a type implicitly convertible to BiggestInt // (e.g. a named or unnamed enum type) kOtherType // anything else }; // TypeWithoutFormatter::PrintValue(value, os) is called // by the universal printer to print a value of type T when neither // operator<< nor PrintTo() is defined for T, where kTypeKind is the // "kind" of T as defined by enum TypeKind. template class TypeWithoutFormatter { public: // This default version is called when kTypeKind is kOtherType. static void PrintValue(const T& value, ::std::ostream* os) { PrintBytesInObjectTo(reinterpret_cast(&value), sizeof(value), os); } }; // We print a protobuf using its ShortDebugString() when the string // doesn't exceed this many characters; otherwise we print it using // DebugString() for better readability. const size_t kProtobufOneLinerMaxLength = 50; template class TypeWithoutFormatter { public: static void PrintValue(const T& value, ::std::ostream* os) { const ::testing::internal::string short_str = value.ShortDebugString(); const ::testing::internal::string pretty_str = short_str.length() <= kProtobufOneLinerMaxLength ? short_str : ("\n" + value.DebugString()); *os << ("<" + pretty_str + ">"); } }; template class TypeWithoutFormatter { public: // Since T has no << operator or PrintTo() but can be implicitly // converted to BiggestInt, we print it as a BiggestInt. // // Most likely T is an enum type (either named or unnamed), in which // case printing it as an integer is the desired behavior. In case // T is not an enum, printing it as an integer is the best we can do // given that it has no user-defined printer. static void PrintValue(const T& value, ::std::ostream* os) { const internal::BiggestInt kBigInt = value; *os << kBigInt; } }; // Prints the given value to the given ostream. If the value is a // protocol message, its debug string is printed; if it's an enum or // of a type implicitly convertible to BiggestInt, it's printed as an // integer; otherwise the bytes in the value are printed. This is // what UniversalPrinter::Print() does when it knows nothing about // type T and T has neither << operator nor PrintTo(). // // A user can override this behavior for a class type Foo by defining // a << operator in the namespace where Foo is defined. // // We put this operator in namespace 'internal2' instead of 'internal' // to simplify the implementation, as much code in 'internal' needs to // use << in STL, which would conflict with our own << were it defined // in 'internal'. // // Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If // we define it to take an std::ostream instead, we'll get an // "ambiguous overloads" compiler error when trying to print a type // Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether // operator<<(std::ostream&, const T&) or // operator<<(std::basic_stream, const Foo&) is more // specific. template ::std::basic_ostream& operator<<( ::std::basic_ostream& os, const T& x) { TypeWithoutFormatter::value ? kProtobuf : internal::ImplicitlyConvertible::value ? kConvertibleToInteger : kOtherType)>::PrintValue(x, &os); return os; } } // namespace internal2 } // namespace testing // This namespace MUST NOT BE NESTED IN ::testing, or the name look-up // magic needed for implementing UniversalPrinter won't work. namespace testing_internal { // Used to print a value that is not an STL-style container when the // user doesn't define PrintTo() for it. template void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { // With the following statement, during unqualified name lookup, // testing::internal2::operator<< appears as if it was declared in // the nearest enclosing namespace that contains both // ::testing_internal and ::testing::internal2, i.e. the global // namespace. For more details, refer to the C++ Standard section // 7.3.4-1 [namespace.udir]. This allows us to fall back onto // testing::internal2::operator<< in case T doesn't come with a << // operator. // // We cannot write 'using ::testing::internal2::operator<<;', which // gcc 3.3 fails to compile due to a compiler bug. using namespace ::testing::internal2; // NOLINT // Assuming T is defined in namespace foo, in the next statement, // the compiler will consider all of: // // 1. foo::operator<< (thanks to Koenig look-up), // 2. ::operator<< (as the current namespace is enclosed in ::), // 3. testing::internal2::operator<< (thanks to the using statement above). // // The operator<< whose type matches T best will be picked. // // We deliberately allow #2 to be a candidate, as sometimes it's // impossible to define #1 (e.g. when foo is ::std, defining // anything in it is undefined behavior unless you are a compiler // vendor.). *os << value; } } // namespace testing_internal namespace testing { namespace internal { // UniversalPrinter::Print(value, ostream_ptr) prints the given // value to the given ostream. The caller must ensure that // 'ostream_ptr' is not NULL, or the behavior is undefined. // // We define UniversalPrinter as a class template (as opposed to a // function template), as we need to partially specialize it for // reference types, which cannot be done with function templates. template class UniversalPrinter; template void UniversalPrint(const T& value, ::std::ostream* os); // Used to print an STL-style container when the user doesn't define // a PrintTo() for it. template void DefaultPrintTo(IsContainer /* dummy */, false_type /* is not a pointer */, const C& container, ::std::ostream* os) { const size_t kMaxCount = 32; // The maximum number of elements to print. *os << '{'; size_t count = 0; for (typename C::const_iterator it = container.begin(); it != container.end(); ++it, ++count) { if (count > 0) { *os << ','; if (count == kMaxCount) { // Enough has been printed. *os << " ..."; break; } } *os << ' '; // We cannot call PrintTo(*it, os) here as PrintTo() doesn't // handle *it being a native array. internal::UniversalPrint(*it, os); } if (count > 0) { *os << ' '; } *os << '}'; } // Used to print a pointer that is neither a char pointer nor a member // pointer, when the user doesn't define PrintTo() for it. (A member // variable pointer or member function pointer doesn't really point to // a location in the address space. Their representation is // implementation-defined. Therefore they will be printed as raw // bytes.) template void DefaultPrintTo(IsNotContainer /* dummy */, true_type /* is a pointer */, T* p, ::std::ostream* os) { if (p == NULL) { *os << "NULL"; } else { // C++ doesn't allow casting from a function pointer to any object // pointer. // // IsTrue() silences warnings: "Condition is always true", // "unreachable code". if (IsTrue(ImplicitlyConvertible::value)) { // T is not a function type. We just call << to print p, // relying on ADL to pick up user-defined << for their pointer // types, if any. *os << p; } else { // T is a function type, so '*os << p' doesn't do what we want // (it just prints p as bool). We want to print p as a const // void*. However, we cannot cast it to const void* directly, // even using reinterpret_cast, as earlier versions of gcc // (e.g. 3.4.5) cannot compile the cast when p is a function // pointer. Casting to UInt64 first solves the problem. *os << reinterpret_cast( reinterpret_cast(p)); } } } // Used to print a non-container, non-pointer value when the user // doesn't define PrintTo() for it. template void DefaultPrintTo(IsNotContainer /* dummy */, false_type /* is not a pointer */, const T& value, ::std::ostream* os) { ::testing_internal::DefaultPrintNonContainerTo(value, os); } // Prints the given value using the << operator if it has one; // otherwise prints the bytes in it. This is what // UniversalPrinter::Print() does when PrintTo() is not specialized // or overloaded for type T. // // A user can override this behavior for a class type Foo by defining // an overload of PrintTo() in the namespace where Foo is defined. We // give the user this option as sometimes defining a << operator for // Foo is not desirable (e.g. the coding style may prevent doing it, // or there is already a << operator but it doesn't do what the user // wants). template void PrintTo(const T& value, ::std::ostream* os) { // DefaultPrintTo() is overloaded. The type of its first two // arguments determine which version will be picked. If T is an // STL-style container, the version for container will be called; if // T is a pointer, the pointer version will be called; otherwise the // generic version will be called. // // Note that we check for container types here, prior to we check // for protocol message types in our operator<<. The rationale is: // // For protocol messages, we want to give people a chance to // override Google Mock's format by defining a PrintTo() or // operator<<. For STL containers, other formats can be // incompatible with Google Mock's format for the container // elements; therefore we check for container types here to ensure // that our format is used. // // The second argument of DefaultPrintTo() is needed to bypass a bug // in Symbian's C++ compiler that prevents it from picking the right // overload between: // // PrintTo(const T& x, ...); // PrintTo(T* x, ...); DefaultPrintTo(IsContainerTest(0), is_pointer(), value, os); } // The following list of PrintTo() overloads tells // UniversalPrinter::Print() how to print standard types (built-in // types, strings, plain arrays, and pointers). // Overloads for various char types. GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); inline void PrintTo(char c, ::std::ostream* os) { // When printing a plain char, we always treat it as unsigned. This // way, the output won't be affected by whether the compiler thinks // char is signed or not. PrintTo(static_cast(c), os); } // Overloads for other simple built-in types. inline void PrintTo(bool x, ::std::ostream* os) { *os << (x ? "true" : "false"); } // Overload for wchar_t type. // Prints a wchar_t as a symbol if it is printable or as its internal // code otherwise and also as its decimal code (except for L'\0'). // The L'\0' char is printed as "L'\\0'". The decimal code is printed // as signed integer when wchar_t is implemented by the compiler // as a signed type and is printed as an unsigned integer when wchar_t // is implemented as an unsigned type. GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); // Overloads for C strings. GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); inline void PrintTo(char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } // signed/unsigned char is often used for representing binary data, so // we print pointers to it as void* to be safe. inline void PrintTo(const signed char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } inline void PrintTo(signed char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } inline void PrintTo(const unsigned char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } inline void PrintTo(unsigned char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } // MSVC can be configured to define wchar_t as a typedef of unsigned // short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native // type. When wchar_t is a typedef, defining an overload for const // wchar_t* would cause unsigned short* be printed as a wide string, // possibly causing invalid memory accesses. #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) // Overloads for wide C strings GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); inline void PrintTo(wchar_t* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } #endif // Overload for C arrays. Multi-dimensional arrays are printed // properly. // Prints the given number of elements in an array, without printing // the curly braces. template void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { UniversalPrint(a[0], os); for (size_t i = 1; i != count; i++) { *os << ", "; UniversalPrint(a[i], os); } } // Overloads for ::string and ::std::string. #if GTEST_HAS_GLOBAL_STRING GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os); inline void PrintTo(const ::string& s, ::std::ostream* os) { PrintStringTo(s, os); } #endif // GTEST_HAS_GLOBAL_STRING GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); inline void PrintTo(const ::std::string& s, ::std::ostream* os) { PrintStringTo(s, os); } // Overloads for ::wstring and ::std::wstring. #if GTEST_HAS_GLOBAL_WSTRING GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os); inline void PrintTo(const ::wstring& s, ::std::ostream* os) { PrintWideStringTo(s, os); } #endif // GTEST_HAS_GLOBAL_WSTRING #if GTEST_HAS_STD_WSTRING GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { PrintWideStringTo(s, os); } #endif // GTEST_HAS_STD_WSTRING #if GTEST_HAS_TR1_TUPLE // Overload for ::std::tr1::tuple. Needed for printing function arguments, // which are packed as tuples. // Helper function for printing a tuple. T must be instantiated with // a tuple type. template void PrintTupleTo(const T& t, ::std::ostream* os); // Overloaded PrintTo() for tuples of various arities. We support // tuples of up-to 10 fields. The following implementation works // regardless of whether tr1::tuple is implemented using the // non-standard variadic template feature or not. inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo(const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } template void PrintTo( const ::std::tr1::tuple& t, ::std::ostream* os) { PrintTupleTo(t, os); } #endif // GTEST_HAS_TR1_TUPLE // Overload for std::pair. template void PrintTo(const ::std::pair& value, ::std::ostream* os) { *os << '('; // We cannot use UniversalPrint(value.first, os) here, as T1 may be // a reference type. The same for printing value.second. UniversalPrinter::Print(value.first, os); *os << ", "; UniversalPrinter::Print(value.second, os); *os << ')'; } // Implements printing a non-reference type T by letting the compiler // pick the right overload of PrintTo() for T. template class UniversalPrinter { public: // MSVC warns about adding const to a function type, so we want to // disable the warning. #ifdef _MSC_VER # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4180) // Temporarily disables warning 4180. #endif // _MSC_VER // Note: we deliberately don't call this PrintTo(), as that name // conflicts with ::testing::internal::PrintTo in the body of the // function. static void Print(const T& value, ::std::ostream* os) { // By default, ::testing::internal::PrintTo() is used for printing // the value. // // Thanks to Koenig look-up, if T is a class and has its own // PrintTo() function defined in its namespace, that function will // be visible here. Since it is more specific than the generic ones // in ::testing::internal, it will be picked by the compiler in the // following statement - exactly what we want. PrintTo(value, os); } #ifdef _MSC_VER # pragma warning(pop) // Restores the warning state. #endif // _MSC_VER }; // UniversalPrintArray(begin, len, os) prints an array of 'len' // elements, starting at address 'begin'. template void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { if (len == 0) { *os << "{}"; } else { *os << "{ "; const size_t kThreshold = 18; const size_t kChunkSize = 8; // If the array has more than kThreshold elements, we'll have to // omit some details by printing only the first and the last // kChunkSize elements. // TODO(wan@google.com): let the user control the threshold using a flag. if (len <= kThreshold) { PrintRawArrayTo(begin, len, os); } else { PrintRawArrayTo(begin, kChunkSize, os); *os << ", ..., "; PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os); } *os << " }"; } } // This overload prints a (const) char array compactly. GTEST_API_ void UniversalPrintArray( const char* begin, size_t len, ::std::ostream* os); // This overload prints a (const) wchar_t array compactly. GTEST_API_ void UniversalPrintArray( const wchar_t* begin, size_t len, ::std::ostream* os); // Implements printing an array type T[N]. template class UniversalPrinter { public: // Prints the given array, omitting some elements when there are too // many. static void Print(const T (&a)[N], ::std::ostream* os) { UniversalPrintArray(a, N, os); } }; // Implements printing a reference type T&. template class UniversalPrinter { public: // MSVC warns about adding const to a function type, so we want to // disable the warning. #ifdef _MSC_VER # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4180) // Temporarily disables warning 4180. #endif // _MSC_VER static void Print(const T& value, ::std::ostream* os) { // Prints the address of the value. We use reinterpret_cast here // as static_cast doesn't compile when T is a function type. *os << "@" << reinterpret_cast(&value) << " "; // Then prints the value itself. UniversalPrint(value, os); } #ifdef _MSC_VER # pragma warning(pop) // Restores the warning state. #endif // _MSC_VER }; // Prints a value tersely: for a reference type, the referenced value // (but not the address) is printed; for a (const) char pointer, the // NUL-terminated string (but not the pointer) is printed. template class UniversalTersePrinter { public: static void Print(const T& value, ::std::ostream* os) { UniversalPrint(value, os); } }; template class UniversalTersePrinter { public: static void Print(const T& value, ::std::ostream* os) { UniversalPrint(value, os); } }; template class UniversalTersePrinter { public: static void Print(const T (&value)[N], ::std::ostream* os) { UniversalPrinter::Print(value, os); } }; template <> class UniversalTersePrinter { public: static void Print(const char* str, ::std::ostream* os) { if (str == NULL) { *os << "NULL"; } else { UniversalPrint(string(str), os); } } }; template <> class UniversalTersePrinter { public: static void Print(char* str, ::std::ostream* os) { UniversalTersePrinter::Print(str, os); } }; #if GTEST_HAS_STD_WSTRING template <> class UniversalTersePrinter { public: static void Print(const wchar_t* str, ::std::ostream* os) { if (str == NULL) { *os << "NULL"; } else { UniversalPrint(::std::wstring(str), os); } } }; #endif template <> class UniversalTersePrinter { public: static void Print(wchar_t* str, ::std::ostream* os) { UniversalTersePrinter::Print(str, os); } }; template void UniversalTersePrint(const T& value, ::std::ostream* os) { UniversalTersePrinter::Print(value, os); } // Prints a value using the type inferred by the compiler. The // difference between this and UniversalTersePrint() is that for a // (const) char pointer, this prints both the pointer and the // NUL-terminated string. template void UniversalPrint(const T& value, ::std::ostream* os) { // A workarond for the bug in VC++ 7.1 that prevents us from instantiating // UniversalPrinter with T directly. typedef T T1; UniversalPrinter::Print(value, os); } #if GTEST_HAS_TR1_TUPLE typedef ::std::vector Strings; // This helper template allows PrintTo() for tuples and // UniversalTersePrintTupleFieldsToStrings() to be defined by // induction on the number of tuple fields. The idea is that // TuplePrefixPrinter::PrintPrefixTo(t, os) prints the first N // fields in tuple t, and can be defined in terms of // TuplePrefixPrinter. // The inductive case. template struct TuplePrefixPrinter { // Prints the first N fields of a tuple. template static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { TuplePrefixPrinter::PrintPrefixTo(t, os); *os << ", "; UniversalPrinter::type> ::Print(::std::tr1::get(t), os); } // Tersely prints the first N fields of a tuple to a string vector, // one element for each field. template static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { TuplePrefixPrinter::TersePrintPrefixToStrings(t, strings); ::std::stringstream ss; UniversalTersePrint(::std::tr1::get(t), &ss); strings->push_back(ss.str()); } }; // Base cases. template <> struct TuplePrefixPrinter<0> { template static void PrintPrefixTo(const Tuple&, ::std::ostream*) {} template static void TersePrintPrefixToStrings(const Tuple&, Strings*) {} }; // We have to specialize the entire TuplePrefixPrinter<> class // template here, even though the definition of // TersePrintPrefixToStrings() is the same as the generic version, as // Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't // support specializing a method template of a class template. template <> struct TuplePrefixPrinter<1> { template static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { UniversalPrinter::type>:: Print(::std::tr1::get<0>(t), os); } template static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) { ::std::stringstream ss; UniversalTersePrint(::std::tr1::get<0>(t), &ss); strings->push_back(ss.str()); } }; // Helper function for printing a tuple. T must be instantiated with // a tuple type. template void PrintTupleTo(const T& t, ::std::ostream* os) { *os << "("; TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: PrintPrefixTo(t, os); *os << ")"; } // Prints the fields of a tuple tersely to a string vector, one // element for each field. See the comment before // UniversalTersePrint() for how we define "tersely". template Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { Strings result; TuplePrefixPrinter< ::std::tr1::tuple_size::value>:: TersePrintPrefixToStrings(value, &result); return result; } #endif // GTEST_HAS_TR1_TUPLE } // namespace internal template ::std::string PrintToString(const T& value) { ::std::stringstream ss; internal::UniversalTersePrinter::Print(value, &ss); return ss.str(); } } // namespace testing #endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #if GTEST_HAS_PARAM_TEST namespace testing { namespace internal { // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Outputs a message explaining invalid registration of different // fixture class for the same test case. This may happen when // TEST_P macro is used to define two tests with the same name // but in different namespaces. GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, const char* file, int line); template class ParamGeneratorInterface; template class ParamGenerator; // Interface for iterating over elements provided by an implementation // of ParamGeneratorInterface. template class ParamIteratorInterface { public: virtual ~ParamIteratorInterface() {} // A pointer to the base generator instance. // Used only for the purposes of iterator comparison // to make sure that two iterators belong to the same generator. virtual const ParamGeneratorInterface* BaseGenerator() const = 0; // Advances iterator to point to the next element // provided by the generator. The caller is responsible // for not calling Advance() on an iterator equal to // BaseGenerator()->End(). virtual void Advance() = 0; // Clones the iterator object. Used for implementing copy semantics // of ParamIterator. virtual ParamIteratorInterface* Clone() const = 0; // Dereferences the current iterator and provides (read-only) access // to the pointed value. It is the caller's responsibility not to call // Current() on an iterator equal to BaseGenerator()->End(). // Used for implementing ParamGenerator::operator*(). virtual const T* Current() const = 0; // Determines whether the given iterator and other point to the same // element in the sequence generated by the generator. // Used for implementing ParamGenerator::operator==(). virtual bool Equals(const ParamIteratorInterface& other) const = 0; }; // Class iterating over elements provided by an implementation of // ParamGeneratorInterface. It wraps ParamIteratorInterface // and implements the const forward iterator concept. template class ParamIterator { public: typedef T value_type; typedef const T& reference; typedef ptrdiff_t difference_type; // ParamIterator assumes ownership of the impl_ pointer. ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {} ParamIterator& operator=(const ParamIterator& other) { if (this != &other) impl_.reset(other.impl_->Clone()); return *this; } const T& operator*() const { return *impl_->Current(); } const T* operator->() const { return impl_->Current(); } // Prefix version of operator++. ParamIterator& operator++() { impl_->Advance(); return *this; } // Postfix version of operator++. ParamIterator operator++(int /*unused*/) { ParamIteratorInterface* clone = impl_->Clone(); impl_->Advance(); return ParamIterator(clone); } bool operator==(const ParamIterator& other) const { return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_); } bool operator!=(const ParamIterator& other) const { return !(*this == other); } private: friend class ParamGenerator; explicit ParamIterator(ParamIteratorInterface* impl) : impl_(impl) {} scoped_ptr > impl_; }; // ParamGeneratorInterface is the binary interface to access generators // defined in other translation units. template class ParamGeneratorInterface { public: typedef T ParamType; virtual ~ParamGeneratorInterface() {} // Generator interface definition virtual ParamIteratorInterface* Begin() const = 0; virtual ParamIteratorInterface* End() const = 0; }; // Wraps ParamGeneratorInterface and provides general generator syntax // compatible with the STL Container concept. // This class implements copy initialization semantics and the contained // ParamGeneratorInterface instance is shared among all copies // of the original object. This is possible because that instance is immutable. template class ParamGenerator { public: typedef ParamIterator iterator; explicit ParamGenerator(ParamGeneratorInterface* impl) : impl_(impl) {} ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {} ParamGenerator& operator=(const ParamGenerator& other) { impl_ = other.impl_; return *this; } iterator begin() const { return iterator(impl_->Begin()); } iterator end() const { return iterator(impl_->End()); } private: linked_ptr > impl_; }; // Generates values from a range of two comparable values. Can be used to // generate sequences of user-defined types that implement operator+() and // operator<(). // This class is used in the Range() function. template class RangeGenerator : public ParamGeneratorInterface { public: RangeGenerator(T begin, T end, IncrementT step) : begin_(begin), end_(end), step_(step), end_index_(CalculateEndIndex(begin, end, step)) {} virtual ~RangeGenerator() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, begin_, 0, step_); } virtual ParamIteratorInterface* End() const { return new Iterator(this, end_, end_index_, step_); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, T value, int index, IncrementT step) : base_(base), value_(value), index_(index), step_(step) {} virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } virtual void Advance() { value_ = value_ + step_; index_++; } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const T* Current() const { return &value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const int other_index = CheckedDowncastToActualType(&other)->index_; return index_ == other_index; } private: Iterator(const Iterator& other) : ParamIteratorInterface(), base_(other.base_), value_(other.value_), index_(other.index_), step_(other.step_) {} // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; T value_; int index_; const IncrementT step_; }; // class RangeGenerator::Iterator static int CalculateEndIndex(const T& begin, const T& end, const IncrementT& step) { int end_index = 0; for (T i = begin; i < end; i = i + step) end_index++; return end_index; } // No implementation - assignment is unsupported. void operator=(const RangeGenerator& other); const T begin_; const T end_; const IncrementT step_; // The index for the end() iterator. All the elements in the generated // sequence are indexed (0-based) to aid iterator comparison. const int end_index_; }; // class RangeGenerator // Generates values from a pair of STL-style iterators. Used in the // ValuesIn() function. The elements are copied from the source range // since the source can be located on the stack, and the generator // is likely to persist beyond that stack frame. template class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface { public: template ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end) : container_(begin, end) {} virtual ~ValuesInIteratorRangeGenerator() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, container_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, container_.end()); } private: typedef typename ::std::vector ContainerType; class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, typename ContainerType::const_iterator iterator) : base_(base), iterator_(iterator) {} virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } virtual void Advance() { ++iterator_; value_.reset(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } // We need to use cached value referenced by iterator_ because *iterator_ // can return a temporary object (and of type other then T), so just // having "return &*iterator_;" doesn't work. // value_ is updated here and not in Advance() because Advance() // can advance iterator_ beyond the end of the range, and we cannot // detect that fact. The client code, on the other hand, is // responsible for not calling Current() on an out-of-range iterator. virtual const T* Current() const { if (value_.get() == NULL) value_.reset(new T(*iterator_)); return value_.get(); } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; return iterator_ == CheckedDowncastToActualType(&other)->iterator_; } private: Iterator(const Iterator& other) // The explicit constructor call suppresses a false warning // emitted by gcc when supplied with the -Wextra option. : ParamIteratorInterface(), base_(other.base_), iterator_(other.iterator_) {} const ParamGeneratorInterface* const base_; typename ContainerType::const_iterator iterator_; // A cached value of *iterator_. We keep it here to allow access by // pointer in the wrapping iterator's operator->(). // value_ needs to be mutable to be accessed in Current(). // Use of scoped_ptr helps manage cached value's lifetime, // which is bound by the lifespan of the iterator itself. mutable scoped_ptr value_; }; // class ValuesInIteratorRangeGenerator::Iterator // No implementation - assignment is unsupported. void operator=(const ValuesInIteratorRangeGenerator& other); const ContainerType container_; }; // class ValuesInIteratorRangeGenerator // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Stores a parameter value and later creates tests parameterized with that // value. template class ParameterizedTestFactory : public TestFactoryBase { public: typedef typename TestClass::ParamType ParamType; explicit ParameterizedTestFactory(ParamType parameter) : parameter_(parameter) {} virtual Test* CreateTest() { TestClass::SetParam(¶meter_); return new TestClass(); } private: const ParamType parameter_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // TestMetaFactoryBase is a base class for meta-factories that create // test factories for passing into MakeAndRegisterTestInfo function. template class TestMetaFactoryBase { public: virtual ~TestMetaFactoryBase() {} virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0; }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // TestMetaFactory creates test factories for passing into // MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives // ownership of test factory pointer, same factory object cannot be passed // into that method twice. But ParameterizedTestCaseInfo is going to call // it for each Test/Parameter value combination. Thus it needs meta factory // creator class. template class TestMetaFactory : public TestMetaFactoryBase { public: typedef typename TestCase::ParamType ParamType; TestMetaFactory() {} virtual TestFactoryBase* CreateTestFactory(ParamType parameter) { return new ParameterizedTestFactory(parameter); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // ParameterizedTestCaseInfoBase is a generic interface // to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase // accumulates test information provided by TEST_P macro invocations // and generators provided by INSTANTIATE_TEST_CASE_P macro invocations // and uses that information to register all resulting test instances // in RegisterTests method. The ParameterizeTestCaseRegistry class holds // a collection of pointers to the ParameterizedTestCaseInfo objects // and calls RegisterTests() on each of them when asked. class ParameterizedTestCaseInfoBase { public: virtual ~ParameterizedTestCaseInfoBase() {} // Base part of test case name for display purposes. virtual const string& GetTestCaseName() const = 0; // Test case id to verify identity. virtual TypeId GetTestCaseTypeId() const = 0; // UnitTest class invokes this method to register tests in this // test case right before running them in RUN_ALL_TESTS macro. // This method should not be called more then once on any single // instance of a ParameterizedTestCaseInfoBase derived class. virtual void RegisterTests() = 0; protected: ParameterizedTestCaseInfoBase() {} private: GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase); }; // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // ParameterizedTestCaseInfo accumulates tests obtained from TEST_P // macro invocations for a particular test case and generators // obtained from INSTANTIATE_TEST_CASE_P macro invocations for that // test case. It registers tests with all values generated by all // generators when asked. template class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { public: // ParamType and GeneratorCreationFunc are private types but are required // for declarations of public methods AddTestPattern() and // AddTestCaseInstantiation(). typedef typename TestCase::ParamType ParamType; // A function that returns an instance of appropriate generator type. typedef ParamGenerator(GeneratorCreationFunc)(); explicit ParameterizedTestCaseInfo(const char* name) : test_case_name_(name) {} // Test case base name for display purposes. virtual const string& GetTestCaseName() const { return test_case_name_; } // Test case id to verify identity. virtual TypeId GetTestCaseTypeId() const { return GetTypeId(); } // TEST_P macro uses AddTestPattern() to record information // about a single test in a LocalTestInfo structure. // test_case_name is the base name of the test case (without invocation // prefix). test_base_name is the name of an individual test without // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is // test case base name and DoBar is test base name. void AddTestPattern(const char* test_case_name, const char* test_base_name, TestMetaFactoryBase* meta_factory) { tests_.push_back(linked_ptr(new TestInfo(test_case_name, test_base_name, meta_factory))); } // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information // about a generator. int AddTestCaseInstantiation(const string& instantiation_name, GeneratorCreationFunc* func, const char* /* file */, int /* line */) { instantiations_.push_back(::std::make_pair(instantiation_name, func)); return 0; // Return value used only to run this method in namespace scope. } // UnitTest class invokes this method to register tests in this test case // test cases right before running tests in RUN_ALL_TESTS macro. // This method should not be called more then once on any single // instance of a ParameterizedTestCaseInfoBase derived class. // UnitTest has a guard to prevent from calling this method more then once. virtual void RegisterTests() { for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { linked_ptr test_info = *test_it; for (typename InstantiationContainer::iterator gen_it = instantiations_.begin(); gen_it != instantiations_.end(); ++gen_it) { const string& instantiation_name = gen_it->first; ParamGenerator generator((*gen_it->second)()); string test_case_name; if ( !instantiation_name.empty() ) test_case_name = instantiation_name + "/"; test_case_name += test_info->test_case_base_name; int i = 0; for (typename ParamGenerator::iterator param_it = generator.begin(); param_it != generator.end(); ++param_it, ++i) { Message test_name_stream; test_name_stream << test_info->test_base_name << "/" << i; MakeAndRegisterTestInfo( test_case_name.c_str(), test_name_stream.GetString().c_str(), NULL, // No type parameter. PrintToString(*param_it).c_str(), GetTestCaseTypeId(), TestCase::SetUpTestCase, TestCase::TearDownTestCase, test_info->test_meta_factory->CreateTestFactory(*param_it)); } // for param_it } // for gen_it } // for test_it } // RegisterTests private: // LocalTestInfo structure keeps information about a single test registered // with TEST_P macro. struct TestInfo { TestInfo(const char* a_test_case_base_name, const char* a_test_base_name, TestMetaFactoryBase* a_test_meta_factory) : test_case_base_name(a_test_case_base_name), test_base_name(a_test_base_name), test_meta_factory(a_test_meta_factory) {} const string test_case_base_name; const string test_base_name; const scoped_ptr > test_meta_factory; }; typedef ::std::vector > TestInfoContainer; // Keeps pairs of // received from INSTANTIATE_TEST_CASE_P macros. typedef ::std::vector > InstantiationContainer; const string test_case_name_; TestInfoContainer tests_; InstantiationContainer instantiations_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo); }; // class ParameterizedTestCaseInfo // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase // classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P // macros use it to locate their corresponding ParameterizedTestCaseInfo // descriptors. class ParameterizedTestCaseRegistry { public: ParameterizedTestCaseRegistry() {} ~ParameterizedTestCaseRegistry() { for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); it != test_case_infos_.end(); ++it) { delete *it; } } // Looks up or creates and returns a structure containing information about // tests and instantiations of a particular test case. template ParameterizedTestCaseInfo* GetTestCasePatternHolder( const char* test_case_name, const char* file, int line) { ParameterizedTestCaseInfo* typed_test_info = NULL; for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); it != test_case_infos_.end(); ++it) { if ((*it)->GetTestCaseName() == test_case_name) { if ((*it)->GetTestCaseTypeId() != GetTypeId()) { // Complain about incorrect usage of Google Test facilities // and terminate the program since we cannot guaranty correct // test case setup and tear-down in this case. ReportInvalidTestCaseType(test_case_name, file, line); posix::Abort(); } else { // At this point we are sure that the object we found is of the same // type we are looking for, so we downcast it to that type // without further checks. typed_test_info = CheckedDowncastToActualType< ParameterizedTestCaseInfo >(*it); } break; } } if (typed_test_info == NULL) { typed_test_info = new ParameterizedTestCaseInfo(test_case_name); test_case_infos_.push_back(typed_test_info); } return typed_test_info; } void RegisterTests() { for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); it != test_case_infos_.end(); ++it) { (*it)->RegisterTests(); } } private: typedef ::std::vector TestCaseInfoContainer; TestCaseInfoContainer test_case_infos_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry); }; } // namespace internal } // namespace testing #endif // GTEST_HAS_PARAM_TEST #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ // This file was GENERATED by command: // pump.py gtest-param-util-generated.h.pump // DO NOT EDIT BY HAND!!! // Copyright 2008 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: vladl@google.com (Vlad Losev) // Type and function utilities for implementing parameterized tests. // This file is generated by a SCRIPT. DO NOT EDIT BY HAND! // // Currently Google Test supports at most 50 arguments in Values, // and at most 10 arguments in Combine. Please contact // googletestframework@googlegroups.com if you need more. // Please note that the number of arguments to Combine is limited // by the maximum arity of the implementation of tr1::tuple which is // currently set at 10. #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ // scripts/fuse_gtest.py depends on gtest's own header being #included // *unconditionally*. Therefore these #includes cannot be moved // inside #if GTEST_HAS_PARAM_TEST. #if GTEST_HAS_PARAM_TEST namespace testing { // Forward declarations of ValuesIn(), which is implemented in // include/gtest/gtest-param-test.h. template internal::ParamGenerator< typename ::testing::internal::IteratorTraits::value_type> ValuesIn(ForwardIterator begin, ForwardIterator end); template internal::ParamGenerator ValuesIn(const T (&array)[N]); template internal::ParamGenerator ValuesIn( const Container& container); namespace internal { // Used in the Values() function to provide polymorphic capabilities. template class ValueArray1 { public: explicit ValueArray1(T1 v1) : v1_(v1) {} template operator ParamGenerator() const { return ValuesIn(&v1_, &v1_ + 1); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray1& other); const T1 v1_; }; template class ValueArray2 { public: ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray2& other); const T1 v1_; const T2 v2_; }; template class ValueArray3 { public: ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray3& other); const T1 v1_; const T2 v2_; const T3 v3_; }; template class ValueArray4 { public: ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3), v4_(v4) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray4& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; }; template class ValueArray5 { public: ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray5& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; }; template class ValueArray6 { public: ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray6& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; }; template class ValueArray7 { public: ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray7& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; }; template class ValueArray8 { public: ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray8& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; }; template class ValueArray9 { public: ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray9& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; }; template class ValueArray10 { public: ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray10& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; }; template class ValueArray11 { public: ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray11& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; }; template class ValueArray12 { public: ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray12& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; }; template class ValueArray13 { public: ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray13& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; }; template class ValueArray14 { public: ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray14& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; }; template class ValueArray15 { public: ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray15& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; }; template class ValueArray16 { public: ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray16& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; }; template class ValueArray17 { public: ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray17& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; }; template class ValueArray18 { public: ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray18& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; }; template class ValueArray19 { public: ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray19& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; }; template class ValueArray20 { public: ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray20& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; }; template class ValueArray21 { public: ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray21& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; }; template class ValueArray22 { public: ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray22& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; }; template class ValueArray23 { public: ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray23& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; }; template class ValueArray24 { public: ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray24& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; }; template class ValueArray25 { public: ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray25& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; }; template class ValueArray26 { public: ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray26& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; }; template class ValueArray27 { public: ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray27& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; }; template class ValueArray28 { public: ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray28& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; }; template class ValueArray29 { public: ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray29& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; }; template class ValueArray30 { public: ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray30& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; }; template class ValueArray31 { public: ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray31& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; }; template class ValueArray32 { public: ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray32& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; }; template class ValueArray33 { public: ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray33& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; }; template class ValueArray34 { public: ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray34& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; }; template class ValueArray35 { public: ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray35& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; }; template class ValueArray36 { public: ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray36& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; }; template class ValueArray37 { public: ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray37& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; }; template class ValueArray38 { public: ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray38& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; }; template class ValueArray39 { public: ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray39& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; }; template class ValueArray40 { public: ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray40& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; }; template class ValueArray41 { public: ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray41& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; }; template class ValueArray42 { public: ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray42& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; }; template class ValueArray43 { public: ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray43& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; }; template class ValueArray44 { public: ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray44& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; }; template class ValueArray45 { public: ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_), static_cast(v45_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray45& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; const T45 v45_; }; template class ValueArray46 { public: ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_), static_cast(v45_), static_cast(v46_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray46& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; const T45 v45_; const T46 v46_; }; template class ValueArray47 { public: ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), v47_(v47) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_), static_cast(v45_), static_cast(v46_), static_cast(v47_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray47& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; const T45 v45_; const T46 v46_; const T47 v47_; }; template class ValueArray48 { public: ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), v47_(v47), v48_(v48) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_), static_cast(v45_), static_cast(v46_), static_cast(v47_), static_cast(v48_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray48& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; const T45 v45_; const T46 v46_; const T47 v47_; const T48 v48_; }; template class ValueArray49 { public: ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_), static_cast(v45_), static_cast(v46_), static_cast(v47_), static_cast(v48_), static_cast(v49_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray49& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; const T45 v45_; const T46 v46_; const T47 v47_; const T48 v48_; const T49 v49_; }; template class ValueArray50 { public: ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {} template operator ParamGenerator() const { const T array[] = {static_cast(v1_), static_cast(v2_), static_cast(v3_), static_cast(v4_), static_cast(v5_), static_cast(v6_), static_cast(v7_), static_cast(v8_), static_cast(v9_), static_cast(v10_), static_cast(v11_), static_cast(v12_), static_cast(v13_), static_cast(v14_), static_cast(v15_), static_cast(v16_), static_cast(v17_), static_cast(v18_), static_cast(v19_), static_cast(v20_), static_cast(v21_), static_cast(v22_), static_cast(v23_), static_cast(v24_), static_cast(v25_), static_cast(v26_), static_cast(v27_), static_cast(v28_), static_cast(v29_), static_cast(v30_), static_cast(v31_), static_cast(v32_), static_cast(v33_), static_cast(v34_), static_cast(v35_), static_cast(v36_), static_cast(v37_), static_cast(v38_), static_cast(v39_), static_cast(v40_), static_cast(v41_), static_cast(v42_), static_cast(v43_), static_cast(v44_), static_cast(v45_), static_cast(v46_), static_cast(v47_), static_cast(v48_), static_cast(v49_), static_cast(v50_)}; return ValuesIn(array); } private: // No implementation - assignment is unsupported. void operator=(const ValueArray50& other); const T1 v1_; const T2 v2_; const T3 v3_; const T4 v4_; const T5 v5_; const T6 v6_; const T7 v7_; const T8 v8_; const T9 v9_; const T10 v10_; const T11 v11_; const T12 v12_; const T13 v13_; const T14 v14_; const T15 v15_; const T16 v16_; const T17 v17_; const T18 v18_; const T19 v19_; const T20 v20_; const T21 v21_; const T22 v22_; const T23 v23_; const T24 v24_; const T25 v25_; const T26 v26_; const T27 v27_; const T28 v28_; const T29 v29_; const T30 v30_; const T31 v31_; const T32 v32_; const T33 v33_; const T34 v34_; const T35 v35_; const T36 v36_; const T37 v37_; const T38 v38_; const T39 v39_; const T40 v40_; const T41 v41_; const T42 v42_; const T43 v43_; const T44 v44_; const T45 v45_; const T46 v46_; const T47 v47_; const T48 v48_; const T49 v49_; const T50 v50_; }; # if GTEST_HAS_COMBINE // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Generates values from the Cartesian product of values produced // by the argument generators. // template class CartesianProductGenerator2 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator2(const ParamGenerator& g1, const ParamGenerator& g2) : g1_(g1), g2_(g2) {} virtual ~CartesianProductGenerator2() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current2_; if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; ParamType current_value_; }; // class CartesianProductGenerator2::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator2& other); const ParamGenerator g1_; const ParamGenerator g2_; }; // class CartesianProductGenerator2 template class CartesianProductGenerator3 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator3(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3) : g1_(g1), g2_(g2), g3_(g3) {} virtual ~CartesianProductGenerator3() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current3_; if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; ParamType current_value_; }; // class CartesianProductGenerator3::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator3& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; }; // class CartesianProductGenerator3 template class CartesianProductGenerator4 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator4(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4) : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} virtual ~CartesianProductGenerator4() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current4_; if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; ParamType current_value_; }; // class CartesianProductGenerator4::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator4& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; }; // class CartesianProductGenerator4 template class CartesianProductGenerator5 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator5(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4, const ParamGenerator& g5) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} virtual ~CartesianProductGenerator5() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end(), g5_, g5_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4, const ParamGenerator& g5, const typename ParamGenerator::iterator& current5) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4), begin5_(g5.begin()), end5_(g5.end()), current5_(current5) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current5_; if (current5_ == end5_) { current5_ = begin5_; ++current4_; } if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_ && current5_ == typed_other->current5_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_), begin5_(other.begin5_), end5_(other.end5_), current5_(other.current5_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_, *current5_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_ || current5_ == end5_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; const typename ParamGenerator::iterator begin5_; const typename ParamGenerator::iterator end5_; typename ParamGenerator::iterator current5_; ParamType current_value_; }; // class CartesianProductGenerator5::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator5& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; const ParamGenerator g5_; }; // class CartesianProductGenerator5 template class CartesianProductGenerator6 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator6(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4, const ParamGenerator& g5, const ParamGenerator& g6) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} virtual ~CartesianProductGenerator6() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4, const ParamGenerator& g5, const typename ParamGenerator::iterator& current5, const ParamGenerator& g6, const typename ParamGenerator::iterator& current6) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4), begin5_(g5.begin()), end5_(g5.end()), current5_(current5), begin6_(g6.begin()), end6_(g6.end()), current6_(current6) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current6_; if (current6_ == end6_) { current6_ = begin6_; ++current5_; } if (current5_ == end5_) { current5_ = begin5_; ++current4_; } if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_ && current5_ == typed_other->current5_ && current6_ == typed_other->current6_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_), begin5_(other.begin5_), end5_(other.end5_), current5_(other.current5_), begin6_(other.begin6_), end6_(other.end6_), current6_(other.current6_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_, *current5_, *current6_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_ || current5_ == end5_ || current6_ == end6_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; const typename ParamGenerator::iterator begin5_; const typename ParamGenerator::iterator end5_; typename ParamGenerator::iterator current5_; const typename ParamGenerator::iterator begin6_; const typename ParamGenerator::iterator end6_; typename ParamGenerator::iterator current6_; ParamType current_value_; }; // class CartesianProductGenerator6::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator6& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; const ParamGenerator g5_; const ParamGenerator g6_; }; // class CartesianProductGenerator6 template class CartesianProductGenerator7 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator7(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4, const ParamGenerator& g5, const ParamGenerator& g6, const ParamGenerator& g7) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} virtual ~CartesianProductGenerator7() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, g7_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4, const ParamGenerator& g5, const typename ParamGenerator::iterator& current5, const ParamGenerator& g6, const typename ParamGenerator::iterator& current6, const ParamGenerator& g7, const typename ParamGenerator::iterator& current7) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4), begin5_(g5.begin()), end5_(g5.end()), current5_(current5), begin6_(g6.begin()), end6_(g6.end()), current6_(current6), begin7_(g7.begin()), end7_(g7.end()), current7_(current7) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current7_; if (current7_ == end7_) { current7_ = begin7_; ++current6_; } if (current6_ == end6_) { current6_ = begin6_; ++current5_; } if (current5_ == end5_) { current5_ = begin5_; ++current4_; } if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_ && current5_ == typed_other->current5_ && current6_ == typed_other->current6_ && current7_ == typed_other->current7_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_), begin5_(other.begin5_), end5_(other.end5_), current5_(other.current5_), begin6_(other.begin6_), end6_(other.end6_), current6_(other.current6_), begin7_(other.begin7_), end7_(other.end7_), current7_(other.current7_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_, *current5_, *current6_, *current7_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_ || current5_ == end5_ || current6_ == end6_ || current7_ == end7_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; const typename ParamGenerator::iterator begin5_; const typename ParamGenerator::iterator end5_; typename ParamGenerator::iterator current5_; const typename ParamGenerator::iterator begin6_; const typename ParamGenerator::iterator end6_; typename ParamGenerator::iterator current6_; const typename ParamGenerator::iterator begin7_; const typename ParamGenerator::iterator end7_; typename ParamGenerator::iterator current7_; ParamType current_value_; }; // class CartesianProductGenerator7::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator7& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; const ParamGenerator g5_; const ParamGenerator g6_; const ParamGenerator g7_; }; // class CartesianProductGenerator7 template class CartesianProductGenerator8 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator8(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4, const ParamGenerator& g5, const ParamGenerator& g6, const ParamGenerator& g7, const ParamGenerator& g8) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8) {} virtual ~CartesianProductGenerator8() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, g7_.begin(), g8_, g8_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, g8_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4, const ParamGenerator& g5, const typename ParamGenerator::iterator& current5, const ParamGenerator& g6, const typename ParamGenerator::iterator& current6, const ParamGenerator& g7, const typename ParamGenerator::iterator& current7, const ParamGenerator& g8, const typename ParamGenerator::iterator& current8) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4), begin5_(g5.begin()), end5_(g5.end()), current5_(current5), begin6_(g6.begin()), end6_(g6.end()), current6_(current6), begin7_(g7.begin()), end7_(g7.end()), current7_(current7), begin8_(g8.begin()), end8_(g8.end()), current8_(current8) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current8_; if (current8_ == end8_) { current8_ = begin8_; ++current7_; } if (current7_ == end7_) { current7_ = begin7_; ++current6_; } if (current6_ == end6_) { current6_ = begin6_; ++current5_; } if (current5_ == end5_) { current5_ = begin5_; ++current4_; } if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_ && current5_ == typed_other->current5_ && current6_ == typed_other->current6_ && current7_ == typed_other->current7_ && current8_ == typed_other->current8_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_), begin5_(other.begin5_), end5_(other.end5_), current5_(other.current5_), begin6_(other.begin6_), end6_(other.end6_), current6_(other.current6_), begin7_(other.begin7_), end7_(other.end7_), current7_(other.current7_), begin8_(other.begin8_), end8_(other.end8_), current8_(other.current8_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_, *current5_, *current6_, *current7_, *current8_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_ || current5_ == end5_ || current6_ == end6_ || current7_ == end7_ || current8_ == end8_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; const typename ParamGenerator::iterator begin5_; const typename ParamGenerator::iterator end5_; typename ParamGenerator::iterator current5_; const typename ParamGenerator::iterator begin6_; const typename ParamGenerator::iterator end6_; typename ParamGenerator::iterator current6_; const typename ParamGenerator::iterator begin7_; const typename ParamGenerator::iterator end7_; typename ParamGenerator::iterator current7_; const typename ParamGenerator::iterator begin8_; const typename ParamGenerator::iterator end8_; typename ParamGenerator::iterator current8_; ParamType current_value_; }; // class CartesianProductGenerator8::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator8& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; const ParamGenerator g5_; const ParamGenerator g6_; const ParamGenerator g7_; const ParamGenerator g8_; }; // class CartesianProductGenerator8 template class CartesianProductGenerator9 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator9(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4, const ParamGenerator& g5, const ParamGenerator& g6, const ParamGenerator& g7, const ParamGenerator& g8, const ParamGenerator& g9) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), g9_(g9) {} virtual ~CartesianProductGenerator9() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, g8_.end(), g9_, g9_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4, const ParamGenerator& g5, const typename ParamGenerator::iterator& current5, const ParamGenerator& g6, const typename ParamGenerator::iterator& current6, const ParamGenerator& g7, const typename ParamGenerator::iterator& current7, const ParamGenerator& g8, const typename ParamGenerator::iterator& current8, const ParamGenerator& g9, const typename ParamGenerator::iterator& current9) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4), begin5_(g5.begin()), end5_(g5.end()), current5_(current5), begin6_(g6.begin()), end6_(g6.end()), current6_(current6), begin7_(g7.begin()), end7_(g7.end()), current7_(current7), begin8_(g8.begin()), end8_(g8.end()), current8_(current8), begin9_(g9.begin()), end9_(g9.end()), current9_(current9) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current9_; if (current9_ == end9_) { current9_ = begin9_; ++current8_; } if (current8_ == end8_) { current8_ = begin8_; ++current7_; } if (current7_ == end7_) { current7_ = begin7_; ++current6_; } if (current6_ == end6_) { current6_ = begin6_; ++current5_; } if (current5_ == end5_) { current5_ = begin5_; ++current4_; } if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_ && current5_ == typed_other->current5_ && current6_ == typed_other->current6_ && current7_ == typed_other->current7_ && current8_ == typed_other->current8_ && current9_ == typed_other->current9_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_), begin5_(other.begin5_), end5_(other.end5_), current5_(other.current5_), begin6_(other.begin6_), end6_(other.end6_), current6_(other.current6_), begin7_(other.begin7_), end7_(other.end7_), current7_(other.current7_), begin8_(other.begin8_), end8_(other.end8_), current8_(other.current8_), begin9_(other.begin9_), end9_(other.end9_), current9_(other.current9_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_, *current5_, *current6_, *current7_, *current8_, *current9_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_ || current5_ == end5_ || current6_ == end6_ || current7_ == end7_ || current8_ == end8_ || current9_ == end9_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; const typename ParamGenerator::iterator begin5_; const typename ParamGenerator::iterator end5_; typename ParamGenerator::iterator current5_; const typename ParamGenerator::iterator begin6_; const typename ParamGenerator::iterator end6_; typename ParamGenerator::iterator current6_; const typename ParamGenerator::iterator begin7_; const typename ParamGenerator::iterator end7_; typename ParamGenerator::iterator current7_; const typename ParamGenerator::iterator begin8_; const typename ParamGenerator::iterator end8_; typename ParamGenerator::iterator current8_; const typename ParamGenerator::iterator begin9_; const typename ParamGenerator::iterator end9_; typename ParamGenerator::iterator current9_; ParamType current_value_; }; // class CartesianProductGenerator9::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator9& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; const ParamGenerator g5_; const ParamGenerator g6_; const ParamGenerator g7_; const ParamGenerator g8_; const ParamGenerator g9_; }; // class CartesianProductGenerator9 template class CartesianProductGenerator10 : public ParamGeneratorInterface< ::std::tr1::tuple > { public: typedef ::std::tr1::tuple ParamType; CartesianProductGenerator10(const ParamGenerator& g1, const ParamGenerator& g2, const ParamGenerator& g3, const ParamGenerator& g4, const ParamGenerator& g5, const ParamGenerator& g6, const ParamGenerator& g7, const ParamGenerator& g8, const ParamGenerator& g9, const ParamGenerator& g10) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), g9_(g9), g10_(g10) {} virtual ~CartesianProductGenerator10() {} virtual ParamIteratorInterface* Begin() const { return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_, g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_, g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin()); } virtual ParamIteratorInterface* End() const { return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(), g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_, g8_.end(), g9_, g9_.end(), g10_, g10_.end()); } private: class Iterator : public ParamIteratorInterface { public: Iterator(const ParamGeneratorInterface* base, const ParamGenerator& g1, const typename ParamGenerator::iterator& current1, const ParamGenerator& g2, const typename ParamGenerator::iterator& current2, const ParamGenerator& g3, const typename ParamGenerator::iterator& current3, const ParamGenerator& g4, const typename ParamGenerator::iterator& current4, const ParamGenerator& g5, const typename ParamGenerator::iterator& current5, const ParamGenerator& g6, const typename ParamGenerator::iterator& current6, const ParamGenerator& g7, const typename ParamGenerator::iterator& current7, const ParamGenerator& g8, const typename ParamGenerator::iterator& current8, const ParamGenerator& g9, const typename ParamGenerator::iterator& current9, const ParamGenerator& g10, const typename ParamGenerator::iterator& current10) : base_(base), begin1_(g1.begin()), end1_(g1.end()), current1_(current1), begin2_(g2.begin()), end2_(g2.end()), current2_(current2), begin3_(g3.begin()), end3_(g3.end()), current3_(current3), begin4_(g4.begin()), end4_(g4.end()), current4_(current4), begin5_(g5.begin()), end5_(g5.end()), current5_(current5), begin6_(g6.begin()), end6_(g6.end()), current6_(current6), begin7_(g7.begin()), end7_(g7.end()), current7_(current7), begin8_(g8.begin()), end8_(g8.end()), current8_(current8), begin9_(g9.begin()), end9_(g9.end()), current9_(current9), begin10_(g10.begin()), end10_(g10.end()), current10_(current10) { ComputeCurrentValue(); } virtual ~Iterator() {} virtual const ParamGeneratorInterface* BaseGenerator() const { return base_; } // Advance should not be called on beyond-of-range iterators // so no component iterators must be beyond end of range, either. virtual void Advance() { assert(!AtEnd()); ++current10_; if (current10_ == end10_) { current10_ = begin10_; ++current9_; } if (current9_ == end9_) { current9_ = begin9_; ++current8_; } if (current8_ == end8_) { current8_ = begin8_; ++current7_; } if (current7_ == end7_) { current7_ = begin7_; ++current6_; } if (current6_ == end6_) { current6_ = begin6_; ++current5_; } if (current5_ == end5_) { current5_ = begin5_; ++current4_; } if (current4_ == end4_) { current4_ = begin4_; ++current3_; } if (current3_ == end3_) { current3_ = begin3_; ++current2_; } if (current2_ == end2_) { current2_ = begin2_; ++current1_; } ComputeCurrentValue(); } virtual ParamIteratorInterface* Clone() const { return new Iterator(*this); } virtual const ParamType* Current() const { return ¤t_value_; } virtual bool Equals(const ParamIteratorInterface& other) const { // Having the same base generator guarantees that the other // iterator is of the same type and we can downcast. GTEST_CHECK_(BaseGenerator() == other.BaseGenerator()) << "The program attempted to compare iterators " << "from different generators." << std::endl; const Iterator* typed_other = CheckedDowncastToActualType(&other); // We must report iterators equal if they both point beyond their // respective ranges. That can happen in a variety of fashions, // so we have to consult AtEnd(). return (AtEnd() && typed_other->AtEnd()) || ( current1_ == typed_other->current1_ && current2_ == typed_other->current2_ && current3_ == typed_other->current3_ && current4_ == typed_other->current4_ && current5_ == typed_other->current5_ && current6_ == typed_other->current6_ && current7_ == typed_other->current7_ && current8_ == typed_other->current8_ && current9_ == typed_other->current9_ && current10_ == typed_other->current10_); } private: Iterator(const Iterator& other) : base_(other.base_), begin1_(other.begin1_), end1_(other.end1_), current1_(other.current1_), begin2_(other.begin2_), end2_(other.end2_), current2_(other.current2_), begin3_(other.begin3_), end3_(other.end3_), current3_(other.current3_), begin4_(other.begin4_), end4_(other.end4_), current4_(other.current4_), begin5_(other.begin5_), end5_(other.end5_), current5_(other.current5_), begin6_(other.begin6_), end6_(other.end6_), current6_(other.current6_), begin7_(other.begin7_), end7_(other.end7_), current7_(other.current7_), begin8_(other.begin8_), end8_(other.end8_), current8_(other.current8_), begin9_(other.begin9_), end9_(other.end9_), current9_(other.current9_), begin10_(other.begin10_), end10_(other.end10_), current10_(other.current10_) { ComputeCurrentValue(); } void ComputeCurrentValue() { if (!AtEnd()) current_value_ = ParamType(*current1_, *current2_, *current3_, *current4_, *current5_, *current6_, *current7_, *current8_, *current9_, *current10_); } bool AtEnd() const { // We must report iterator past the end of the range when either of the // component iterators has reached the end of its range. return current1_ == end1_ || current2_ == end2_ || current3_ == end3_ || current4_ == end4_ || current5_ == end5_ || current6_ == end6_ || current7_ == end7_ || current8_ == end8_ || current9_ == end9_ || current10_ == end10_; } // No implementation - assignment is unsupported. void operator=(const Iterator& other); const ParamGeneratorInterface* const base_; // begin[i]_ and end[i]_ define the i-th range that Iterator traverses. // current[i]_ is the actual traversing iterator. const typename ParamGenerator::iterator begin1_; const typename ParamGenerator::iterator end1_; typename ParamGenerator::iterator current1_; const typename ParamGenerator::iterator begin2_; const typename ParamGenerator::iterator end2_; typename ParamGenerator::iterator current2_; const typename ParamGenerator::iterator begin3_; const typename ParamGenerator::iterator end3_; typename ParamGenerator::iterator current3_; const typename ParamGenerator::iterator begin4_; const typename ParamGenerator::iterator end4_; typename ParamGenerator::iterator current4_; const typename ParamGenerator::iterator begin5_; const typename ParamGenerator::iterator end5_; typename ParamGenerator::iterator current5_; const typename ParamGenerator::iterator begin6_; const typename ParamGenerator::iterator end6_; typename ParamGenerator::iterator current6_; const typename ParamGenerator::iterator begin7_; const typename ParamGenerator::iterator end7_; typename ParamGenerator::iterator current7_; const typename ParamGenerator::iterator begin8_; const typename ParamGenerator::iterator end8_; typename ParamGenerator::iterator current8_; const typename ParamGenerator::iterator begin9_; const typename ParamGenerator::iterator end9_; typename ParamGenerator::iterator current9_; const typename ParamGenerator::iterator begin10_; const typename ParamGenerator::iterator end10_; typename ParamGenerator::iterator current10_; ParamType current_value_; }; // class CartesianProductGenerator10::Iterator // No implementation - assignment is unsupported. void operator=(const CartesianProductGenerator10& other); const ParamGenerator g1_; const ParamGenerator g2_; const ParamGenerator g3_; const ParamGenerator g4_; const ParamGenerator g5_; const ParamGenerator g6_; const ParamGenerator g7_; const ParamGenerator g8_; const ParamGenerator g9_; const ParamGenerator g10_; }; // class CartesianProductGenerator10 // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Helper classes providing Combine() with polymorphic features. They allow // casting CartesianProductGeneratorN to ParamGenerator if T is // convertible to U. // template class CartesianProductHolder2 { public: CartesianProductHolder2(const Generator1& g1, const Generator2& g2) : g1_(g1), g2_(g2) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator2( static_cast >(g1_), static_cast >(g2_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder2& other); const Generator1 g1_; const Generator2 g2_; }; // class CartesianProductHolder2 template class CartesianProductHolder3 { public: CartesianProductHolder3(const Generator1& g1, const Generator2& g2, const Generator3& g3) : g1_(g1), g2_(g2), g3_(g3) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator3( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder3& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; }; // class CartesianProductHolder3 template class CartesianProductHolder4 { public: CartesianProductHolder4(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4) : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator4( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder4& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; }; // class CartesianProductHolder4 template class CartesianProductHolder5 { public: CartesianProductHolder5(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator5( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_), static_cast >(g5_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder5& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; }; // class CartesianProductHolder5 template class CartesianProductHolder6 { public: CartesianProductHolder6(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator6( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_), static_cast >(g5_), static_cast >(g6_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder6& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; const Generator6 g6_; }; // class CartesianProductHolder6 template class CartesianProductHolder7 { public: CartesianProductHolder7(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator7( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_), static_cast >(g5_), static_cast >(g6_), static_cast >(g7_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder7& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; const Generator6 g6_; const Generator7 g7_; }; // class CartesianProductHolder7 template class CartesianProductHolder8 { public: CartesianProductHolder8(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7, const Generator8& g8) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator8( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_), static_cast >(g5_), static_cast >(g6_), static_cast >(g7_), static_cast >(g8_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder8& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; const Generator6 g6_; const Generator7 g7_; const Generator8 g8_; }; // class CartesianProductHolder8 template class CartesianProductHolder9 { public: CartesianProductHolder9(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7, const Generator8& g8, const Generator9& g9) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), g9_(g9) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator9( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_), static_cast >(g5_), static_cast >(g6_), static_cast >(g7_), static_cast >(g8_), static_cast >(g9_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder9& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; const Generator6 g6_; const Generator7 g7_; const Generator8 g8_; const Generator9 g9_; }; // class CartesianProductHolder9 template class CartesianProductHolder10 { public: CartesianProductHolder10(const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7, const Generator8& g8, const Generator9& g9, const Generator10& g10) : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8), g9_(g9), g10_(g10) {} template operator ParamGenerator< ::std::tr1::tuple >() const { return ParamGenerator< ::std::tr1::tuple >( new CartesianProductGenerator10( static_cast >(g1_), static_cast >(g2_), static_cast >(g3_), static_cast >(g4_), static_cast >(g5_), static_cast >(g6_), static_cast >(g7_), static_cast >(g8_), static_cast >(g9_), static_cast >(g10_))); } private: // No implementation - assignment is unsupported. void operator=(const CartesianProductHolder10& other); const Generator1 g1_; const Generator2 g2_; const Generator3 g3_; const Generator4 g4_; const Generator5 g5_; const Generator6 g6_; const Generator7 g7_; const Generator8 g8_; const Generator9 g9_; const Generator10 g10_; }; // class CartesianProductHolder10 # endif // GTEST_HAS_COMBINE } // namespace internal } // namespace testing #endif // GTEST_HAS_PARAM_TEST #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #if GTEST_HAS_PARAM_TEST namespace testing { // Functions producing parameter generators. // // Google Test uses these generators to produce parameters for value- // parameterized tests. When a parameterized test case is instantiated // with a particular generator, Google Test creates and runs tests // for each element in the sequence produced by the generator. // // In the following sample, tests from test case FooTest are instantiated // each three times with parameter values 3, 5, and 8: // // class FooTest : public TestWithParam { ... }; // // TEST_P(FooTest, TestThis) { // } // TEST_P(FooTest, TestThat) { // } // INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8)); // // Range() returns generators providing sequences of values in a range. // // Synopsis: // Range(start, end) // - returns a generator producing a sequence of values {start, start+1, // start+2, ..., }. // Range(start, end, step) // - returns a generator producing a sequence of values {start, start+step, // start+step+step, ..., }. // Notes: // * The generated sequences never include end. For example, Range(1, 5) // returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2) // returns a generator producing {1, 3, 5, 7}. // * start and end must have the same type. That type may be any integral or // floating-point type or a user defined type satisfying these conditions: // * It must be assignable (have operator=() defined). // * It must have operator+() (operator+(int-compatible type) for // two-operand version). // * It must have operator<() defined. // Elements in the resulting sequences will also have that type. // * Condition start < end must be satisfied in order for resulting sequences // to contain any elements. // template internal::ParamGenerator Range(T start, T end, IncrementT step) { return internal::ParamGenerator( new internal::RangeGenerator(start, end, step)); } template internal::ParamGenerator Range(T start, T end) { return Range(start, end, 1); } // ValuesIn() function allows generation of tests with parameters coming from // a container. // // Synopsis: // ValuesIn(const T (&array)[N]) // - returns a generator producing sequences with elements from // a C-style array. // ValuesIn(const Container& container) // - returns a generator producing sequences with elements from // an STL-style container. // ValuesIn(Iterator begin, Iterator end) // - returns a generator producing sequences with elements from // a range [begin, end) defined by a pair of STL-style iterators. These // iterators can also be plain C pointers. // // Please note that ValuesIn copies the values from the containers // passed in and keeps them to generate tests in RUN_ALL_TESTS(). // // Examples: // // This instantiates tests from test case StringTest // each with C-string values of "foo", "bar", and "baz": // // const char* strings[] = {"foo", "bar", "baz"}; // INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings)); // // This instantiates tests from test case StlStringTest // each with STL strings with values "a" and "b": // // ::std::vector< ::std::string> GetParameterStrings() { // ::std::vector< ::std::string> v; // v.push_back("a"); // v.push_back("b"); // return v; // } // // INSTANTIATE_TEST_CASE_P(CharSequence, // StlStringTest, // ValuesIn(GetParameterStrings())); // // // This will also instantiate tests from CharTest // each with parameter values 'a' and 'b': // // ::std::list GetParameterChars() { // ::std::list list; // list.push_back('a'); // list.push_back('b'); // return list; // } // ::std::list l = GetParameterChars(); // INSTANTIATE_TEST_CASE_P(CharSequence2, // CharTest, // ValuesIn(l.begin(), l.end())); // template internal::ParamGenerator< typename ::testing::internal::IteratorTraits::value_type> ValuesIn(ForwardIterator begin, ForwardIterator end) { typedef typename ::testing::internal::IteratorTraits ::value_type ParamType; return internal::ParamGenerator( new internal::ValuesInIteratorRangeGenerator(begin, end)); } template internal::ParamGenerator ValuesIn(const T (&array)[N]) { return ValuesIn(array, array + N); } template internal::ParamGenerator ValuesIn( const Container& container) { return ValuesIn(container.begin(), container.end()); } // Values() allows generating tests from explicitly specified list of // parameters. // // Synopsis: // Values(T v1, T v2, ..., T vN) // - returns a generator producing sequences with elements v1, v2, ..., vN. // // For example, this instantiates tests from test case BarTest each // with values "one", "two", and "three": // // INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three")); // // This instantiates tests from test case BazTest each with values 1, 2, 3.5. // The exact type of values will depend on the type of parameter in BazTest. // // INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5)); // // Currently, Values() supports from 1 to 50 parameters. // template internal::ValueArray1 Values(T1 v1) { return internal::ValueArray1(v1); } template internal::ValueArray2 Values(T1 v1, T2 v2) { return internal::ValueArray2(v1, v2); } template internal::ValueArray3 Values(T1 v1, T2 v2, T3 v3) { return internal::ValueArray3(v1, v2, v3); } template internal::ValueArray4 Values(T1 v1, T2 v2, T3 v3, T4 v4) { return internal::ValueArray4(v1, v2, v3, v4); } template internal::ValueArray5 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) { return internal::ValueArray5(v1, v2, v3, v4, v5); } template internal::ValueArray6 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) { return internal::ValueArray6(v1, v2, v3, v4, v5, v6); } template internal::ValueArray7 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) { return internal::ValueArray7(v1, v2, v3, v4, v5, v6, v7); } template internal::ValueArray8 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) { return internal::ValueArray8(v1, v2, v3, v4, v5, v6, v7, v8); } template internal::ValueArray9 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) { return internal::ValueArray9(v1, v2, v3, v4, v5, v6, v7, v8, v9); } template internal::ValueArray10 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) { return internal::ValueArray10(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } template internal::ValueArray11 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11) { return internal::ValueArray11(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); } template internal::ValueArray12 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12) { return internal::ValueArray12(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); } template internal::ValueArray13 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13) { return internal::ValueArray13(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); } template internal::ValueArray14 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) { return internal::ValueArray14(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14); } template internal::ValueArray15 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) { return internal::ValueArray15(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15); } template internal::ValueArray16 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) { return internal::ValueArray16(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16); } template internal::ValueArray17 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17) { return internal::ValueArray17(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17); } template internal::ValueArray18 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18) { return internal::ValueArray18(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18); } template internal::ValueArray19 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) { return internal::ValueArray19(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19); } template internal::ValueArray20 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) { return internal::ValueArray20(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20); } template internal::ValueArray21 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) { return internal::ValueArray21(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21); } template internal::ValueArray22 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) { return internal::ValueArray22(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22); } template internal::ValueArray23 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) { return internal::ValueArray23(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23); } template internal::ValueArray24 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) { return internal::ValueArray24(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24); } template internal::ValueArray25 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) { return internal::ValueArray25(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25); } template internal::ValueArray26 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26) { return internal::ValueArray26(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26); } template internal::ValueArray27 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27) { return internal::ValueArray27(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27); } template internal::ValueArray28 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28) { return internal::ValueArray28(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28); } template internal::ValueArray29 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29) { return internal::ValueArray29(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29); } template internal::ValueArray30 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) { return internal::ValueArray30(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30); } template internal::ValueArray31 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) { return internal::ValueArray31(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31); } template internal::ValueArray32 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) { return internal::ValueArray32(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32); } template internal::ValueArray33 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33) { return internal::ValueArray33(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33); } template internal::ValueArray34 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34) { return internal::ValueArray34(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34); } template internal::ValueArray35 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) { return internal::ValueArray35(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35); } template internal::ValueArray36 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) { return internal::ValueArray36(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36); } template internal::ValueArray37 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37) { return internal::ValueArray37(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37); } template internal::ValueArray38 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) { return internal::ValueArray38(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38); } template internal::ValueArray39 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) { return internal::ValueArray39(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39); } template internal::ValueArray40 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) { return internal::ValueArray40(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40); } template internal::ValueArray41 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) { return internal::ValueArray41(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41); } template internal::ValueArray42 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42) { return internal::ValueArray42(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42); } template internal::ValueArray43 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43) { return internal::ValueArray43(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43); } template internal::ValueArray44 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44) { return internal::ValueArray44(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44); } template internal::ValueArray45 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) { return internal::ValueArray45(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45); } template internal::ValueArray46 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) { return internal::ValueArray46(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46); } template internal::ValueArray47 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) { return internal::ValueArray47(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47); } template internal::ValueArray48 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) { return internal::ValueArray48(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48); } template internal::ValueArray49 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49) { return internal::ValueArray49(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49); } template internal::ValueArray50 Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) { return internal::ValueArray50(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50); } // Bool() allows generating tests with parameters in a set of (false, true). // // Synopsis: // Bool() // - returns a generator producing sequences with elements {false, true}. // // It is useful when testing code that depends on Boolean flags. Combinations // of multiple flags can be tested when several Bool()'s are combined using // Combine() function. // // In the following example all tests in the test case FlagDependentTest // will be instantiated twice with parameters false and true. // // class FlagDependentTest : public testing::TestWithParam { // virtual void SetUp() { // external_flag = GetParam(); // } // } // INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool()); // inline internal::ParamGenerator Bool() { return Values(false, true); } # if GTEST_HAS_COMBINE // Combine() allows the user to combine two or more sequences to produce // values of a Cartesian product of those sequences' elements. // // Synopsis: // Combine(gen1, gen2, ..., genN) // - returns a generator producing sequences with elements coming from // the Cartesian product of elements from the sequences generated by // gen1, gen2, ..., genN. The sequence elements will have a type of // tuple where T1, T2, ..., TN are the types // of elements from sequences produces by gen1, gen2, ..., genN. // // Combine can have up to 10 arguments. This number is currently limited // by the maximum number of elements in the tuple implementation used by Google // Test. // // Example: // // This will instantiate tests in test case AnimalTest each one with // the parameter values tuple("cat", BLACK), tuple("cat", WHITE), // tuple("dog", BLACK), and tuple("dog", WHITE): // // enum Color { BLACK, GRAY, WHITE }; // class AnimalTest // : public testing::TestWithParam > {...}; // // TEST_P(AnimalTest, AnimalLooksNice) {...} // // INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest, // Combine(Values("cat", "dog"), // Values(BLACK, WHITE))); // // This will instantiate tests in FlagDependentTest with all variations of two // Boolean flags: // // class FlagDependentTest // : public testing::TestWithParam > { // virtual void SetUp() { // // Assigns external_flag_1 and external_flag_2 values from the tuple. // tie(external_flag_1, external_flag_2) = GetParam(); // } // }; // // TEST_P(FlagDependentTest, TestFeature1) { // // Test your code using external_flag_1 and external_flag_2 here. // } // INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest, // Combine(Bool(), Bool())); // template internal::CartesianProductHolder2 Combine( const Generator1& g1, const Generator2& g2) { return internal::CartesianProductHolder2( g1, g2); } template internal::CartesianProductHolder3 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3) { return internal::CartesianProductHolder3( g1, g2, g3); } template internal::CartesianProductHolder4 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4) { return internal::CartesianProductHolder4( g1, g2, g3, g4); } template internal::CartesianProductHolder5 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5) { return internal::CartesianProductHolder5( g1, g2, g3, g4, g5); } template internal::CartesianProductHolder6 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6) { return internal::CartesianProductHolder6( g1, g2, g3, g4, g5, g6); } template internal::CartesianProductHolder7 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7) { return internal::CartesianProductHolder7( g1, g2, g3, g4, g5, g6, g7); } template internal::CartesianProductHolder8 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7, const Generator8& g8) { return internal::CartesianProductHolder8( g1, g2, g3, g4, g5, g6, g7, g8); } template internal::CartesianProductHolder9 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7, const Generator8& g8, const Generator9& g9) { return internal::CartesianProductHolder9( g1, g2, g3, g4, g5, g6, g7, g8, g9); } template internal::CartesianProductHolder10 Combine( const Generator1& g1, const Generator2& g2, const Generator3& g3, const Generator4& g4, const Generator5& g5, const Generator6& g6, const Generator7& g7, const Generator8& g8, const Generator9& g9, const Generator10& g10) { return internal::CartesianProductHolder10( g1, g2, g3, g4, g5, g6, g7, g8, g9, g10); } # endif // GTEST_HAS_COMBINE # define TEST_P(test_case_name, test_name) \ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ : public test_case_name { \ public: \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ virtual void TestBody(); \ private: \ static int AddToRegistry() { \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ GetTestCasePatternHolder(\ #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ #test_case_name, \ #test_name, \ new ::testing::internal::TestMetaFactory< \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ return 0; \ } \ static int gtest_registering_dummy_; \ GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ }; \ int GTEST_TEST_CLASS_NAME_(test_case_name, \ test_name)::gtest_registering_dummy_ = \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() # define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ ::testing::internal::ParamGenerator \ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ int gtest_##prefix##test_case_name##_dummy_ = \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ GetTestCasePatternHolder(\ #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ #prefix, \ >est_##prefix##test_case_name##_EvalGenerator_, \ __FILE__, __LINE__) } // namespace testing #endif // GTEST_HAS_PARAM_TEST #endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ // Copyright 2006, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // // Google C++ Testing Framework definitions useful in production code. #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ // When you need to test the private or protected members of a class, // use the FRIEND_TEST macro to declare your tests as friends of the // class. For example: // // class MyClass { // private: // void MyMethod(); // FRIEND_TEST(MyClassTest, MyMethod); // }; // // class MyClassTest : public testing::Test { // // ... // }; // // TEST_F(MyClassTest, MyMethod) { // // Can call MyClass::MyMethod() here. // } #define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: mheule@google.com (Markus Heule) // #ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ #define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ #include #include namespace testing { // A copyable object representing the result of a test part (i.e. an // assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()). // // Don't inherit from TestPartResult as its destructor is not virtual. class GTEST_API_ TestPartResult { public: // The possible outcomes of a test part (i.e. an assertion or an // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). enum Type { kSuccess, // Succeeded. kNonFatalFailure, // Failed but the test can continue. kFatalFailure // Failed and the test should be terminated. }; // C'tor. TestPartResult does NOT have a default constructor. // Always use this constructor (with parameters) to create a // TestPartResult object. TestPartResult(Type a_type, const char* a_file_name, int a_line_number, const char* a_message) : type_(a_type), file_name_(a_file_name == NULL ? "" : a_file_name), line_number_(a_line_number), summary_(ExtractSummary(a_message)), message_(a_message) { } // Gets the outcome of the test part. Type type() const { return type_; } // Gets the name of the source file where the test part took place, or // NULL if it's unknown. const char* file_name() const { return file_name_.empty() ? NULL : file_name_.c_str(); } // Gets the line in the source file where the test part took place, // or -1 if it's unknown. int line_number() const { return line_number_; } // Gets the summary of the failure message. const char* summary() const { return summary_.c_str(); } // Gets the message associated with the test part. const char* message() const { return message_.c_str(); } // Returns true iff the test part passed. bool passed() const { return type_ == kSuccess; } // Returns true iff the test part failed. bool failed() const { return type_ != kSuccess; } // Returns true iff the test part non-fatally failed. bool nonfatally_failed() const { return type_ == kNonFatalFailure; } // Returns true iff the test part fatally failed. bool fatally_failed() const { return type_ == kFatalFailure; } private: Type type_; // Gets the summary of the failure message by omitting the stack // trace in it. static std::string ExtractSummary(const char* message); // The name of the source file where the test part took place, or // "" if the source file is unknown. std::string file_name_; // The line in the source file where the test part took place, or -1 // if the line number is unknown. int line_number_; std::string summary_; // The test failure summary. std::string message_; // The test failure message. }; // Prints a TestPartResult object. std::ostream& operator<<(std::ostream& os, const TestPartResult& result); // An array of TestPartResult objects. // // Don't inherit from TestPartResultArray as its destructor is not // virtual. class GTEST_API_ TestPartResultArray { public: TestPartResultArray() {} // Appends the given TestPartResult to the array. void Append(const TestPartResult& result); // Returns the TestPartResult at the given index (0-based). const TestPartResult& GetTestPartResult(int index) const; // Returns the number of TestPartResult objects in the array. int size() const; private: std::vector array_; GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray); }; // This interface knows how to report a test part result. class TestPartResultReporterInterface { public: virtual ~TestPartResultReporterInterface() {} virtual void ReportTestPartResult(const TestPartResult& result) = 0; }; namespace internal { // This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a // statement generates new fatal failures. To do so it registers itself as the // current test part result reporter. Besides checking if fatal failures were // reported, it only delegates the reporting to the former result reporter. // The original result reporter is restored in the destructor. // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. class GTEST_API_ HasNewFatalFailureHelper : public TestPartResultReporterInterface { public: HasNewFatalFailureHelper(); virtual ~HasNewFatalFailureHelper(); virtual void ReportTestPartResult(const TestPartResult& result); bool has_new_fatal_failure() const { return has_new_fatal_failure_; } private: bool has_new_fatal_failure_; TestPartResultReporterInterface* original_reporter_; GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper); }; } // namespace internal } // namespace testing #endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ // Copyright 2008 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) #ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ #define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ // This header implements typed tests and type-parameterized tests. // Typed (aka type-driven) tests repeat the same test for types in a // list. You must know which types you want to test with when writing // typed tests. Here's how you do it: #if 0 // First, define a fixture class template. It should be parameterized // by a type. Remember to derive it from testing::Test. template class FooTest : public testing::Test { public: ... typedef std::list List; static T shared_; T value_; }; // Next, associate a list of types with the test case, which will be // repeated for each type in the list. The typedef is necessary for // the macro to parse correctly. typedef testing::Types MyTypes; TYPED_TEST_CASE(FooTest, MyTypes); // If the type list contains only one type, you can write that type // directly without Types<...>: // TYPED_TEST_CASE(FooTest, int); // Then, use TYPED_TEST() instead of TEST_F() to define as many typed // tests for this test case as you want. TYPED_TEST(FooTest, DoesBlah) { // Inside a test, refer to TypeParam to get the type parameter. // Since we are inside a derived class template, C++ requires use to // visit the members of FooTest via 'this'. TypeParam n = this->value_; // To visit static members of the fixture, add the TestFixture:: // prefix. n += TestFixture::shared_; // To refer to typedefs in the fixture, add the "typename // TestFixture::" prefix. typename TestFixture::List values; values.push_back(n); ... } TYPED_TEST(FooTest, HasPropertyA) { ... } #endif // 0 // Type-parameterized tests are abstract test patterns parameterized // by a type. Compared with typed tests, type-parameterized tests // allow you to define the test pattern without knowing what the type // parameters are. The defined pattern can be instantiated with // different types any number of times, in any number of translation // units. // // If you are designing an interface or concept, you can define a // suite of type-parameterized tests to verify properties that any // valid implementation of the interface/concept should have. Then, // each implementation can easily instantiate the test suite to verify // that it conforms to the requirements, without having to write // similar tests repeatedly. Here's an example: #if 0 // First, define a fixture class template. It should be parameterized // by a type. Remember to derive it from testing::Test. template class FooTest : public testing::Test { ... }; // Next, declare that you will define a type-parameterized test case // (the _P suffix is for "parameterized" or "pattern", whichever you // prefer): TYPED_TEST_CASE_P(FooTest); // Then, use TYPED_TEST_P() to define as many type-parameterized tests // for this type-parameterized test case as you want. TYPED_TEST_P(FooTest, DoesBlah) { // Inside a test, refer to TypeParam to get the type parameter. TypeParam n = 0; ... } TYPED_TEST_P(FooTest, HasPropertyA) { ... } // Now the tricky part: you need to register all test patterns before // you can instantiate them. The first argument of the macro is the // test case name; the rest are the names of the tests in this test // case. REGISTER_TYPED_TEST_CASE_P(FooTest, DoesBlah, HasPropertyA); // Finally, you are free to instantiate the pattern with the types you // want. If you put the above code in a header file, you can #include // it in multiple C++ source files and instantiate it multiple times. // // To distinguish different instances of the pattern, the first // argument to the INSTANTIATE_* macro is a prefix that will be added // to the actual test case name. Remember to pick unique prefixes for // different instances. typedef testing::Types MyTypes; INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); // If the type list contains only one type, you can write that type // directly without Types<...>: // INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); #endif // 0 // Implements typed tests. #if GTEST_HAS_TYPED_TEST // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the name of the typedef for the type parameters of the // given test case. # define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_ // The 'Types' template argument below must have spaces around it // since some compilers may choke on '>>' when passing a template // instance (e.g. Types) # define TYPED_TEST_CASE(CaseName, Types) \ typedef ::testing::internal::TypeList< Types >::type \ GTEST_TYPE_PARAMS_(CaseName) # define TYPED_TEST(CaseName, TestName) \ template \ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ : public CaseName { \ private: \ typedef CaseName TestFixture; \ typedef gtest_TypeParam_ TypeParam; \ virtual void TestBody(); \ }; \ bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \ ::testing::internal::TypeParameterizedTest< \ CaseName, \ ::testing::internal::TemplateSel< \ GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ GTEST_TYPE_PARAMS_(CaseName)>::Register(\ "", #CaseName, #TestName, 0); \ template \ void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() #endif // GTEST_HAS_TYPED_TEST // Implements type-parameterized tests. #if GTEST_HAS_TYPED_TEST_P // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the namespace name that the type-parameterized tests for // the given type-parameterized test case are defined in. The exact // name of the namespace is subject to change without notice. # define GTEST_CASE_NAMESPACE_(TestCaseName) \ gtest_case_##TestCaseName##_ // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the name of the variable used to remember the names of // the defined tests in the given test case. # define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \ gtest_typed_test_case_p_state_##TestCaseName##_ // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY. // // Expands to the name of the variable used to remember the names of // the registered tests in the given test case. # define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \ gtest_registered_test_names_##TestCaseName##_ // The variables defined in the type-parameterized test macros are // static as typically these macros are used in a .h file that can be // #included in multiple translation units linked together. # define TYPED_TEST_CASE_P(CaseName) \ static ::testing::internal::TypedTestCasePState \ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName) # define TYPED_TEST_P(CaseName, TestName) \ namespace GTEST_CASE_NAMESPACE_(CaseName) { \ template \ class TestName : public CaseName { \ private: \ typedef CaseName TestFixture; \ typedef gtest_TypeParam_ TypeParam; \ virtual void TestBody(); \ }; \ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ __FILE__, __LINE__, #CaseName, #TestName); \ } \ template \ void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() # define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ namespace GTEST_CASE_NAMESPACE_(CaseName) { \ typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ } \ static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ __FILE__, __LINE__, #__VA_ARGS__) // The 'Types' template argument below must have spaces around it // since some compilers may choke on '>>' when passing a template // instance (e.g. Types) # define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \ bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \ ::testing::internal::TypeParameterizedTestCase::type>::Register(\ #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) #endif // GTEST_HAS_TYPED_TEST_P #endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ // Depending on the platform, different string classes are available. // On Linux, in addition to ::std::string, Google also makes use of // class ::string, which has the same interface as ::std::string, but // has a different implementation. // // The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that // ::string is available AND is a distinct type to ::std::string, or // define it to 0 to indicate otherwise. // // If the user's ::std::string and ::string are the same class due to // aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. // // If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined // heuristically. namespace testing { // Declares the flags. // This flag temporary enables the disabled tests. GTEST_DECLARE_bool_(also_run_disabled_tests); // This flag brings the debugger on an assertion failure. GTEST_DECLARE_bool_(break_on_failure); // This flag controls whether Google Test catches all test-thrown exceptions // and logs them as failures. GTEST_DECLARE_bool_(catch_exceptions); // This flag enables using colors in terminal output. Available values are // "yes" to enable colors, "no" (disable colors), or "auto" (the default) // to let Google Test decide. GTEST_DECLARE_string_(color); // This flag sets up the filter to select by name using a glob pattern // the tests to run. If the filter is not given all tests are executed. GTEST_DECLARE_string_(filter); // This flag causes the Google Test to list tests. None of the tests listed // are actually run if the flag is provided. GTEST_DECLARE_bool_(list_tests); // This flag controls whether Google Test emits a detailed XML report to a file // in addition to its normal textual output. GTEST_DECLARE_string_(output); // This flags control whether Google Test prints the elapsed time for each // test. GTEST_DECLARE_bool_(print_time); // This flag specifies the random number seed. GTEST_DECLARE_int32_(random_seed); // This flag sets how many times the tests are repeated. The default value // is 1. If the value is -1 the tests are repeating forever. GTEST_DECLARE_int32_(repeat); // This flag controls whether Google Test includes Google Test internal // stack frames in failure stack traces. GTEST_DECLARE_bool_(show_internal_stack_frames); // When this flag is specified, tests' order is randomized on every iteration. GTEST_DECLARE_bool_(shuffle); // This flag specifies the maximum number of stack frames to be // printed in a failure message. GTEST_DECLARE_int32_(stack_trace_depth); // When this flag is specified, a failed assertion will throw an // exception if exceptions are enabled, or exit the program with a // non-zero code otherwise. GTEST_DECLARE_bool_(throw_on_failure); // When this flag is set with a "host:port" string, on supported // platforms test results are streamed to the specified port on // the specified host machine. GTEST_DECLARE_string_(stream_result_to); // The upper limit for valid stack trace depths. const int kMaxStackTraceDepth = 100; namespace internal { class AssertHelper; class DefaultGlobalTestPartResultReporter; class ExecDeathTest; class NoExecDeathTest; class FinalSuccessChecker; class GTestFlagSaver; class StreamingListenerTest; class TestResultAccessor; class TestEventListenersAccessor; class TestEventRepeater; class UnitTestRecordPropertyTestHelper; class WindowsDeathTest; class UnitTestImpl* GetUnitTestImpl(); void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message); } // namespace internal // The friend relationship of some of these classes is cyclic. // If we don't forward declare them the compiler might confuse the classes // in friendship clauses with same named classes on the scope. class Test; class TestCase; class TestInfo; class UnitTest; // A class for indicating whether an assertion was successful. When // the assertion wasn't successful, the AssertionResult object // remembers a non-empty message that describes how it failed. // // To create an instance of this class, use one of the factory functions // (AssertionSuccess() and AssertionFailure()). // // This class is useful for two purposes: // 1. Defining predicate functions to be used with Boolean test assertions // EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts // 2. Defining predicate-format functions to be // used with predicate assertions (ASSERT_PRED_FORMAT*, etc). // // For example, if you define IsEven predicate: // // testing::AssertionResult IsEven(int n) { // if ((n % 2) == 0) // return testing::AssertionSuccess(); // else // return testing::AssertionFailure() << n << " is odd"; // } // // Then the failed expectation EXPECT_TRUE(IsEven(Fib(5))) // will print the message // // Value of: IsEven(Fib(5)) // Actual: false (5 is odd) // Expected: true // // instead of a more opaque // // Value of: IsEven(Fib(5)) // Actual: false // Expected: true // // in case IsEven is a simple Boolean predicate. // // If you expect your predicate to be reused and want to support informative // messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up // about half as often as positive ones in our tests), supply messages for // both success and failure cases: // // testing::AssertionResult IsEven(int n) { // if ((n % 2) == 0) // return testing::AssertionSuccess() << n << " is even"; // else // return testing::AssertionFailure() << n << " is odd"; // } // // Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print // // Value of: IsEven(Fib(6)) // Actual: true (8 is even) // Expected: false // // NB: Predicates that support negative Boolean assertions have reduced // performance in positive ones so be careful not to use them in tests // that have lots (tens of thousands) of positive Boolean assertions. // // To use this class with EXPECT_PRED_FORMAT assertions such as: // // // Verifies that Foo() returns an even number. // EXPECT_PRED_FORMAT1(IsEven, Foo()); // // you need to define: // // testing::AssertionResult IsEven(const char* expr, int n) { // if ((n % 2) == 0) // return testing::AssertionSuccess(); // else // return testing::AssertionFailure() // << "Expected: " << expr << " is even\n Actual: it's " << n; // } // // If Foo() returns 5, you will see the following message: // // Expected: Foo() is even // Actual: it's 5 // class GTEST_API_ AssertionResult { public: // Copy constructor. // Used in EXPECT_TRUE/FALSE(assertion_result). AssertionResult(const AssertionResult& other); // Used in the EXPECT_TRUE/FALSE(bool_expression). explicit AssertionResult(bool success) : success_(success) {} // Returns true iff the assertion succeeded. operator bool() const { return success_; } // NOLINT // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. AssertionResult operator!() const; // Returns the text streamed into this AssertionResult. Test assertions // use it when they fail (i.e., the predicate's outcome doesn't match the // assertion's expectation). When nothing has been streamed into the // object, returns an empty string. const char* message() const { return message_.get() != NULL ? message_->c_str() : ""; } // TODO(vladl@google.com): Remove this after making sure no clients use it. // Deprecated; please use message() instead. const char* failure_message() const { return message(); } // Streams a custom failure message into this object. template AssertionResult& operator<<(const T& value) { AppendMessage(Message() << value); return *this; } // Allows streaming basic output manipulators such as endl or flush into // this object. AssertionResult& operator<<( ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) { AppendMessage(Message() << basic_manipulator); return *this; } private: // Appends the contents of message to message_. void AppendMessage(const Message& a_message) { if (message_.get() == NULL) message_.reset(new ::std::string); message_->append(a_message.GetString().c_str()); } // Stores result of the assertion predicate. bool success_; // Stores the message describing the condition in case the expectation // construct is not satisfied with the predicate's outcome. // Referenced via a pointer to avoid taking too much stack frame space // with test assertions. internal::scoped_ptr< ::std::string> message_; GTEST_DISALLOW_ASSIGN_(AssertionResult); }; // Makes a successful assertion result. GTEST_API_ AssertionResult AssertionSuccess(); // Makes a failed assertion result. GTEST_API_ AssertionResult AssertionFailure(); // Makes a failed assertion result with the given failure message. // Deprecated; use AssertionFailure() << msg. GTEST_API_ AssertionResult AssertionFailure(const Message& msg); // The abstract class that all tests inherit from. // // In Google Test, a unit test program contains one or many TestCases, and // each TestCase contains one or many Tests. // // When you define a test using the TEST macro, you don't need to // explicitly derive from Test - the TEST macro automatically does // this for you. // // The only time you derive from Test is when defining a test fixture // to be used a TEST_F. For example: // // class FooTest : public testing::Test { // protected: // virtual void SetUp() { ... } // virtual void TearDown() { ... } // ... // }; // // TEST_F(FooTest, Bar) { ... } // TEST_F(FooTest, Baz) { ... } // // Test is not copyable. class GTEST_API_ Test { public: friend class TestInfo; // Defines types for pointers to functions that set up and tear down // a test case. typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc; typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc; // The d'tor is virtual as we intend to inherit from Test. virtual ~Test(); // Sets up the stuff shared by all tests in this test case. // // Google Test will call Foo::SetUpTestCase() before running the first // test in test case Foo. Hence a sub-class can define its own // SetUpTestCase() method to shadow the one defined in the super // class. static void SetUpTestCase() {} // Tears down the stuff shared by all tests in this test case. // // Google Test will call Foo::TearDownTestCase() after running the last // test in test case Foo. Hence a sub-class can define its own // TearDownTestCase() method to shadow the one defined in the super // class. static void TearDownTestCase() {} // Returns true iff the current test has a fatal failure. static bool HasFatalFailure(); // Returns true iff the current test has a non-fatal failure. static bool HasNonfatalFailure(); // Returns true iff the current test has a (either fatal or // non-fatal) failure. static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); } // Logs a property for the current test, test case, or for the entire // invocation of the test program when used outside of the context of a // test case. Only the last value for a given key is remembered. These // are public static so they can be called from utility functions that are // not members of the test fixture. Calls to RecordProperty made during // lifespan of the test (from the moment its constructor starts to the // moment its destructor finishes) will be output in XML as attributes of // the element. Properties recorded from fixture's // SetUpTestCase or TearDownTestCase are logged as attributes of the // corresponding element. Calls to RecordProperty made in the // global context (before or after invocation of RUN_ALL_TESTS and from // SetUp/TearDown method of Environment objects registered with Google // Test) will be output as attributes of the element. static void RecordProperty(const std::string& key, const std::string& value); static void RecordProperty(const std::string& key, int value); protected: // Creates a Test object. Test(); // Sets up the test fixture. virtual void SetUp(); // Tears down the test fixture. virtual void TearDown(); private: // Returns true iff the current test has the same fixture class as // the first test in the current test case. static bool HasSameFixtureClass(); // Runs the test after the test fixture has been set up. // // A sub-class must implement this to define the test logic. // // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM. // Instead, use the TEST or TEST_F macro. virtual void TestBody() = 0; // Sets up, executes, and tears down the test. void Run(); // Deletes self. We deliberately pick an unusual name for this // internal method to avoid clashing with names used in user TESTs. void DeleteSelf_() { delete this; } // Uses a GTestFlagSaver to save and restore all Google Test flags. const internal::GTestFlagSaver* const gtest_flag_saver_; // Often a user mis-spells SetUp() as Setup() and spends a long time // wondering why it is never called by Google Test. The declaration of // the following method is solely for catching such an error at // compile time: // // - The return type is deliberately chosen to be not void, so it // will be a conflict if a user declares void Setup() in his test // fixture. // // - This method is private, so it will be another compiler error // if a user calls it from his test fixture. // // DO NOT OVERRIDE THIS FUNCTION. // // If you see an error about overriding the following function or // about it being private, you have mis-spelled SetUp() as Setup(). struct Setup_should_be_spelled_SetUp {}; virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } // We disallow copying Tests. GTEST_DISALLOW_COPY_AND_ASSIGN_(Test); }; typedef internal::TimeInMillis TimeInMillis; // A copyable object representing a user specified test property which can be // output as a key/value string pair. // // Don't inherit from TestProperty as its destructor is not virtual. class TestProperty { public: // C'tor. TestProperty does NOT have a default constructor. // Always use this constructor (with parameters) to create a // TestProperty object. TestProperty(const std::string& a_key, const std::string& a_value) : key_(a_key), value_(a_value) { } // Gets the user supplied key. const char* key() const { return key_.c_str(); } // Gets the user supplied value. const char* value() const { return value_.c_str(); } // Sets a new value, overriding the one supplied in the constructor. void SetValue(const std::string& new_value) { value_ = new_value; } private: // The key supplied by the user. std::string key_; // The value supplied by the user. std::string value_; }; // The result of a single Test. This includes a list of // TestPartResults, a list of TestProperties, a count of how many // death tests there are in the Test, and how much time it took to run // the Test. // // TestResult is not copyable. class GTEST_API_ TestResult { public: // Creates an empty TestResult. TestResult(); // D'tor. Do not inherit from TestResult. ~TestResult(); // Gets the number of all test parts. This is the sum of the number // of successful test parts and the number of failed test parts. int total_part_count() const; // Returns the number of the test properties. int test_property_count() const; // Returns true iff the test passed (i.e. no test part failed). bool Passed() const { return !Failed(); } // Returns true iff the test failed. bool Failed() const; // Returns true iff the test fatally failed. bool HasFatalFailure() const; // Returns true iff the test has a non-fatal failure. bool HasNonfatalFailure() const; // Returns the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } // Returns the i-th test part result among all the results. i can range // from 0 to test_property_count() - 1. If i is not in that range, aborts // the program. const TestPartResult& GetTestPartResult(int i) const; // Returns the i-th test property. i can range from 0 to // test_property_count() - 1. If i is not in that range, aborts the // program. const TestProperty& GetTestProperty(int i) const; private: friend class TestInfo; friend class TestCase; friend class UnitTest; friend class internal::DefaultGlobalTestPartResultReporter; friend class internal::ExecDeathTest; friend class internal::TestResultAccessor; friend class internal::UnitTestImpl; friend class internal::WindowsDeathTest; // Gets the vector of TestPartResults. const std::vector& test_part_results() const { return test_part_results_; } // Gets the vector of TestProperties. const std::vector& test_properties() const { return test_properties_; } // Sets the elapsed time. void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; } // Adds a test property to the list. The property is validated and may add // a non-fatal failure if invalid (e.g., if it conflicts with reserved // key names). If a property is already recorded for the same key, the // value will be updated, rather than storing multiple values for the same // key. xml_element specifies the element for which the property is being // recorded and is used for validation. void RecordProperty(const std::string& xml_element, const TestProperty& test_property); // Adds a failure if the key is a reserved attribute of Google Test // testcase tags. Returns true if the property is valid. // TODO(russr): Validate attribute names are legal and human readable. static bool ValidateTestProperty(const std::string& xml_element, const TestProperty& test_property); // Adds a test part result to the list. void AddTestPartResult(const TestPartResult& test_part_result); // Returns the death test count. int death_test_count() const { return death_test_count_; } // Increments the death test count, returning the new count. int increment_death_test_count() { return ++death_test_count_; } // Clears the test part results. void ClearTestPartResults(); // Clears the object. void Clear(); // Protects mutable state of the property vector and of owned // properties, whose values may be updated. internal::Mutex test_properites_mutex_; // The vector of TestPartResults std::vector test_part_results_; // The vector of TestProperties std::vector test_properties_; // Running count of death tests. int death_test_count_; // The elapsed time, in milliseconds. TimeInMillis elapsed_time_; // We disallow copying TestResult. GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult); }; // class TestResult // A TestInfo object stores the following information about a test: // // Test case name // Test name // Whether the test should be run // A function pointer that creates the test object when invoked // Test result // // The constructor of TestInfo registers itself with the UnitTest // singleton such that the RUN_ALL_TESTS() macro knows which tests to // run. class GTEST_API_ TestInfo { public: // Destructs a TestInfo object. This function is not virtual, so // don't inherit from TestInfo. ~TestInfo(); // Returns the test case name. const char* test_case_name() const { return test_case_name_.c_str(); } // Returns the test name. const char* name() const { return name_.c_str(); } // Returns the name of the parameter type, or NULL if this is not a typed // or a type-parameterized test. const char* type_param() const { if (type_param_.get() != NULL) return type_param_->c_str(); return NULL; } // Returns the text representation of the value parameter, or NULL if this // is not a value-parameterized test. const char* value_param() const { if (value_param_.get() != NULL) return value_param_->c_str(); return NULL; } // Returns true if this test should run, that is if the test is not // disabled (or it is disabled but the also_run_disabled_tests flag has // been specified) and its full name matches the user-specified filter. // // Google Test allows the user to filter the tests by their full names. // The full name of a test Bar in test case Foo is defined as // "Foo.Bar". Only the tests that match the filter will run. // // A filter is a colon-separated list of glob (not regex) patterns, // optionally followed by a '-' and a colon-separated list of // negative patterns (tests to exclude). A test is run if it // matches one of the positive patterns and does not match any of // the negative patterns. // // For example, *A*:Foo.* is a filter that matches any string that // contains the character 'A' or starts with "Foo.". bool should_run() const { return should_run_; } // Returns true iff this test will appear in the XML report. bool is_reportable() const { // For now, the XML report includes all tests matching the filter. // In the future, we may trim tests that are excluded because of // sharding. return matches_filter_; } // Returns the result of the test. const TestResult* result() const { return &result_; } private: #if GTEST_HAS_DEATH_TEST friend class internal::DefaultDeathTestFactory; #endif // GTEST_HAS_DEATH_TEST friend class Test; friend class TestCase; friend class internal::UnitTestImpl; friend class internal::StreamingListenerTest; friend TestInfo* internal::MakeAndRegisterTestInfo( const char* test_case_name, const char* name, const char* type_param, const char* value_param, internal::TypeId fixture_class_id, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc, internal::TestFactoryBase* factory); // Constructs a TestInfo object. The newly constructed instance assumes // ownership of the factory object. TestInfo(const std::string& test_case_name, const std::string& name, const char* a_type_param, // NULL if not a type-parameterized test const char* a_value_param, // NULL if not a value-parameterized test internal::TypeId fixture_class_id, internal::TestFactoryBase* factory); // Increments the number of death tests encountered in this test so // far. int increment_death_test_count() { return result_.increment_death_test_count(); } // Creates the test object, runs it, records its result, and then // deletes it. void Run(); static void ClearTestResult(TestInfo* test_info) { test_info->result_.Clear(); } // These fields are immutable properties of the test. const std::string test_case_name_; // Test case name const std::string name_; // Test name // Name of the parameter type, or NULL if this is not a typed or a // type-parameterized test. const internal::scoped_ptr type_param_; // Text representation of the value parameter, or NULL if this is not a // value-parameterized test. const internal::scoped_ptr value_param_; const internal::TypeId fixture_class_id_; // ID of the test fixture class bool should_run_; // True iff this test should run bool is_disabled_; // True iff this test is disabled bool matches_filter_; // True if this test matches the // user-specified filter. internal::TestFactoryBase* const factory_; // The factory that creates // the test object // This field is mutable and needs to be reset before running the // test for the second time. TestResult result_; GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo); }; // A test case, which consists of a vector of TestInfos. // // TestCase is not copyable. class GTEST_API_ TestCase { public: // Creates a TestCase with the given name. // // TestCase does NOT have a default constructor. Always use this // constructor to create a TestCase object. // // Arguments: // // name: name of the test case // a_type_param: the name of the test's type parameter, or NULL if // this is not a type-parameterized test. // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case TestCase(const char* name, const char* a_type_param, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc); // Destructor of TestCase. virtual ~TestCase(); // Gets the name of the TestCase. const char* name() const { return name_.c_str(); } // Returns the name of the parameter type, or NULL if this is not a // type-parameterized test case. const char* type_param() const { if (type_param_.get() != NULL) return type_param_->c_str(); return NULL; } // Returns true if any test in this test case should run. bool should_run() const { return should_run_; } // Gets the number of successful tests in this test case. int successful_test_count() const; // Gets the number of failed tests in this test case. int failed_test_count() const; // Gets the number of disabled tests that will be reported in the XML report. int reportable_disabled_test_count() const; // Gets the number of disabled tests in this test case. int disabled_test_count() const; // Gets the number of tests to be printed in the XML report. int reportable_test_count() const; // Get the number of tests in this test case that should run. int test_to_run_count() const; // Gets the number of all tests in this test case. int total_test_count() const; // Returns true iff the test case passed. bool Passed() const { return !Failed(); } // Returns true iff the test case failed. bool Failed() const { return failed_test_count() > 0; } // Returns the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. const TestInfo* GetTestInfo(int i) const; // Returns the TestResult that holds test properties recorded during // execution of SetUpTestCase and TearDownTestCase. const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; } private: friend class Test; friend class internal::UnitTestImpl; // Gets the (mutable) vector of TestInfos in this TestCase. std::vector& test_info_list() { return test_info_list_; } // Gets the (immutable) vector of TestInfos in this TestCase. const std::vector& test_info_list() const { return test_info_list_; } // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. TestInfo* GetMutableTestInfo(int i); // Sets the should_run member. void set_should_run(bool should) { should_run_ = should; } // Adds a TestInfo to this test case. Will delete the TestInfo upon // destruction of the TestCase object. void AddTestInfo(TestInfo * test_info); // Clears the results of all tests in this test case. void ClearResult(); // Clears the results of all tests in the given test case. static void ClearTestCaseResult(TestCase* test_case) { test_case->ClearResult(); } // Runs every test in this TestCase. void Run(); // Runs SetUpTestCase() for this TestCase. This wrapper is needed // for catching exceptions thrown from SetUpTestCase(). void RunSetUpTestCase() { (*set_up_tc_)(); } // Runs TearDownTestCase() for this TestCase. This wrapper is // needed for catching exceptions thrown from TearDownTestCase(). void RunTearDownTestCase() { (*tear_down_tc_)(); } // Returns true iff test passed. static bool TestPassed(const TestInfo* test_info) { return test_info->should_run() && test_info->result()->Passed(); } // Returns true iff test failed. static bool TestFailed(const TestInfo* test_info) { return test_info->should_run() && test_info->result()->Failed(); } // Returns true iff the test is disabled and will be reported in the XML // report. static bool TestReportableDisabled(const TestInfo* test_info) { return test_info->is_reportable() && test_info->is_disabled_; } // Returns true iff test is disabled. static bool TestDisabled(const TestInfo* test_info) { return test_info->is_disabled_; } // Returns true iff this test will appear in the XML report. static bool TestReportable(const TestInfo* test_info) { return test_info->is_reportable(); } // Returns true if the given test should run. static bool ShouldRunTest(const TestInfo* test_info) { return test_info->should_run(); } // Shuffles the tests in this test case. void ShuffleTests(internal::Random* random); // Restores the test order to before the first shuffle. void UnshuffleTests(); // Name of the test case. std::string name_; // Name of the parameter type, or NULL if this is not a typed or a // type-parameterized test. const internal::scoped_ptr type_param_; // The vector of TestInfos in their original order. It owns the // elements in the vector. std::vector test_info_list_; // Provides a level of indirection for the test list to allow easy // shuffling and restoring the test order. The i-th element in this // vector is the index of the i-th test in the shuffled test list. std::vector test_indices_; // Pointer to the function that sets up the test case. Test::SetUpTestCaseFunc set_up_tc_; // Pointer to the function that tears down the test case. Test::TearDownTestCaseFunc tear_down_tc_; // True iff any test in this test case should run. bool should_run_; // Elapsed time, in milliseconds. TimeInMillis elapsed_time_; // Holds test properties recorded during execution of SetUpTestCase and // TearDownTestCase. TestResult ad_hoc_test_result_; // We disallow copying TestCases. GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase); }; // An Environment object is capable of setting up and tearing down an // environment. The user should subclass this to define his own // environment(s). // // An Environment object does the set-up and tear-down in virtual // methods SetUp() and TearDown() instead of the constructor and the // destructor, as: // // 1. You cannot safely throw from a destructor. This is a problem // as in some cases Google Test is used where exceptions are enabled, and // we may want to implement ASSERT_* using exceptions where they are // available. // 2. You cannot use ASSERT_* directly in a constructor or // destructor. class Environment { public: // The d'tor is virtual as we need to subclass Environment. virtual ~Environment() {} // Override this to define how to set up the environment. virtual void SetUp() {} // Override this to define how to tear down the environment. virtual void TearDown() {} private: // If you see an error about overriding the following function or // about it being private, you have mis-spelled SetUp() as Setup(). struct Setup_should_be_spelled_SetUp {}; virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; } }; // The interface for tracing execution of tests. The methods are organized in // the order the corresponding events are fired. class TestEventListener { public: virtual ~TestEventListener() {} // Fired before any test activity starts. virtual void OnTestProgramStart(const UnitTest& unit_test) = 0; // Fired before each iteration of tests starts. There may be more than // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration // index, starting from 0. virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration) = 0; // Fired before environment set-up for each iteration of tests starts. virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0; // Fired after environment set-up for each iteration of tests ends. virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0; // Fired before the test case starts. virtual void OnTestCaseStart(const TestCase& test_case) = 0; // Fired before the test starts. virtual void OnTestStart(const TestInfo& test_info) = 0; // Fired after a failed assertion or a SUCCEED() invocation. virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0; // Fired after the test ends. virtual void OnTestEnd(const TestInfo& test_info) = 0; // Fired after the test case ends. virtual void OnTestCaseEnd(const TestCase& test_case) = 0; // Fired before environment tear-down for each iteration of tests starts. virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0; // Fired after environment tear-down for each iteration of tests ends. virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0; // Fired after each iteration of tests finishes. virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) = 0; // Fired after all test activities have ended. virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0; }; // The convenience class for users who need to override just one or two // methods and are not concerned that a possible change to a signature of // the methods they override will not be caught during the build. For // comments about each method please see the definition of TestEventListener // above. class EmptyTestEventListener : public TestEventListener { public: virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, int /*iteration*/) {} virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} virtual void OnTestStart(const TestInfo& /*test_info*/) {} virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} virtual void OnTestEnd(const TestInfo& /*test_info*/) {} virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, int /*iteration*/) {} virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} }; // TestEventListeners lets users add listeners to track events in Google Test. class GTEST_API_ TestEventListeners { public: TestEventListeners(); ~TestEventListeners(); // Appends an event listener to the end of the list. Google Test assumes // the ownership of the listener (i.e. it will delete the listener when // the test program finishes). void Append(TestEventListener* listener); // Removes the given event listener from the list and returns it. It then // becomes the caller's responsibility to delete the listener. Returns // NULL if the listener is not found in the list. TestEventListener* Release(TestEventListener* listener); // Returns the standard listener responsible for the default console // output. Can be removed from the listeners list to shut down default // console output. Note that removing this object from the listener list // with Release transfers its ownership to the caller and makes this // function return NULL the next time. TestEventListener* default_result_printer() const { return default_result_printer_; } // Returns the standard listener responsible for the default XML output // controlled by the --gtest_output=xml flag. Can be removed from the // listeners list by users who want to shut down the default XML output // controlled by this flag and substitute it with custom one. Note that // removing this object from the listener list with Release transfers its // ownership to the caller and makes this function return NULL the next // time. TestEventListener* default_xml_generator() const { return default_xml_generator_; } private: friend class TestCase; friend class TestInfo; friend class internal::DefaultGlobalTestPartResultReporter; friend class internal::NoExecDeathTest; friend class internal::TestEventListenersAccessor; friend class internal::UnitTestImpl; // Returns repeater that broadcasts the TestEventListener events to all // subscribers. TestEventListener* repeater(); // Sets the default_result_printer attribute to the provided listener. // The listener is also added to the listener list and previous // default_result_printer is removed from it and deleted. The listener can // also be NULL in which case it will not be added to the list. Does // nothing if the previous and the current listener objects are the same. void SetDefaultResultPrinter(TestEventListener* listener); // Sets the default_xml_generator attribute to the provided listener. The // listener is also added to the listener list and previous // default_xml_generator is removed from it and deleted. The listener can // also be NULL in which case it will not be added to the list. Does // nothing if the previous and the current listener objects are the same. void SetDefaultXmlGenerator(TestEventListener* listener); // Controls whether events will be forwarded by the repeater to the // listeners in the list. bool EventForwardingEnabled() const; void SuppressEventForwarding(); // The actual list of listeners. internal::TestEventRepeater* repeater_; // Listener responsible for the standard result output. TestEventListener* default_result_printer_; // Listener responsible for the creation of the XML output file. TestEventListener* default_xml_generator_; // We disallow copying TestEventListeners. GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners); }; // A UnitTest consists of a vector of TestCases. // // This is a singleton class. The only instance of UnitTest is // created when UnitTest::GetInstance() is first called. This // instance is never deleted. // // UnitTest is not copyable. // // This class is thread-safe as long as the methods are called // according to their specification. class GTEST_API_ UnitTest { public: // Gets the singleton UnitTest object. The first time this method // is called, a UnitTest object is constructed and returned. // Consecutive calls will return the same object. static UnitTest* GetInstance(); // Runs all tests in this UnitTest object and prints the result. // Returns 0 if successful, or 1 otherwise. // // This method can only be called from the main thread. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. int Run() GTEST_MUST_USE_RESULT_; // Returns the working directory when the first TEST() or TEST_F() // was executed. The UnitTest object owns the string. const char* original_working_dir() const; // Returns the TestCase object for the test that's currently running, // or NULL if no test is running. const TestCase* current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_); // Returns the TestInfo object for the test that's currently running, // or NULL if no test is running. const TestInfo* current_test_info() const GTEST_LOCK_EXCLUDED_(mutex_); // Returns the random seed used at the start of the current test run. int random_seed() const; #if GTEST_HAS_PARAM_TEST // Returns the ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. internal::ParameterizedTestCaseRegistry& parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_); #endif // GTEST_HAS_PARAM_TEST // Gets the number of successful test cases. int successful_test_case_count() const; // Gets the number of failed test cases. int failed_test_case_count() const; // Gets the number of all test cases. int total_test_case_count() const; // Gets the number of all test cases that contain at least one test // that should run. int test_case_to_run_count() const; // Gets the number of successful tests. int successful_test_count() const; // Gets the number of failed tests. int failed_test_count() const; // Gets the number of disabled tests that will be reported in the XML report. int reportable_disabled_test_count() const; // Gets the number of disabled tests. int disabled_test_count() const; // Gets the number of tests to be printed in the XML report. int reportable_test_count() const; // Gets the number of all tests. int total_test_count() const; // Gets the number of tests that should run. int test_to_run_count() const; // Gets the time of the test program start, in ms from the start of the // UNIX epoch. TimeInMillis start_timestamp() const; // Gets the elapsed time, in milliseconds. TimeInMillis elapsed_time() const; // Returns true iff the unit test passed (i.e. all test cases passed). bool Passed() const; // Returns true iff the unit test failed (i.e. some test case failed // or something outside of all tests failed). bool Failed() const; // Gets the i-th test case among all the test cases. i can range from 0 to // total_test_case_count() - 1. If i is not in that range, returns NULL. const TestCase* GetTestCase(int i) const; // Returns the TestResult containing information on test failures and // properties logged outside of individual test cases. const TestResult& ad_hoc_test_result() const; // Returns the list of event listeners that can be used to track events // inside Google Test. TestEventListeners& listeners(); private: // Registers and returns a global test environment. When a test // program is run, all global test environments will be set-up in // the order they were registered. After all tests in the program // have finished, all global test environments will be torn-down in // the *reverse* order they were registered. // // The UnitTest object takes ownership of the given environment. // // This method can only be called from the main thread. Environment* AddEnvironment(Environment* env); // Adds a TestPartResult to the current TestResult object. All // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) // eventually call this to report their results. The user code // should use the assertion macros instead of calling this directly. void AddTestPartResult(TestPartResult::Type result_type, const char* file_name, int line_number, const std::string& message, const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_); // Adds a TestProperty to the current TestResult object when invoked from // inside a test, to current TestCase's ad_hoc_test_result_ when invoked // from SetUpTestCase or TearDownTestCase, or to the global property set // when invoked elsewhere. If the result already contains a property with // the same key, the value will be updated. void RecordProperty(const std::string& key, const std::string& value); // Gets the i-th test case among all the test cases. i can range from 0 to // total_test_case_count() - 1. If i is not in that range, returns NULL. TestCase* GetMutableTestCase(int i); // Accessors for the implementation object. internal::UnitTestImpl* impl() { return impl_; } const internal::UnitTestImpl* impl() const { return impl_; } // These classes and funcions are friends as they need to access private // members of UnitTest. friend class Test; friend class internal::AssertHelper; friend class internal::ScopedTrace; friend class internal::StreamingListenerTest; friend class internal::UnitTestRecordPropertyTestHelper; friend Environment* AddGlobalTestEnvironment(Environment* env); friend internal::UnitTestImpl* internal::GetUnitTestImpl(); friend void internal::ReportFailureInUnknownLocation( TestPartResult::Type result_type, const std::string& message); // Creates an empty UnitTest. UnitTest(); // D'tor virtual ~UnitTest(); // Pushes a trace defined by SCOPED_TRACE() on to the per-thread // Google Test trace stack. void PushGTestTrace(const internal::TraceInfo& trace) GTEST_LOCK_EXCLUDED_(mutex_); // Pops a trace from the per-thread Google Test trace stack. void PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_); // Protects mutable state in *impl_. This is mutable as some const // methods need to lock it too. mutable internal::Mutex mutex_; // Opaque implementation object. This field is never changed once // the object is constructed. We don't mark it as const here, as // doing so will cause a warning in the constructor of UnitTest. // Mutable state in *impl_ is protected by mutex_. internal::UnitTestImpl* impl_; // We disallow copying UnitTest. GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest); }; // A convenient wrapper for adding an environment for the test // program. // // You should call this before RUN_ALL_TESTS() is called, probably in // main(). If you use gtest_main, you need to call this before main() // starts for it to take effect. For example, you can define a global // variable like this: // // testing::Environment* const foo_env = // testing::AddGlobalTestEnvironment(new FooEnvironment); // // However, we strongly recommend you to write your own main() and // call AddGlobalTestEnvironment() there, as relying on initialization // of global variables makes the code harder to read and may cause // problems when you register multiple environments from different // translation units and the environments have dependencies among them // (remember that the compiler doesn't guarantee the order in which // global variables from different translation units are initialized). inline Environment* AddGlobalTestEnvironment(Environment* env) { return UnitTest::GetInstance()->AddEnvironment(env); } // Initializes Google Test. This must be called before calling // RUN_ALL_TESTS(). In particular, it parses a command line for the // flags that Google Test recognizes. Whenever a Google Test flag is // seen, it is removed from argv, and *argc is decremented. // // No value is returned. Instead, the Google Test flag variables are // updated. // // Calling the function for the second time has no user-visible effect. GTEST_API_ void InitGoogleTest(int* argc, char** argv); // This overloaded version can be used in Windows programs compiled in // UNICODE mode. GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); namespace internal { // FormatForComparison::Format(value) formats a // value of type ToPrint that is an operand of a comparison assertion // (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in // the comparison, and is used to help determine the best way to // format the value. In particular, when the value is a C string // (char pointer) and the other operand is an STL string object, we // want to format the C string as a string, since we know it is // compared by value with the string object. If the value is a char // pointer but the other operand is not an STL string object, we don't // know whether the pointer is supposed to point to a NUL-terminated // string, and thus want to print it as a pointer to be safe. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // The default case. template class FormatForComparison { public: static ::std::string Format(const ToPrint& value) { return ::testing::PrintToString(value); } }; // Array. template class FormatForComparison { public: static ::std::string Format(const ToPrint* value) { return FormatForComparison::Format(value); } }; // By default, print C string as pointers to be safe, as we don't know // whether they actually point to a NUL-terminated string. #define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \ template \ class FormatForComparison { \ public: \ static ::std::string Format(CharType* value) { \ return ::testing::PrintToString(static_cast(value)); \ } \ } GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); #undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ // If a C string is compared with an STL string object, we know it's meant // to point to a NUL-terminated string, and thus can print it as a string. #define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ template <> \ class FormatForComparison { \ public: \ static ::std::string Format(CharType* value) { \ return ::testing::PrintToString(value); \ } \ } GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); #if GTEST_HAS_GLOBAL_STRING GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string); #endif #if GTEST_HAS_GLOBAL_WSTRING GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring); #endif #if GTEST_HAS_STD_WSTRING GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); #endif #undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_ // Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) // operand to be used in a failure message. The type (but not value) // of the other operand may affect the format. This allows us to // print a char* as a raw pointer when it is compared against another // char* or void*, and print it as a C string when it is compared // against an std::string object, for example. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. template std::string FormatForComparisonFailureMessage( const T1& value, const T2& /* other_operand */) { return FormatForComparison::Format(value); } // The helper function for {ASSERT|EXPECT}_EQ. template AssertionResult CmpHelperEQ(const char* expected_expression, const char* actual_expression, const T1& expected, const T2& actual) { #ifdef _MSC_VER # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4389) // Temporarily disables warning on // signed/unsigned mismatch. #endif if (expected == actual) { return AssertionSuccess(); } #ifdef _MSC_VER # pragma warning(pop) // Restores the warning state. #endif return EqFailure(expected_expression, actual_expression, FormatForComparisonFailureMessage(expected, actual), FormatForComparisonFailureMessage(actual, expected), false); } // With this overloaded version, we allow anonymous enums to be used // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums // can be implicitly cast to BiggestInt. GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression, const char* actual_expression, BiggestInt expected, BiggestInt actual); // The helper class for {ASSERT|EXPECT}_EQ. The template argument // lhs_is_null_literal is true iff the first argument to ASSERT_EQ() // is a null pointer literal. The following default implementation is // for lhs_is_null_literal being false. template class EqHelper { public: // This templatized version is for the general case. template static AssertionResult Compare(const char* expected_expression, const char* actual_expression, const T1& expected, const T2& actual) { return CmpHelperEQ(expected_expression, actual_expression, expected, actual); } // With this overloaded version, we allow anonymous enums to be used // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous // enums can be implicitly cast to BiggestInt. // // Even though its body looks the same as the above version, we // cannot merge the two, as it will make anonymous enums unhappy. static AssertionResult Compare(const char* expected_expression, const char* actual_expression, BiggestInt expected, BiggestInt actual) { return CmpHelperEQ(expected_expression, actual_expression, expected, actual); } }; // This specialization is used when the first argument to ASSERT_EQ() // is a null pointer literal, like NULL, false, or 0. template <> class EqHelper { public: // We define two overloaded versions of Compare(). The first // version will be picked when the second argument to ASSERT_EQ() is // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or // EXPECT_EQ(false, a_bool). template static AssertionResult Compare( const char* expected_expression, const char* actual_expression, const T1& expected, const T2& actual, // The following line prevents this overload from being considered if T2 // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr) // expands to Compare("", "", NULL, my_ptr), which requires a conversion // to match the Secret* in the other overload, which would otherwise make // this template match better. typename EnableIf::value>::type* = 0) { return CmpHelperEQ(expected_expression, actual_expression, expected, actual); } // This version will be picked when the second argument to ASSERT_EQ() is a // pointer, e.g. ASSERT_EQ(NULL, a_pointer). template static AssertionResult Compare( const char* expected_expression, const char* actual_expression, // We used to have a second template parameter instead of Secret*. That // template parameter would deduce to 'long', making this a better match // than the first overload even without the first overload's EnableIf. // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to // non-pointer argument" (even a deduced integral argument), so the old // implementation caused warnings in user code. Secret* /* expected (NULL) */, T* actual) { // We already know that 'expected' is a null pointer. return CmpHelperEQ(expected_expression, actual_expression, static_cast(NULL), actual); } }; // A macro for implementing the helper functions needed to implement // ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste // of similar code. // // For each templatized helper function, we also define an overloaded // version for BiggestInt in order to reduce code bloat and allow // anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled // with gcc 4. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. #define GTEST_IMPL_CMP_HELPER_(op_name, op)\ template \ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ const T1& val1, const T2& val2) {\ if (val1 op val2) {\ return AssertionSuccess();\ } else {\ return AssertionFailure() \ << "Expected: (" << expr1 << ") " #op " (" << expr2\ << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ << " vs " << FormatForComparisonFailureMessage(val2, val1);\ }\ }\ GTEST_API_ AssertionResult CmpHelper##op_name(\ const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // Implements the helper function for {ASSERT|EXPECT}_NE GTEST_IMPL_CMP_HELPER_(NE, !=); // Implements the helper function for {ASSERT|EXPECT}_LE GTEST_IMPL_CMP_HELPER_(LE, <=); // Implements the helper function for {ASSERT|EXPECT}_LT GTEST_IMPL_CMP_HELPER_(LT, <); // Implements the helper function for {ASSERT|EXPECT}_GE GTEST_IMPL_CMP_HELPER_(GE, >=); // Implements the helper function for {ASSERT|EXPECT}_GT GTEST_IMPL_CMP_HELPER_(GT, >); #undef GTEST_IMPL_CMP_HELPER_ // The helper function for {ASSERT|EXPECT}_STREQ. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, const char* actual_expression, const char* expected, const char* actual); // The helper function for {ASSERT|EXPECT}_STRCASEEQ. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, const char* actual_expression, const char* expected, const char* actual); // The helper function for {ASSERT|EXPECT}_STRNE. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, const char* s2_expression, const char* s1, const char* s2); // The helper function for {ASSERT|EXPECT}_STRCASENE. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression, const char* s2_expression, const char* s1, const char* s2); // Helper function for *_STREQ on wide strings. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression, const char* actual_expression, const wchar_t* expected, const wchar_t* actual); // Helper function for *_STRNE on wide strings. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression, const char* s2_expression, const wchar_t* s1, const wchar_t* s2); } // namespace internal // IsSubstring() and IsNotSubstring() are intended to be used as the // first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by // themselves. They check whether needle is a substring of haystack // (NULL is considered a substring of itself only), and return an // appropriate error message when they fail. // // The {needle,haystack}_expr arguments are the stringified // expressions that generated the two real arguments. GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const char* needle, const char* haystack); GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const wchar_t* needle, const wchar_t* haystack); GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const char* needle, const char* haystack); GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const wchar_t* needle, const wchar_t* haystack); GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack); GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack); #if GTEST_HAS_STD_WSTRING GTEST_API_ AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::wstring& needle, const ::std::wstring& haystack); GTEST_API_ AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const ::std::wstring& needle, const ::std::wstring& haystack); #endif // GTEST_HAS_STD_WSTRING namespace internal { // Helper template function for comparing floating-points. // // Template parameter: // // RawType: the raw floating-point type (either float or double) // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. template AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression, const char* actual_expression, RawType expected, RawType actual) { const FloatingPoint lhs(expected), rhs(actual); if (lhs.AlmostEquals(rhs)) { return AssertionSuccess(); } ::std::stringstream expected_ss; expected_ss << std::setprecision(std::numeric_limits::digits10 + 2) << expected; ::std::stringstream actual_ss; actual_ss << std::setprecision(std::numeric_limits::digits10 + 2) << actual; return EqFailure(expected_expression, actual_expression, StringStreamToString(&expected_ss), StringStreamToString(&actual_ss), false); } // Helper function for implementing ASSERT_NEAR. // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2, const char* abs_error_expr, double val1, double val2, double abs_error); // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // A class that enables one to stream messages to assertion macros class GTEST_API_ AssertHelper { public: // Constructor. AssertHelper(TestPartResult::Type type, const char* file, int line, const char* message); ~AssertHelper(); // Message assignment is a semantic trick to enable assertion // streaming; see the GTEST_MESSAGE_ macro below. void operator=(const Message& message) const; private: // We put our data in a struct so that the size of the AssertHelper class can // be as small as possible. This is important because gcc is incapable of // re-using stack space even for temporary variables, so every EXPECT_EQ // reserves stack space for another AssertHelper. struct AssertHelperData { AssertHelperData(TestPartResult::Type t, const char* srcfile, int line_num, const char* msg) : type(t), file(srcfile), line(line_num), message(msg) { } TestPartResult::Type const type; const char* const file; int const line; std::string const message; private: GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData); }; AssertHelperData* const data_; GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); }; } // namespace internal #if GTEST_HAS_PARAM_TEST // The pure interface class that all value-parameterized tests inherit from. // A value-parameterized class must inherit from both ::testing::Test and // ::testing::WithParamInterface. In most cases that just means inheriting // from ::testing::TestWithParam, but more complicated test hierarchies // may need to inherit from Test and WithParamInterface at different levels. // // This interface has support for accessing the test parameter value via // the GetParam() method. // // Use it with one of the parameter generator defining functions, like Range(), // Values(), ValuesIn(), Bool(), and Combine(). // // class FooTest : public ::testing::TestWithParam { // protected: // FooTest() { // // Can use GetParam() here. // } // virtual ~FooTest() { // // Can use GetParam() here. // } // virtual void SetUp() { // // Can use GetParam() here. // } // virtual void TearDown { // // Can use GetParam() here. // } // }; // TEST_P(FooTest, DoesBar) { // // Can use GetParam() method here. // Foo foo; // ASSERT_TRUE(foo.DoesBar(GetParam())); // } // INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10)); template class WithParamInterface { public: typedef T ParamType; virtual ~WithParamInterface() {} // The current parameter value. Is also available in the test fixture's // constructor. This member function is non-static, even though it only // references static data, to reduce the opportunity for incorrect uses // like writing 'WithParamInterface::GetParam()' for a test that // uses a fixture whose parameter type is int. const ParamType& GetParam() const { GTEST_CHECK_(parameter_ != NULL) << "GetParam() can only be called inside a value-parameterized test " << "-- did you intend to write TEST_P instead of TEST_F?"; return *parameter_; } private: // Sets parameter value. The caller is responsible for making sure the value // remains alive and unchanged throughout the current test. static void SetParam(const ParamType* parameter) { parameter_ = parameter; } // Static value used for accessing parameter during a test lifetime. static const ParamType* parameter_; // TestClass must be a subclass of WithParamInterface and Test. template friend class internal::ParameterizedTestFactory; }; template const T* WithParamInterface::parameter_ = NULL; // Most value-parameterized classes can ignore the existence of // WithParamInterface, and can just inherit from ::testing::TestWithParam. template class TestWithParam : public Test, public WithParamInterface { }; #endif // GTEST_HAS_PARAM_TEST // Macros for indicating success/failure in test code. // ADD_FAILURE unconditionally adds a failure to the current test. // SUCCEED generates a success - it doesn't automatically make the // current test successful, as a test is only successful when it has // no failure. // // EXPECT_* verifies that a certain condition is satisfied. If not, // it behaves like ADD_FAILURE. In particular: // // EXPECT_TRUE verifies that a Boolean condition is true. // EXPECT_FALSE verifies that a Boolean condition is false. // // FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except // that they will also abort the current function on failure. People // usually want the fail-fast behavior of FAIL and ASSERT_*, but those // writing data-driven tests often find themselves using ADD_FAILURE // and EXPECT_* more. // Generates a nonfatal failure with a generic message. #define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed") // Generates a nonfatal failure at the given source file location with // a generic message. #define ADD_FAILURE_AT(file, line) \ GTEST_MESSAGE_AT_(file, line, "Failed", \ ::testing::TestPartResult::kNonFatalFailure) // Generates a fatal failure with a generic message. #define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed") // Define this macro to 1 to omit the definition of FAIL(), which is a // generic name and clashes with some other libraries. #if !GTEST_DONT_DEFINE_FAIL # define FAIL() GTEST_FAIL() #endif // Generates a success with a generic message. #define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded") // Define this macro to 1 to omit the definition of SUCCEED(), which // is a generic name and clashes with some other libraries. #if !GTEST_DONT_DEFINE_SUCCEED # define SUCCEED() GTEST_SUCCEED() #endif // Macros for testing exceptions. // // * {ASSERT|EXPECT}_THROW(statement, expected_exception): // Tests that the statement throws the expected exception. // * {ASSERT|EXPECT}_NO_THROW(statement): // Tests that the statement doesn't throw any exception. // * {ASSERT|EXPECT}_ANY_THROW(statement): // Tests that the statement throws an exception. #define EXPECT_THROW(statement, expected_exception) \ GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_) #define EXPECT_NO_THROW(statement) \ GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_) #define EXPECT_ANY_THROW(statement) \ GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_) #define ASSERT_THROW(statement, expected_exception) \ GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_) #define ASSERT_NO_THROW(statement) \ GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_) #define ASSERT_ANY_THROW(statement) \ GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_) // Boolean assertions. Condition can be either a Boolean expression or an // AssertionResult. For more information on how to use AssertionResult with // these macros see comments on that class. #define EXPECT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_NONFATAL_FAILURE_) #define EXPECT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_NONFATAL_FAILURE_) #define ASSERT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_FATAL_FAILURE_) #define ASSERT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_FATAL_FAILURE_) // Includes the auto-generated header that implements a family of // generic predicate assertion macros. // Copyright 2006, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // This file is AUTOMATICALLY GENERATED on 10/31/2011 by command // 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND! // // Implements a family of generic predicate assertion macros. #ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ // Makes sure this header is not included before gtest.h. #ifndef GTEST_INCLUDE_GTEST_GTEST_H_ # error Do not include gtest_pred_impl.h directly. Include gtest.h instead. #endif // GTEST_INCLUDE_GTEST_GTEST_H_ // This header implements a family of generic predicate assertion // macros: // // ASSERT_PRED_FORMAT1(pred_format, v1) // ASSERT_PRED_FORMAT2(pred_format, v1, v2) // ... // // where pred_format is a function or functor that takes n (in the // case of ASSERT_PRED_FORMATn) values and their source expression // text, and returns a testing::AssertionResult. See the definition // of ASSERT_EQ in gtest.h for an example. // // If you don't care about formatting, you can use the more // restrictive version: // // ASSERT_PRED1(pred, v1) // ASSERT_PRED2(pred, v1, v2) // ... // // where pred is an n-ary function or functor that returns bool, // and the values v1, v2, ..., must support the << operator for // streaming to std::ostream. // // We also define the EXPECT_* variations. // // For now we only support predicates whose arity is at most 5. // Please email googletestframework@googlegroups.com if you need // support for higher arities. // GTEST_ASSERT_ is the basic statement to which all of the assertions // in this file reduce. Don't use this in your code. #define GTEST_ASSERT_(expression, on_failure) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const ::testing::AssertionResult gtest_ar = (expression)) \ ; \ else \ on_failure(gtest_ar.failure_message()) // Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use // this in your code. template AssertionResult AssertPred1Helper(const char* pred_text, const char* e1, Pred pred, const T1& v1) { if (pred(v1)) return AssertionSuccess(); return AssertionFailure() << pred_text << "(" << e1 << ") evaluates to false, where" << "\n" << e1 << " evaluates to " << v1; } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1. // Don't use this in your code. #define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\ GTEST_ASSERT_(pred_format(#v1, v1), \ on_failure) // Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use // this in your code. #define GTEST_PRED1_(pred, v1, on_failure)\ GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \ #v1, \ pred, \ v1), on_failure) // Unary predicate assertion macros. #define EXPECT_PRED_FORMAT1(pred_format, v1) \ GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_) #define EXPECT_PRED1(pred, v1) \ GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_) #define ASSERT_PRED_FORMAT1(pred_format, v1) \ GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_) #define ASSERT_PRED1(pred, v1) \ GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_) // Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use // this in your code. template AssertionResult AssertPred2Helper(const char* pred_text, const char* e1, const char* e2, Pred pred, const T1& v1, const T2& v2) { if (pred(v1, v2)) return AssertionSuccess(); return AssertionFailure() << pred_text << "(" << e1 << ", " << e2 << ") evaluates to false, where" << "\n" << e1 << " evaluates to " << v1 << "\n" << e2 << " evaluates to " << v2; } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2. // Don't use this in your code. #define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\ GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \ on_failure) // Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use // this in your code. #define GTEST_PRED2_(pred, v1, v2, on_failure)\ GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \ #v1, \ #v2, \ pred, \ v1, \ v2), on_failure) // Binary predicate assertion macros. #define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \ GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_) #define EXPECT_PRED2(pred, v1, v2) \ GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_) #define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \ GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_) #define ASSERT_PRED2(pred, v1, v2) \ GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_) // Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use // this in your code. template AssertionResult AssertPred3Helper(const char* pred_text, const char* e1, const char* e2, const char* e3, Pred pred, const T1& v1, const T2& v2, const T3& v3) { if (pred(v1, v2, v3)) return AssertionSuccess(); return AssertionFailure() << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ") evaluates to false, where" << "\n" << e1 << " evaluates to " << v1 << "\n" << e2 << " evaluates to " << v2 << "\n" << e3 << " evaluates to " << v3; } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3. // Don't use this in your code. #define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \ on_failure) // Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use // this in your code. #define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\ GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \ #v1, \ #v2, \ #v3, \ pred, \ v1, \ v2, \ v3), on_failure) // Ternary predicate assertion macros. #define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \ GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_) #define EXPECT_PRED3(pred, v1, v2, v3) \ GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_) #define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \ GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_) #define ASSERT_PRED3(pred, v1, v2, v3) \ GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_) // Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use // this in your code. template AssertionResult AssertPred4Helper(const char* pred_text, const char* e1, const char* e2, const char* e3, const char* e4, Pred pred, const T1& v1, const T2& v2, const T3& v3, const T4& v4) { if (pred(v1, v2, v3, v4)) return AssertionSuccess(); return AssertionFailure() << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4 << ") evaluates to false, where" << "\n" << e1 << " evaluates to " << v1 << "\n" << e2 << " evaluates to " << v2 << "\n" << e3 << " evaluates to " << v3 << "\n" << e4 << " evaluates to " << v4; } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4. // Don't use this in your code. #define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \ on_failure) // Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use // this in your code. #define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\ GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \ #v1, \ #v2, \ #v3, \ #v4, \ pred, \ v1, \ v2, \ v3, \ v4), on_failure) // 4-ary predicate assertion macros. #define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) #define EXPECT_PRED4(pred, v1, v2, v3, v4) \ GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_) #define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \ GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) #define ASSERT_PRED4(pred, v1, v2, v3, v4) \ GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_) // Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use // this in your code. template AssertionResult AssertPred5Helper(const char* pred_text, const char* e1, const char* e2, const char* e3, const char* e4, const char* e5, Pred pred, const T1& v1, const T2& v2, const T3& v3, const T4& v4, const T5& v5) { if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess(); return AssertionFailure() << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4 << ", " << e5 << ") evaluates to false, where" << "\n" << e1 << " evaluates to " << v1 << "\n" << e2 << " evaluates to " << v2 << "\n" << e3 << " evaluates to " << v3 << "\n" << e4 << " evaluates to " << v4 << "\n" << e5 << " evaluates to " << v5; } // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5. // Don't use this in your code. #define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\ GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \ on_failure) // Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use // this in your code. #define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\ GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \ #v1, \ #v2, \ #v3, \ #v4, \ #v5, \ pred, \ v1, \ v2, \ v3, \ v4, \ v5), on_failure) // 5-ary predicate assertion macros. #define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) #define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \ GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_) #define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \ GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) #define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \ GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_) #endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ // Macros for testing equalities and inequalities. // // * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual // * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2 // * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2 // * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2 // * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2 // * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2 // // When they are not, Google Test prints both the tested expressions and // their actual values. The values must be compatible built-in types, // or you will get a compiler error. By "compatible" we mean that the // values can be compared by the respective operator. // // Note: // // 1. It is possible to make a user-defined type work with // {ASSERT|EXPECT}_??(), but that requires overloading the // comparison operators and is thus discouraged by the Google C++ // Usage Guide. Therefore, you are advised to use the // {ASSERT|EXPECT}_TRUE() macro to assert that two objects are // equal. // // 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on // pointers (in particular, C strings). Therefore, if you use it // with two C strings, you are testing how their locations in memory // are related, not how their content is related. To compare two C // strings by content, use {ASSERT|EXPECT}_STR*(). // // 3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to // {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you // what the actual value is when it fails, and similarly for the // other comparisons. // // 4. Do not depend on the order in which {ASSERT|EXPECT}_??() // evaluate their arguments, which is undefined. // // 5. These macros evaluate their arguments exactly once. // // Examples: // // EXPECT_NE(5, Foo()); // EXPECT_EQ(NULL, a_pointer); // ASSERT_LT(i, array_size); // ASSERT_GT(records.size(), 0) << "There is no record left."; #define EXPECT_EQ(expected, actual) \ EXPECT_PRED_FORMAT2(::testing::internal:: \ EqHelper::Compare, \ expected, actual) #define EXPECT_NE(expected, actual) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual) #define EXPECT_LE(val1, val2) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) #define EXPECT_LT(val1, val2) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) #define EXPECT_GE(val1, val2) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) #define EXPECT_GT(val1, val2) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) #define GTEST_ASSERT_EQ(expected, actual) \ ASSERT_PRED_FORMAT2(::testing::internal:: \ EqHelper::Compare, \ expected, actual) #define GTEST_ASSERT_NE(val1, val2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2) #define GTEST_ASSERT_LE(val1, val2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2) #define GTEST_ASSERT_LT(val1, val2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2) #define GTEST_ASSERT_GE(val1, val2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2) #define GTEST_ASSERT_GT(val1, val2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2) // Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of // ASSERT_XY(), which clashes with some users' own code. #if !GTEST_DONT_DEFINE_ASSERT_EQ # define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2) #endif #if !GTEST_DONT_DEFINE_ASSERT_NE # define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2) #endif #if !GTEST_DONT_DEFINE_ASSERT_LE # define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2) #endif #if !GTEST_DONT_DEFINE_ASSERT_LT # define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2) #endif #if !GTEST_DONT_DEFINE_ASSERT_GE # define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2) #endif #if !GTEST_DONT_DEFINE_ASSERT_GT # define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2) #endif // C-string Comparisons. All tests treat NULL and any non-NULL string // as different. Two NULLs are equal. // // * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2 // * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2 // * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case // * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case // // For wide or narrow string objects, you can use the // {ASSERT|EXPECT}_??() macros. // // Don't depend on the order in which the arguments are evaluated, // which is undefined. // // These macros evaluate their arguments exactly once. #define EXPECT_STREQ(expected, actual) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) #define EXPECT_STRNE(s1, s2) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) #define EXPECT_STRCASEEQ(expected, actual) \ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) #define EXPECT_STRCASENE(s1, s2)\ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) #define ASSERT_STREQ(expected, actual) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual) #define ASSERT_STRNE(s1, s2) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2) #define ASSERT_STRCASEEQ(expected, actual) \ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual) #define ASSERT_STRCASENE(s1, s2)\ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2) // Macros for comparing floating-point numbers. // // * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual): // Tests that two float values are almost equal. // * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual): // Tests that two double values are almost equal. // * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error): // Tests that v1 and v2 are within the given distance to each other. // // Google Test uses ULP-based comparison to automatically pick a default // error bound that is appropriate for the operands. See the // FloatingPoint template class in gtest-internal.h if you are // interested in the implementation details. #define EXPECT_FLOAT_EQ(expected, actual)\ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ expected, actual) #define EXPECT_DOUBLE_EQ(expected, actual)\ EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ expected, actual) #define ASSERT_FLOAT_EQ(expected, actual)\ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ expected, actual) #define ASSERT_DOUBLE_EQ(expected, actual)\ ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ, \ expected, actual) #define EXPECT_NEAR(val1, val2, abs_error)\ EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ val1, val2, abs_error) #define ASSERT_NEAR(val1, val2, abs_error)\ ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \ val1, val2, abs_error) // These predicate format functions work on floating-point values, and // can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g. // // EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0); // Asserts that val1 is less than, or almost equal to, val2. Fails // otherwise. In particular, it fails if either val1 or val2 is NaN. GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2, float val1, float val2); GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2, double val1, double val2); #if GTEST_OS_WINDOWS // Macros that test for HRESULT failure and success, these are only useful // on Windows, and rely on Windows SDK macros and APIs to compile. // // * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr) // // When expr unexpectedly fails or succeeds, Google Test prints the // expected result and the actual result with both a human-readable // string representation of the error, if available, as well as the // hex result code. # define EXPECT_HRESULT_SUCCEEDED(expr) \ EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) # define ASSERT_HRESULT_SUCCEEDED(expr) \ ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr)) # define EXPECT_HRESULT_FAILED(expr) \ EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) # define ASSERT_HRESULT_FAILED(expr) \ ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr)) #endif // GTEST_OS_WINDOWS // Macros that execute statement and check that it doesn't generate new fatal // failures in the current thread. // // * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement); // // Examples: // // EXPECT_NO_FATAL_FAILURE(Process()); // ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed"; // #define ASSERT_NO_FATAL_FAILURE(statement) \ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_) #define EXPECT_NO_FATAL_FAILURE(statement) \ GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_) // Causes a trace (including the source file path, the current line // number, and the given message) to be included in every test failure // message generated by code in the current scope. The effect is // undone when the control leaves the current scope. // // The message argument can be anything streamable to std::ostream. // // In the implementation, we include the current line number as part // of the dummy variable name, thus allowing multiple SCOPED_TRACE()s // to appear in the same block - as long as they are on different // lines. #define SCOPED_TRACE(message) \ ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\ __FILE__, __LINE__, ::testing::Message() << (message)) // Compile-time assertion for type equality. // StaticAssertTypeEq() compiles iff type1 and type2 are // the same type. The value it returns is not interesting. // // Instead of making StaticAssertTypeEq a class template, we make it a // function template that invokes a helper class template. This // prevents a user from misusing StaticAssertTypeEq by // defining objects of that type. // // CAVEAT: // // When used inside a method of a class template, // StaticAssertTypeEq() is effective ONLY IF the method is // instantiated. For example, given: // // template class Foo { // public: // void Bar() { testing::StaticAssertTypeEq(); } // }; // // the code: // // void Test1() { Foo foo; } // // will NOT generate a compiler error, as Foo::Bar() is never // actually instantiated. Instead, you need: // // void Test2() { Foo foo; foo.Bar(); } // // to cause a compiler error. template bool StaticAssertTypeEq() { (void)internal::StaticAssertTypeEqHelper(); return true; } // Defines a test. // // The first parameter is the name of the test case, and the second // parameter is the name of the test within the test case. // // The convention is to end the test case name with "Test". For // example, a test case for the Foo class can be named FooTest. // // The user should put his test code between braces after using this // macro. Example: // // TEST(FooTest, InitializesCorrectly) { // Foo foo; // EXPECT_TRUE(foo.StatusIsOK()); // } // Note that we call GetTestTypeId() instead of GetTypeId< // ::testing::Test>() here to get the type ID of testing::Test. This // is to work around a suspected linker bug when using Google Test as // a framework on Mac OS X. The bug causes GetTypeId< // ::testing::Test>() to return different values depending on whether // the call is from the Google Test framework itself or from user test // code. GetTestTypeId() is guaranteed to always return the same // value, as it always calls GetTypeId<>() from the Google Test // framework. #define GTEST_TEST(test_case_name, test_name)\ GTEST_TEST_(test_case_name, test_name, \ ::testing::Test, ::testing::internal::GetTestTypeId()) // Define this macro to 1 to omit the definition of TEST(), which // is a generic name and clashes with some other libraries. #if !GTEST_DONT_DEFINE_TEST # define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name) #endif // Defines a test that uses a test fixture. // // The first parameter is the name of the test fixture class, which // also doubles as the test case name. The second parameter is the // name of the test within the test case. // // A test fixture class must be declared earlier. The user should put // his test code between braces after using this macro. Example: // // class FooTest : public testing::Test { // protected: // virtual void SetUp() { b_.AddElement(3); } // // Foo a_; // Foo b_; // }; // // TEST_F(FooTest, InitializesCorrectly) { // EXPECT_TRUE(a_.StatusIsOK()); // } // // TEST_F(FooTest, ReturnsElementCountCorrectly) { // EXPECT_EQ(0, a_.size()); // EXPECT_EQ(1, b_.size()); // } #define TEST_F(test_fixture, test_name)\ GTEST_TEST_(test_fixture, test_name, test_fixture, \ ::testing::internal::GetTypeId()) } // namespace testing // Use this function in main() to run all tests. It returns 0 if all // tests are successful, or 1 otherwise. // // RUN_ALL_TESTS() should be invoked after the command line has been // parsed by InitGoogleTest(). // // This function was formerly a macro; thus, it is in the global // namespace and has an all-caps name. int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_; inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); } #endif // GTEST_INCLUDE_GTEST_GTEST_H_ Jellyfish-2.2.8/unit_tests/gtest/src/000077500000000000000000000000001323712541700175775ustar00rootroot00000000000000Jellyfish-2.2.8/unit_tests/gtest/src/gtest-all.cc000066400000000000000000012640701323712541700220140ustar00rootroot00000000000000// Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: mheule@google.com (Markus Heule) // // Google C++ Testing Framework (Google Test) // // Sometimes it's desirable to build Google Test by compiling a single file. // This file serves this purpose. // This line ensures that gtest.h can be compiled on its own, even // when it's fused. #include "gtest/gtest.h" // The following lines pull in the real gtest *.cc files. // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // // The Google C++ Testing Framework (Google Test) // Copyright 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // // Utilities for testing Google Test itself and code that uses Google Test // (e.g. frameworks built on top of Google Test). #ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ #define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ namespace testing { // This helper class can be used to mock out Google Test failure reporting // so that we can test Google Test or code that builds on Google Test. // // An object of this class appends a TestPartResult object to the // TestPartResultArray object given in the constructor whenever a Google Test // failure is reported. It can either intercept only failures that are // generated in the same thread that created this object or it can intercept // all generated failures. The scope of this mock object can be controlled with // the second argument to the two arguments constructor. class GTEST_API_ ScopedFakeTestPartResultReporter : public TestPartResultReporterInterface { public: // The two possible mocking modes of this object. enum InterceptMode { INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures. INTERCEPT_ALL_THREADS // Intercepts all failures. }; // The c'tor sets this object as the test part result reporter used // by Google Test. The 'result' parameter specifies where to report the // results. This reporter will only catch failures generated in the current // thread. DEPRECATED explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result); // Same as above, but you can choose the interception scope of this object. ScopedFakeTestPartResultReporter(InterceptMode intercept_mode, TestPartResultArray* result); // The d'tor restores the previous test part result reporter. virtual ~ScopedFakeTestPartResultReporter(); // Appends the TestPartResult object to the TestPartResultArray // received in the constructor. // // This method is from the TestPartResultReporterInterface // interface. virtual void ReportTestPartResult(const TestPartResult& result); private: void Init(); const InterceptMode intercept_mode_; TestPartResultReporterInterface* old_reporter_; TestPartResultArray* const result_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter); }; namespace internal { // A helper class for implementing EXPECT_FATAL_FAILURE() and // EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given // TestPartResultArray contains exactly one failure that has the given // type and contains the given substring. If that's not the case, a // non-fatal failure will be generated. class GTEST_API_ SingleFailureChecker { public: // The constructor remembers the arguments. SingleFailureChecker(const TestPartResultArray* results, TestPartResult::Type type, const string& substr); ~SingleFailureChecker(); private: const TestPartResultArray* const results_; const TestPartResult::Type type_; const string substr_; GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker); }; } // namespace internal } // namespace testing // A set of macros for testing Google Test assertions or code that's expected // to generate Google Test fatal failures. It verifies that the given // statement will cause exactly one fatal Google Test failure with 'substr' // being part of the failure message. // // There are two different versions of this macro. EXPECT_FATAL_FAILURE only // affects and considers failures generated in the current thread and // EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. // // The verification of the assertion is done correctly even when the statement // throws an exception or aborts the current function. // // Known restrictions: // - 'statement' cannot reference local non-static variables or // non-static members of the current object. // - 'statement' cannot return a value. // - You cannot stream a failure message to this macro. // // Note that even though the implementations of the following two // macros are much alike, we cannot refactor them to use a common // helper macro, due to some peculiarity in how the preprocessor // works. The AcceptsMacroThatExpandsToUnprotectedComma test in // gtest_unittest.cc will fail to compile if we do that. #define EXPECT_FATAL_FAILURE(statement, substr) \ do { \ class GTestExpectFatalFailureHelper {\ public:\ static void Execute() { statement; }\ };\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter:: \ INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ GTestExpectFatalFailureHelper::Execute();\ }\ } while (::testing::internal::AlwaysFalse()) #define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ do { \ class GTestExpectFatalFailureHelper {\ public:\ static void Execute() { statement; }\ };\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter:: \ INTERCEPT_ALL_THREADS, >est_failures);\ GTestExpectFatalFailureHelper::Execute();\ }\ } while (::testing::internal::AlwaysFalse()) // A macro for testing Google Test assertions or code that's expected to // generate Google Test non-fatal failures. It asserts that the given // statement will cause exactly one non-fatal Google Test failure with 'substr' // being part of the failure message. // // There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only // affects and considers failures generated in the current thread and // EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads. // // 'statement' is allowed to reference local variables and members of // the current object. // // The verification of the assertion is done correctly even when the statement // throws an exception or aborts the current function. // // Known restrictions: // - You cannot stream a failure message to this macro. // // Note that even though the implementations of the following two // macros are much alike, we cannot refactor them to use a common // helper macro, due to some peculiarity in how the preprocessor // works. If we do that, the code won't compile when the user gives // EXPECT_NONFATAL_FAILURE() a statement that contains a macro that // expands to code containing an unprotected comma. The // AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc // catches that. // // For the same reason, we have to write // if (::testing::internal::AlwaysTrue()) { statement; } // instead of // GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) // to avoid an MSVC warning on unreachable code. #define EXPECT_NONFATAL_FAILURE(statement, substr) \ do {\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter:: \ INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\ if (::testing::internal::AlwaysTrue()) { statement; }\ }\ } while (::testing::internal::AlwaysFalse()) #define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \ do {\ ::testing::TestPartResultArray gtest_failures;\ ::testing::internal::SingleFailureChecker gtest_checker(\ >est_failures, ::testing::TestPartResult::kNonFatalFailure, \ (substr));\ {\ ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\ ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \ >est_failures);\ if (::testing::internal::AlwaysTrue()) { statement; }\ }\ } while (::testing::internal::AlwaysFalse()) #endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ #include #include #include #include #include #include #include #include #include #include #include #include // NOLINT #include #include #if GTEST_OS_LINUX // TODO(kenton@google.com): Use autoconf to detect availability of // gettimeofday(). # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT # include // NOLINT # include // NOLINT // Declares vsnprintf(). This header is not available on Windows. # include // NOLINT # include // NOLINT # include // NOLINT # include // NOLINT # include #elif GTEST_OS_SYMBIAN # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT #elif GTEST_OS_ZOS # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT // On z/OS we additionally need strings.h for strcasecmp. # include // NOLINT #elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. # include // NOLINT #elif GTEST_OS_WINDOWS // We are on Windows proper. # include // NOLINT # include // NOLINT # include // NOLINT # include // NOLINT # if GTEST_OS_WINDOWS_MINGW // MinGW has gettimeofday() but not _ftime64(). // TODO(kenton@google.com): Use autoconf to detect availability of // gettimeofday(). // TODO(kenton@google.com): There are other ways to get the time on // Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW // supports these. consider using them instead. # define GTEST_HAS_GETTIMEOFDAY_ 1 # include // NOLINT # endif // GTEST_OS_WINDOWS_MINGW // cpplint thinks that the header is already included, so we want to // silence it. # include // NOLINT #else // Assume other platforms have gettimeofday(). // TODO(kenton@google.com): Use autoconf to detect availability of // gettimeofday(). # define GTEST_HAS_GETTIMEOFDAY_ 1 // cpplint thinks that the header is already included, so we want to // silence it. # include // NOLINT # include // NOLINT #endif // GTEST_OS_LINUX #if GTEST_HAS_EXCEPTIONS # include #endif #if GTEST_CAN_STREAM_RESULTS_ # include // NOLINT # include // NOLINT #endif // Indicates that this translation unit is part of Google Test's // implementation. It must come before gtest-internal-inl.h is // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. #define GTEST_IMPLEMENTATION_ 1 // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Utility functions and classes used by the Google C++ testing framework. // // Author: wan@google.com (Zhanyong Wan) // // This file contains purely Google Test's internal implementation. Please // DO NOT #INCLUDE IT IN A USER PROGRAM. #ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_ #define GTEST_SRC_GTEST_INTERNAL_INL_H_ // GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is // part of Google Test's implementation; otherwise it's undefined. #if !GTEST_IMPLEMENTATION_ // A user is trying to include this from his code - just say no. # error "gtest-internal-inl.h is part of Google Test's internal implementation." # error "It must not be included except by Google Test itself." #endif // GTEST_IMPLEMENTATION_ #ifndef _WIN32_WCE # include #endif // !_WIN32_WCE #include #include // For strtoll/_strtoul64/malloc/free. #include // For memmove. #include #include #include #if GTEST_CAN_STREAM_RESULTS_ # include // NOLINT # include // NOLINT #endif #if GTEST_OS_WINDOWS # include // NOLINT #endif // GTEST_OS_WINDOWS namespace testing { // Declares the flags. // // We don't want the users to modify this flag in the code, but want // Google Test's own unit tests to be able to access it. Therefore we // declare it here as opposed to in gtest.h. GTEST_DECLARE_bool_(death_test_use_fork); namespace internal { // The value of GetTestTypeId() as seen from within the Google Test // library. This is solely for testing GetTestTypeId(). GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest; // Names of the flags (needed for parsing Google Test flags). const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests"; const char kBreakOnFailureFlag[] = "break_on_failure"; const char kCatchExceptionsFlag[] = "catch_exceptions"; const char kColorFlag[] = "color"; const char kFilterFlag[] = "filter"; const char kListTestsFlag[] = "list_tests"; const char kOutputFlag[] = "output"; const char kPrintTimeFlag[] = "print_time"; const char kRandomSeedFlag[] = "random_seed"; const char kRepeatFlag[] = "repeat"; const char kShuffleFlag[] = "shuffle"; const char kStackTraceDepthFlag[] = "stack_trace_depth"; const char kStreamResultToFlag[] = "stream_result_to"; const char kThrowOnFailureFlag[] = "throw_on_failure"; // A valid random seed must be in [1, kMaxRandomSeed]. const int kMaxRandomSeed = 99999; // g_help_flag is true iff the --help flag or an equivalent form is // specified on the command line. GTEST_API_ extern bool g_help_flag; // Returns the current time in milliseconds. GTEST_API_ TimeInMillis GetTimeInMillis(); // Returns true iff Google Test should use colors in the output. GTEST_API_ bool ShouldUseColor(bool stdout_is_tty); // Formats the given time in milliseconds as seconds. GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms); // Converts the given time in milliseconds to a date string in the ISO 8601 // format, without the timezone information. N.B.: due to the use the // non-reentrant localtime() function, this function is not thread safe. Do // not use it in any code that can be called from multiple threads. GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms); // Parses a string for an Int32 flag, in the form of "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. GTEST_API_ bool ParseInt32Flag( const char* str, const char* flag, Int32* value); // Returns a random seed in range [1, kMaxRandomSeed] based on the // given --gtest_random_seed flag value. inline int GetRandomSeedFromFlag(Int32 random_seed_flag) { const unsigned int raw_seed = (random_seed_flag == 0) ? static_cast(GetTimeInMillis()) : static_cast(random_seed_flag); // Normalizes the actual seed to range [1, kMaxRandomSeed] such that // it's easy to type. const int normalized_seed = static_cast((raw_seed - 1U) % static_cast(kMaxRandomSeed)) + 1; return normalized_seed; } // Returns the first valid random seed after 'seed'. The behavior is // undefined if 'seed' is invalid. The seed after kMaxRandomSeed is // considered to be 1. inline int GetNextRandomSeed(int seed) { GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed) << "Invalid random seed " << seed << " - must be in [1, " << kMaxRandomSeed << "]."; const int next_seed = seed + 1; return (next_seed > kMaxRandomSeed) ? 1 : next_seed; } // This class saves the values of all Google Test flags in its c'tor, and // restores them in its d'tor. class GTestFlagSaver { public: // The c'tor. GTestFlagSaver() { also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests); break_on_failure_ = GTEST_FLAG(break_on_failure); catch_exceptions_ = GTEST_FLAG(catch_exceptions); color_ = GTEST_FLAG(color); death_test_style_ = GTEST_FLAG(death_test_style); death_test_use_fork_ = GTEST_FLAG(death_test_use_fork); filter_ = GTEST_FLAG(filter); internal_run_death_test_ = GTEST_FLAG(internal_run_death_test); list_tests_ = GTEST_FLAG(list_tests); output_ = GTEST_FLAG(output); print_time_ = GTEST_FLAG(print_time); random_seed_ = GTEST_FLAG(random_seed); repeat_ = GTEST_FLAG(repeat); shuffle_ = GTEST_FLAG(shuffle); stack_trace_depth_ = GTEST_FLAG(stack_trace_depth); stream_result_to_ = GTEST_FLAG(stream_result_to); throw_on_failure_ = GTEST_FLAG(throw_on_failure); } // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS. ~GTestFlagSaver() { GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_; GTEST_FLAG(break_on_failure) = break_on_failure_; GTEST_FLAG(catch_exceptions) = catch_exceptions_; GTEST_FLAG(color) = color_; GTEST_FLAG(death_test_style) = death_test_style_; GTEST_FLAG(death_test_use_fork) = death_test_use_fork_; GTEST_FLAG(filter) = filter_; GTEST_FLAG(internal_run_death_test) = internal_run_death_test_; GTEST_FLAG(list_tests) = list_tests_; GTEST_FLAG(output) = output_; GTEST_FLAG(print_time) = print_time_; GTEST_FLAG(random_seed) = random_seed_; GTEST_FLAG(repeat) = repeat_; GTEST_FLAG(shuffle) = shuffle_; GTEST_FLAG(stack_trace_depth) = stack_trace_depth_; GTEST_FLAG(stream_result_to) = stream_result_to_; GTEST_FLAG(throw_on_failure) = throw_on_failure_; } private: // Fields for saving the original values of flags. bool also_run_disabled_tests_; bool break_on_failure_; bool catch_exceptions_; std::string color_; std::string death_test_style_; bool death_test_use_fork_; std::string filter_; std::string internal_run_death_test_; bool list_tests_; std::string output_; bool print_time_; internal::Int32 random_seed_; internal::Int32 repeat_; bool shuffle_; internal::Int32 stack_trace_depth_; std::string stream_result_to_; bool throw_on_failure_; } GTEST_ATTRIBUTE_UNUSED_; // Converts a Unicode code point to a narrow string in UTF-8 encoding. // code_point parameter is of type UInt32 because wchar_t may not be // wide enough to contain a code point. // If the code_point is not a valid Unicode code point // (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted // to "(Invalid Unicode 0xXXXXXXXX)". GTEST_API_ std::string CodePointToUtf8(UInt32 code_point); // Converts a wide string to a narrow string in UTF-8 encoding. // The wide string is assumed to have the following encoding: // UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) // UTF-32 if sizeof(wchar_t) == 4 (on Linux) // Parameter str points to a null-terminated wide string. // Parameter num_chars may additionally limit the number // of wchar_t characters processed. -1 is used when the entire string // should be processed. // If the string contains code points that are not valid Unicode code points // (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output // as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding // and contains invalid UTF-16 surrogate pairs, values in those pairs // will be encoded as individual Unicode characters from Basic Normal Plane. GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars); // Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file // if the variable is present. If a file already exists at this location, this // function will write over it. If the variable is present, but the file cannot // be created, prints an error and exits. void WriteToShardStatusFileIfNeeded(); // Checks whether sharding is enabled by examining the relevant // environment variable values. If the variables are present, // but inconsistent (e.g., shard_index >= total_shards), prints // an error and exits. If in_subprocess_for_death_test, sharding is // disabled because it must only be applied to the original test // process. Otherwise, we could filter out death tests we intended to execute. GTEST_API_ bool ShouldShard(const char* total_shards_str, const char* shard_index_str, bool in_subprocess_for_death_test); // Parses the environment variable var as an Int32. If it is unset, // returns default_val. If it is not an Int32, prints an error and // and aborts. GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val); // Given the total number of shards, the shard index, and the test id, // returns true iff the test should be run on this shard. The test id is // some arbitrary but unique non-negative integer assigned to each test // method. Assumes that 0 <= shard_index < total_shards. GTEST_API_ bool ShouldRunTestOnShard( int total_shards, int shard_index, int test_id); // STL container utilities. // Returns the number of elements in the given container that satisfy // the given predicate. template inline int CountIf(const Container& c, Predicate predicate) { // Implemented as an explicit loop since std::count_if() in libCstd on // Solaris has a non-standard signature. int count = 0; for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) { if (predicate(*it)) ++count; } return count; } // Applies a function/functor to each element in the container. template void ForEach(const Container& c, Functor functor) { std::for_each(c.begin(), c.end(), functor); } // Returns the i-th element of the vector, or default_value if i is not // in range [0, v.size()). template inline E GetElementOr(const std::vector& v, int i, E default_value) { return (i < 0 || i >= static_cast(v.size())) ? default_value : v[i]; } // Performs an in-place shuffle of a range of the vector's elements. // 'begin' and 'end' are element indices as an STL-style range; // i.e. [begin, end) are shuffled, where 'end' == size() means to // shuffle to the end of the vector. template void ShuffleRange(internal::Random* random, int begin, int end, std::vector* v) { const int size = static_cast(v->size()); GTEST_CHECK_(0 <= begin && begin <= size) << "Invalid shuffle range start " << begin << ": must be in range [0, " << size << "]."; GTEST_CHECK_(begin <= end && end <= size) << "Invalid shuffle range finish " << end << ": must be in range [" << begin << ", " << size << "]."; // Fisher-Yates shuffle, from // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle for (int range_width = end - begin; range_width >= 2; range_width--) { const int last_in_range = begin + range_width - 1; const int selected = begin + random->Generate(range_width); std::swap((*v)[selected], (*v)[last_in_range]); } } // Performs an in-place shuffle of the vector's elements. template inline void Shuffle(internal::Random* random, std::vector* v) { ShuffleRange(random, 0, static_cast(v->size()), v); } // A function for deleting an object. Handy for being used as a // functor. template static void Delete(T* x) { delete x; } // A predicate that checks the key of a TestProperty against a known key. // // TestPropertyKeyIs is copyable. class TestPropertyKeyIs { public: // Constructor. // // TestPropertyKeyIs has NO default constructor. explicit TestPropertyKeyIs(const std::string& key) : key_(key) {} // Returns true iff the test name of test property matches on key_. bool operator()(const TestProperty& test_property) const { return test_property.key() == key_; } private: std::string key_; }; // Class UnitTestOptions. // // This class contains functions for processing options the user // specifies when running the tests. It has only static members. // // In most cases, the user can specify an option using either an // environment variable or a command line flag. E.g. you can set the // test filter using either GTEST_FILTER or --gtest_filter. If both // the variable and the flag are present, the latter overrides the // former. class GTEST_API_ UnitTestOptions { public: // Functions for processing the gtest_output flag. // Returns the output format, or "" for normal printed output. static std::string GetOutputFormat(); // Returns the absolute path of the requested output file, or the // default (test_detail.xml in the original working directory) if // none was explicitly specified. static std::string GetAbsolutePathToOutputFile(); // Functions for processing the gtest_filter flag. // Returns true iff the wildcard pattern matches the string. The // first ':' or '\0' character in pattern marks the end of it. // // This recursive algorithm isn't very efficient, but is clear and // works well enough for matching test names, which are short. static bool PatternMatchesString(const char *pattern, const char *str); // Returns true iff the user-specified filter matches the test case // name and the test name. static bool FilterMatchesTest(const std::string &test_case_name, const std::string &test_name); #if GTEST_OS_WINDOWS // Function for supporting the gtest_catch_exception flag. // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. // This function is useful as an __except condition. static int GTestShouldProcessSEH(DWORD exception_code); #endif // GTEST_OS_WINDOWS // Returns true if "name" matches the ':' separated list of glob-style // filters in "filter". static bool MatchesFilter(const std::string& name, const char* filter); }; // Returns the current application's name, removing directory path if that // is present. Used by UnitTestOptions::GetOutputFile. GTEST_API_ FilePath GetCurrentExecutableName(); // The role interface for getting the OS stack trace as a string. class OsStackTraceGetterInterface { public: OsStackTraceGetterInterface() {} virtual ~OsStackTraceGetterInterface() {} // Returns the current OS stack trace as an std::string. Parameters: // // max_depth - the maximum number of stack frames to be included // in the trace. // skip_count - the number of top frames to be skipped; doesn't count // against max_depth. virtual string CurrentStackTrace(int max_depth, int skip_count) = 0; // UponLeavingGTest() should be called immediately before Google Test calls // user code. It saves some information about the current stack that // CurrentStackTrace() will use to find and hide Google Test stack frames. virtual void UponLeavingGTest() = 0; private: GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); }; // A working implementation of the OsStackTraceGetterInterface interface. class OsStackTraceGetter : public OsStackTraceGetterInterface { public: OsStackTraceGetter() : caller_frame_(NULL) {} virtual string CurrentStackTrace(int max_depth, int skip_count) GTEST_LOCK_EXCLUDED_(mutex_); virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_); // This string is inserted in place of stack frames that are part of // Google Test's implementation. static const char* const kElidedFramesMarker; private: Mutex mutex_; // protects all internal state // We save the stack frame below the frame that calls user code. // We do this because the address of the frame immediately below // the user code changes between the call to UponLeavingGTest() // and any calls to CurrentStackTrace() from within the user code. void* caller_frame_; GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); }; // Information about a Google Test trace point. struct TraceInfo { const char* file; int line; std::string message; }; // This is the default global test part result reporter used in UnitTestImpl. // This class should only be used by UnitTestImpl. class DefaultGlobalTestPartResultReporter : public TestPartResultReporterInterface { public: explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test); // Implements the TestPartResultReporterInterface. Reports the test part // result in the current test. virtual void ReportTestPartResult(const TestPartResult& result); private: UnitTestImpl* const unit_test_; GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter); }; // This is the default per thread test part result reporter used in // UnitTestImpl. This class should only be used by UnitTestImpl. class DefaultPerThreadTestPartResultReporter : public TestPartResultReporterInterface { public: explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test); // Implements the TestPartResultReporterInterface. The implementation just // delegates to the current global test part result reporter of *unit_test_. virtual void ReportTestPartResult(const TestPartResult& result); private: UnitTestImpl* const unit_test_; GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter); }; // The private implementation of the UnitTest class. We don't protect // the methods under a mutex, as this class is not accessible by a // user and the UnitTest class that delegates work to this class does // proper locking. class GTEST_API_ UnitTestImpl { public: explicit UnitTestImpl(UnitTest* parent); virtual ~UnitTestImpl(); // There are two different ways to register your own TestPartResultReporter. // You can register your own repoter to listen either only for test results // from the current thread or for results from all threads. // By default, each per-thread test result repoter just passes a new // TestPartResult to the global test result reporter, which registers the // test part result for the currently running test. // Returns the global test part result reporter. TestPartResultReporterInterface* GetGlobalTestPartResultReporter(); // Sets the global test part result reporter. void SetGlobalTestPartResultReporter( TestPartResultReporterInterface* reporter); // Returns the test part result reporter for the current thread. TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread(); // Sets the test part result reporter for the current thread. void SetTestPartResultReporterForCurrentThread( TestPartResultReporterInterface* reporter); // Gets the number of successful test cases. int successful_test_case_count() const; // Gets the number of failed test cases. int failed_test_case_count() const; // Gets the number of all test cases. int total_test_case_count() const; // Gets the number of all test cases that contain at least one test // that should run. int test_case_to_run_count() const; // Gets the number of successful tests. int successful_test_count() const; // Gets the number of failed tests. int failed_test_count() const; // Gets the number of disabled tests that will be reported in the XML report. int reportable_disabled_test_count() const; // Gets the number of disabled tests. int disabled_test_count() const; // Gets the number of tests to be printed in the XML report. int reportable_test_count() const; // Gets the number of all tests. int total_test_count() const; // Gets the number of tests that should run. int test_to_run_count() const; // Gets the time of the test program start, in ms from the start of the // UNIX epoch. TimeInMillis start_timestamp() const { return start_timestamp_; } // Gets the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } // Returns true iff the unit test passed (i.e. all test cases passed). bool Passed() const { return !Failed(); } // Returns true iff the unit test failed (i.e. some test case failed // or something outside of all tests failed). bool Failed() const { return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed(); } // Gets the i-th test case among all the test cases. i can range from 0 to // total_test_case_count() - 1. If i is not in that range, returns NULL. const TestCase* GetTestCase(int i) const { const int index = GetElementOr(test_case_indices_, i, -1); return index < 0 ? NULL : test_cases_[i]; } // Gets the i-th test case among all the test cases. i can range from 0 to // total_test_case_count() - 1. If i is not in that range, returns NULL. TestCase* GetMutableTestCase(int i) { const int index = GetElementOr(test_case_indices_, i, -1); return index < 0 ? NULL : test_cases_[index]; } // Provides access to the event listener list. TestEventListeners* listeners() { return &listeners_; } // Returns the TestResult for the test that's currently running, or // the TestResult for the ad hoc test if no test is running. TestResult* current_test_result(); // Returns the TestResult for the ad hoc test. const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; } // Sets the OS stack trace getter. // // Does nothing if the input and the current OS stack trace getter // are the same; otherwise, deletes the old getter and makes the // input the current getter. void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter); // Returns the current OS stack trace getter if it is not NULL; // otherwise, creates an OsStackTraceGetter, makes it the current // getter, and returns it. OsStackTraceGetterInterface* os_stack_trace_getter(); // Returns the current OS stack trace as an std::string. // // The maximum number of stack frames to be included is specified by // the gtest_stack_trace_depth flag. The skip_count parameter // specifies the number of top frames to be skipped, which doesn't // count against the number of frames to be included. // // For example, if Foo() calls Bar(), which in turn calls // CurrentOsStackTraceExceptTop(1), Foo() will be included in the // trace but Bar() and CurrentOsStackTraceExceptTop() won't. std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_; // Finds and returns a TestCase with the given name. If one doesn't // exist, creates one and returns it. // // Arguments: // // test_case_name: name of the test case // type_param: the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case TestCase* GetTestCase(const char* test_case_name, const char* type_param, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc); // Adds a TestInfo to the unit test. // // Arguments: // // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case // test_info: the TestInfo object void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc, TestInfo* test_info) { // In order to support thread-safe death tests, we need to // remember the original working directory when the test program // was first invoked. We cannot do this in RUN_ALL_TESTS(), as // the user may have changed the current directory before calling // RUN_ALL_TESTS(). Therefore we capture the current directory in // AddTestInfo(), which is called to register a TEST or TEST_F // before main() is reached. if (original_working_dir_.IsEmpty()) { original_working_dir_.Set(FilePath::GetCurrentDir()); GTEST_CHECK_(!original_working_dir_.IsEmpty()) << "Failed to get the current working directory."; } GetTestCase(test_info->test_case_name(), test_info->type_param(), set_up_tc, tear_down_tc)->AddTestInfo(test_info); } #if GTEST_HAS_PARAM_TEST // Returns ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. internal::ParameterizedTestCaseRegistry& parameterized_test_registry() { return parameterized_test_registry_; } #endif // GTEST_HAS_PARAM_TEST // Sets the TestCase object for the test that's currently running. void set_current_test_case(TestCase* a_current_test_case) { current_test_case_ = a_current_test_case; } // Sets the TestInfo object for the test that's currently running. If // current_test_info is NULL, the assertion results will be stored in // ad_hoc_test_result_. void set_current_test_info(TestInfo* a_current_test_info) { current_test_info_ = a_current_test_info; } // Registers all parameterized tests defined using TEST_P and // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter // combination. This method can be called more then once; it has guards // protecting from registering the tests more then once. If // value-parameterized tests are disabled, RegisterParameterizedTests is // present but does nothing. void RegisterParameterizedTests(); // Runs all tests in this UnitTest object, prints the result, and // returns true if all tests are successful. If any exception is // thrown during a test, this test is considered to be failed, but // the rest of the tests will still be run. bool RunAllTests(); // Clears the results of all tests, except the ad hoc tests. void ClearNonAdHocTestResult() { ForEach(test_cases_, TestCase::ClearTestCaseResult); } // Clears the results of ad-hoc test assertions. void ClearAdHocTestResult() { ad_hoc_test_result_.Clear(); } // Adds a TestProperty to the current TestResult object when invoked in a // context of a test or a test case, or to the global property set. If the // result already contains a property with the same key, the value will be // updated. void RecordProperty(const TestProperty& test_property); enum ReactionToSharding { HONOR_SHARDING_PROTOCOL, IGNORE_SHARDING_PROTOCOL }; // Matches the full name of each test against the user-specified // filter to decide whether the test should run, then records the // result in each TestCase and TestInfo object. // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests // based on sharding variables in the environment. // Returns the number of tests that should run. int FilterTests(ReactionToSharding shard_tests); // Prints the names of the tests matching the user-specified filter flag. void ListTestsMatchingFilter(); const TestCase* current_test_case() const { return current_test_case_; } TestInfo* current_test_info() { return current_test_info_; } const TestInfo* current_test_info() const { return current_test_info_; } // Returns the vector of environments that need to be set-up/torn-down // before/after the tests are run. std::vector& environments() { return environments_; } // Getters for the per-thread Google Test trace stack. std::vector& gtest_trace_stack() { return *(gtest_trace_stack_.pointer()); } const std::vector& gtest_trace_stack() const { return gtest_trace_stack_.get(); } #if GTEST_HAS_DEATH_TEST void InitDeathTestSubprocessControlInfo() { internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag()); } // Returns a pointer to the parsed --gtest_internal_run_death_test // flag, or NULL if that flag was not specified. // This information is useful only in a death test child process. // Must not be called before a call to InitGoogleTest. const InternalRunDeathTestFlag* internal_run_death_test_flag() const { return internal_run_death_test_flag_.get(); } // Returns a pointer to the current death test factory. internal::DeathTestFactory* death_test_factory() { return death_test_factory_.get(); } void SuppressTestEventsIfInSubprocess(); friend class ReplaceDeathTestFactory; #endif // GTEST_HAS_DEATH_TEST // Initializes the event listener performing XML output as specified by // UnitTestOptions. Must not be called before InitGoogleTest. void ConfigureXmlOutput(); #if GTEST_CAN_STREAM_RESULTS_ // Initializes the event listener for streaming test results to a socket. // Must not be called before InitGoogleTest. void ConfigureStreamingOutput(); #endif // Performs initialization dependent upon flag values obtained in // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest // this function is also called from RunAllTests. Since this function can be // called more than once, it has to be idempotent. void PostFlagParsingInit(); // Gets the random seed used at the start of the current test iteration. int random_seed() const { return random_seed_; } // Gets the random number generator. internal::Random* random() { return &random_; } // Shuffles all test cases, and the tests within each test case, // making sure that death tests are still run first. void ShuffleTests(); // Restores the test cases and tests to their order before the first shuffle. void UnshuffleTests(); // Returns the value of GTEST_FLAG(catch_exceptions) at the moment // UnitTest::Run() starts. bool catch_exceptions() const { return catch_exceptions_; } private: friend class ::testing::UnitTest; // Used by UnitTest::Run() to capture the state of // GTEST_FLAG(catch_exceptions) at the moment it starts. void set_catch_exceptions(bool value) { catch_exceptions_ = value; } // The UnitTest object that owns this implementation object. UnitTest* const parent_; // The working directory when the first TEST() or TEST_F() was // executed. internal::FilePath original_working_dir_; // The default test part result reporters. DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_; DefaultPerThreadTestPartResultReporter default_per_thread_test_part_result_reporter_; // Points to (but doesn't own) the global test part result reporter. TestPartResultReporterInterface* global_test_part_result_repoter_; // Protects read and write access to global_test_part_result_reporter_. internal::Mutex global_test_part_result_reporter_mutex_; // Points to (but doesn't own) the per-thread test part result reporter. internal::ThreadLocal per_thread_test_part_result_reporter_; // The vector of environments that need to be set-up/torn-down // before/after the tests are run. std::vector environments_; // The vector of TestCases in their original order. It owns the // elements in the vector. std::vector test_cases_; // Provides a level of indirection for the test case list to allow // easy shuffling and restoring the test case order. The i-th // element of this vector is the index of the i-th test case in the // shuffled order. std::vector test_case_indices_; #if GTEST_HAS_PARAM_TEST // ParameterizedTestRegistry object used to register value-parameterized // tests. internal::ParameterizedTestCaseRegistry parameterized_test_registry_; // Indicates whether RegisterParameterizedTests() has been called already. bool parameterized_tests_registered_; #endif // GTEST_HAS_PARAM_TEST // Index of the last death test case registered. Initially -1. int last_death_test_case_; // This points to the TestCase for the currently running test. It // changes as Google Test goes through one test case after another. // When no test is running, this is set to NULL and Google Test // stores assertion results in ad_hoc_test_result_. Initially NULL. TestCase* current_test_case_; // This points to the TestInfo for the currently running test. It // changes as Google Test goes through one test after another. When // no test is running, this is set to NULL and Google Test stores // assertion results in ad_hoc_test_result_. Initially NULL. TestInfo* current_test_info_; // Normally, a user only writes assertions inside a TEST or TEST_F, // or inside a function called by a TEST or TEST_F. Since Google // Test keeps track of which test is current running, it can // associate such an assertion with the test it belongs to. // // If an assertion is encountered when no TEST or TEST_F is running, // Google Test attributes the assertion result to an imaginary "ad hoc" // test, and records the result in ad_hoc_test_result_. TestResult ad_hoc_test_result_; // The list of event listeners that can be used to track events inside // Google Test. TestEventListeners listeners_; // The OS stack trace getter. Will be deleted when the UnitTest // object is destructed. By default, an OsStackTraceGetter is used, // but the user can set this field to use a custom getter if that is // desired. OsStackTraceGetterInterface* os_stack_trace_getter_; // True iff PostFlagParsingInit() has been called. bool post_flag_parse_init_performed_; // The random number seed used at the beginning of the test run. int random_seed_; // Our random number generator. internal::Random random_; // The time of the test program start, in ms from the start of the // UNIX epoch. TimeInMillis start_timestamp_; // How long the test took to run, in milliseconds. TimeInMillis elapsed_time_; #if GTEST_HAS_DEATH_TEST // The decomposed components of the gtest_internal_run_death_test flag, // parsed when RUN_ALL_TESTS is called. internal::scoped_ptr internal_run_death_test_flag_; internal::scoped_ptr death_test_factory_; #endif // GTEST_HAS_DEATH_TEST // A per-thread stack of traces created by the SCOPED_TRACE() macro. internal::ThreadLocal > gtest_trace_stack_; // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests() // starts. bool catch_exceptions_; GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl); }; // class UnitTestImpl // Convenience function for accessing the global UnitTest // implementation object. inline UnitTestImpl* GetUnitTestImpl() { return UnitTest::GetInstance()->impl(); } #if GTEST_USES_SIMPLE_RE // Internal helper functions for implementing the simple regular // expression matcher. GTEST_API_ bool IsInSet(char ch, const char* str); GTEST_API_ bool IsAsciiDigit(char ch); GTEST_API_ bool IsAsciiPunct(char ch); GTEST_API_ bool IsRepeat(char ch); GTEST_API_ bool IsAsciiWhiteSpace(char ch); GTEST_API_ bool IsAsciiWordChar(char ch); GTEST_API_ bool IsValidEscape(char ch); GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch); GTEST_API_ bool ValidateRegex(const char* regex); GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str); GTEST_API_ bool MatchRepetitionAndRegexAtHead( bool escaped, char ch, char repeat, const char* regex, const char* str); GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str); #endif // GTEST_USES_SIMPLE_RE // Parses the command line for Google Test flags, without initializing // other parts of Google Test. GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv); GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv); #if GTEST_HAS_DEATH_TEST // Returns the message describing the last system error, regardless of the // platform. GTEST_API_ std::string GetLastErrnoDescription(); # if GTEST_OS_WINDOWS // Provides leak-safe Windows kernel handle ownership. class AutoHandle { public: AutoHandle() : handle_(INVALID_HANDLE_VALUE) {} explicit AutoHandle(HANDLE handle) : handle_(handle) {} ~AutoHandle() { Reset(); } HANDLE Get() const { return handle_; } void Reset() { Reset(INVALID_HANDLE_VALUE); } void Reset(HANDLE handle) { if (handle != handle_) { if (handle_ != INVALID_HANDLE_VALUE) ::CloseHandle(handle_); handle_ = handle; } } private: HANDLE handle_; GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle); }; # endif // GTEST_OS_WINDOWS // Attempts to parse a string into a positive integer pointed to by the // number parameter. Returns true if that is possible. // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use // it here. template bool ParseNaturalNumber(const ::std::string& str, Integer* number) { // Fail fast if the given string does not begin with a digit; // this bypasses strtoXXX's "optional leading whitespace and plus // or minus sign" semantics, which are undesirable here. if (str.empty() || !IsDigit(str[0])) { return false; } errno = 0; char* end; // BiggestConvertible is the largest integer type that system-provided // string-to-number conversion routines can return. # if GTEST_OS_WINDOWS && !defined(__GNUC__) // MSVC and C++ Builder define __int64 instead of the standard long long. typedef unsigned __int64 BiggestConvertible; const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10); # else typedef unsigned long long BiggestConvertible; // NOLINT const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10); # endif // GTEST_OS_WINDOWS && !defined(__GNUC__) const bool parse_success = *end == '\0' && errno == 0; // TODO(vladl@google.com): Convert this to compile time assertion when it is // available. GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed)); const Integer result = static_cast(parsed); if (parse_success && static_cast(result) == parsed) { *number = result; return true; } return false; } #endif // GTEST_HAS_DEATH_TEST // TestResult contains some private methods that should be hidden from // Google Test user but are required for testing. This class allow our tests // to access them. // // This class is supplied only for the purpose of testing Google Test's own // constructs. Do not use it in user tests, either directly or indirectly. class TestResultAccessor { public: static void RecordProperty(TestResult* test_result, const std::string& xml_element, const TestProperty& property) { test_result->RecordProperty(xml_element, property); } static void ClearTestPartResults(TestResult* test_result) { test_result->ClearTestPartResults(); } static const std::vector& test_part_results( const TestResult& test_result) { return test_result.test_part_results(); } }; #if GTEST_CAN_STREAM_RESULTS_ // Streams test results to the given port on the given host machine. class StreamingListener : public EmptyTestEventListener { public: // Abstract base class for writing strings to a socket. class AbstractSocketWriter { public: virtual ~AbstractSocketWriter() {} // Sends a string to the socket. virtual void Send(const string& message) = 0; // Closes the socket. virtual void CloseConnection() {} // Sends a string and a newline to the socket. void SendLn(const string& message) { Send(message + "\n"); } }; // Concrete class for actually writing strings to a socket. class SocketWriter : public AbstractSocketWriter { public: SocketWriter(const string& host, const string& port) : sockfd_(-1), host_name_(host), port_num_(port) { MakeConnection(); } virtual ~SocketWriter() { if (sockfd_ != -1) CloseConnection(); } // Sends a string to the socket. virtual void Send(const string& message) { GTEST_CHECK_(sockfd_ != -1) << "Send() can be called only when there is a connection."; const int len = static_cast(message.length()); if (write(sockfd_, message.c_str(), len) != len) { GTEST_LOG_(WARNING) << "stream_result_to: failed to stream to " << host_name_ << ":" << port_num_; } } private: // Creates a client socket and connects to the server. void MakeConnection(); // Closes the socket. void CloseConnection() { GTEST_CHECK_(sockfd_ != -1) << "CloseConnection() can be called only when there is a connection."; close(sockfd_); sockfd_ = -1; } int sockfd_; // socket file descriptor const string host_name_; const string port_num_; GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter); }; // class SocketWriter // Escapes '=', '&', '%', and '\n' characters in str as "%xx". static string UrlEncode(const char* str); StreamingListener(const string& host, const string& port) : socket_writer_(new SocketWriter(host, port)) { Start(); } explicit StreamingListener(AbstractSocketWriter* socket_writer) : socket_writer_(socket_writer) { Start(); } void OnTestProgramStart(const UnitTest& /* unit_test */) { SendLn("event=TestProgramStart"); } void OnTestProgramEnd(const UnitTest& unit_test) { // Note that Google Test current only report elapsed time for each // test iteration, not for the entire test program. SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed())); // Notify the streaming server to stop. socket_writer_->CloseConnection(); } void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) { SendLn("event=TestIterationStart&iteration=" + StreamableToString(iteration)); } void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) { SendLn("event=TestIterationEnd&passed=" + FormatBool(unit_test.Passed()) + "&elapsed_time=" + StreamableToString(unit_test.elapsed_time()) + "ms"); } void OnTestCaseStart(const TestCase& test_case) { SendLn(std::string("event=TestCaseStart&name=") + test_case.name()); } void OnTestCaseEnd(const TestCase& test_case) { SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) + "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) + "ms"); } void OnTestStart(const TestInfo& test_info) { SendLn(std::string("event=TestStart&name=") + test_info.name()); } void OnTestEnd(const TestInfo& test_info) { SendLn("event=TestEnd&passed=" + FormatBool((test_info.result())->Passed()) + "&elapsed_time=" + StreamableToString((test_info.result())->elapsed_time()) + "ms"); } void OnTestPartResult(const TestPartResult& test_part_result) { const char* file_name = test_part_result.file_name(); if (file_name == NULL) file_name = ""; SendLn("event=TestPartResult&file=" + UrlEncode(file_name) + "&line=" + StreamableToString(test_part_result.line_number()) + "&message=" + UrlEncode(test_part_result.message())); } private: // Sends the given message and a newline to the socket. void SendLn(const string& message) { socket_writer_->SendLn(message); } // Called at the start of streaming to notify the receiver what // protocol we are using. void Start() { SendLn("gtest_streaming_protocol_version=1.0"); } string FormatBool(bool value) { return value ? "1" : "0"; } const scoped_ptr socket_writer_; GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener); }; // class StreamingListener #endif // GTEST_CAN_STREAM_RESULTS_ } // namespace internal } // namespace testing #endif // GTEST_SRC_GTEST_INTERNAL_INL_H_ #undef GTEST_IMPLEMENTATION_ #if GTEST_OS_WINDOWS # define vsnprintf _vsnprintf #endif // GTEST_OS_WINDOWS namespace testing { using internal::CountIf; using internal::ForEach; using internal::GetElementOr; using internal::Shuffle; // Constants. // A test whose test case name or test name matches this filter is // disabled and not run. static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*"; // A test case whose name matches this filter is considered a death // test case and will be run before test cases whose name doesn't // match this filter. static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*"; // A test filter that matches everything. static const char kUniversalFilter[] = "*"; // The default output file for XML output. static const char kDefaultOutputFile[] = "test_detail.xml"; // The environment variable name for the test shard index. static const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; // The environment variable name for the total number of test shards. static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; // The environment variable name for the test shard status file. static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE"; namespace internal { // The text used in failure messages to indicate the start of the // stack trace. const char kStackTraceMarker[] = "\nStack trace:\n"; // g_help_flag is true iff the --help flag or an equivalent form is // specified on the command line. bool g_help_flag = false; } // namespace internal static const char* GetDefaultFilter() { return kUniversalFilter; } GTEST_DEFINE_bool_( also_run_disabled_tests, internal::BoolFromGTestEnv("also_run_disabled_tests", false), "Run disabled tests too, in addition to the tests normally being run."); GTEST_DEFINE_bool_( break_on_failure, internal::BoolFromGTestEnv("break_on_failure", false), "True iff a failed assertion should be a debugger break-point."); GTEST_DEFINE_bool_( catch_exceptions, internal::BoolFromGTestEnv("catch_exceptions", true), "True iff " GTEST_NAME_ " should catch exceptions and treat them as test failures."); GTEST_DEFINE_string_( color, internal::StringFromGTestEnv("color", "auto"), "Whether to use colors in the output. Valid values: yes, no, " "and auto. 'auto' means to use colors if the output is " "being sent to a terminal and the TERM environment variable " "is set to a terminal type that supports colors."); GTEST_DEFINE_string_( filter, internal::StringFromGTestEnv("filter", GetDefaultFilter()), "A colon-separated list of glob (not regex) patterns " "for filtering the tests to run, optionally followed by a " "'-' and a : separated list of negative patterns (tests to " "exclude). A test is run if it matches one of the positive " "patterns and does not match any of the negative patterns."); GTEST_DEFINE_bool_(list_tests, false, "List all tests without running them."); GTEST_DEFINE_string_( output, internal::StringFromGTestEnv("output", ""), "A format (currently must be \"xml\"), optionally followed " "by a colon and an output file name or directory. A directory " "is indicated by a trailing pathname separator. " "Examples: \"xml:filename.xml\", \"xml::directoryname/\". " "If a directory is specified, output files will be created " "within that directory, with file-names based on the test " "executable's name and, if necessary, made unique by adding " "digits."); GTEST_DEFINE_bool_( print_time, internal::BoolFromGTestEnv("print_time", true), "True iff " GTEST_NAME_ " should display elapsed time in text output."); GTEST_DEFINE_int32_( random_seed, internal::Int32FromGTestEnv("random_seed", 0), "Random number seed to use when shuffling test orders. Must be in range " "[1, 99999], or 0 to use a seed based on the current time."); GTEST_DEFINE_int32_( repeat, internal::Int32FromGTestEnv("repeat", 1), "How many times to repeat each test. Specify a negative number " "for repeating forever. Useful for shaking out flaky tests."); GTEST_DEFINE_bool_( show_internal_stack_frames, false, "True iff " GTEST_NAME_ " should include internal stack frames when " "printing test failure stack traces."); GTEST_DEFINE_bool_( shuffle, internal::BoolFromGTestEnv("shuffle", false), "True iff " GTEST_NAME_ " should randomize tests' order on every run."); GTEST_DEFINE_int32_( stack_trace_depth, internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth), "The maximum number of stack frames to print when an " "assertion fails. The valid range is 0 through 100, inclusive."); GTEST_DEFINE_string_( stream_result_to, internal::StringFromGTestEnv("stream_result_to", ""), "This flag specifies the host name and the port number on which to stream " "test results. Example: \"localhost:555\". The flag is effective only on " "Linux."); GTEST_DEFINE_bool_( throw_on_failure, internal::BoolFromGTestEnv("throw_on_failure", false), "When this flag is specified, a failed assertion will throw an exception " "if exceptions are enabled or exit the program with a non-zero code " "otherwise."); namespace internal { // Generates a random number from [0, range), using a Linear // Congruential Generator (LCG). Crashes if 'range' is 0 or greater // than kMaxRange. UInt32 Random::Generate(UInt32 range) { // These constants are the same as are used in glibc's rand(3). state_ = (1103515245U*state_ + 12345U) % kMaxRange; GTEST_CHECK_(range > 0) << "Cannot generate a number in the range [0, 0)."; GTEST_CHECK_(range <= kMaxRange) << "Generation of a number in [0, " << range << ") was requested, " << "but this can only generate numbers in [0, " << kMaxRange << ")."; // Converting via modulus introduces a bit of downward bias, but // it's simple, and a linear congruential generator isn't too good // to begin with. return state_ % range; } // GTestIsInitialized() returns true iff the user has initialized // Google Test. Useful for catching the user mistake of not initializing // Google Test before calling RUN_ALL_TESTS(). // // A user must call testing::InitGoogleTest() to initialize Google // Test. g_init_gtest_count is set to the number of times // InitGoogleTest() has been called. We don't protect this variable // under a mutex as it is only accessed in the main thread. GTEST_API_ int g_init_gtest_count = 0; static bool GTestIsInitialized() { return g_init_gtest_count != 0; } // Iterates over a vector of TestCases, keeping a running sum of the // results of calling a given int-returning method on each. // Returns the sum. static int SumOverTestCaseList(const std::vector& case_list, int (TestCase::*method)() const) { int sum = 0; for (size_t i = 0; i < case_list.size(); i++) { sum += (case_list[i]->*method)(); } return sum; } // Returns true iff the test case passed. static bool TestCasePassed(const TestCase* test_case) { return test_case->should_run() && test_case->Passed(); } // Returns true iff the test case failed. static bool TestCaseFailed(const TestCase* test_case) { return test_case->should_run() && test_case->Failed(); } // Returns true iff test_case contains at least one test that should // run. static bool ShouldRunTestCase(const TestCase* test_case) { return test_case->should_run(); } // AssertHelper constructor. AssertHelper::AssertHelper(TestPartResult::Type type, const char* file, int line, const char* message) : data_(new AssertHelperData(type, file, line, message)) { } AssertHelper::~AssertHelper() { delete data_; } // Message assignment, for assertion streaming support. void AssertHelper::operator=(const Message& message) const { UnitTest::GetInstance()-> AddTestPartResult(data_->type, data_->file, data_->line, AppendUserMessage(data_->message, message), UnitTest::GetInstance()->impl() ->CurrentOsStackTraceExceptTop(1) // Skips the stack frame for this function itself. ); // NOLINT } // Mutex for linked pointers. GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex); // Application pathname gotten in InitGoogleTest. std::string g_executable_path; // Returns the current application's name, removing directory path if that // is present. FilePath GetCurrentExecutableName() { FilePath result; #if GTEST_OS_WINDOWS result.Set(FilePath(g_executable_path).RemoveExtension("exe")); #else result.Set(FilePath(g_executable_path)); #endif // GTEST_OS_WINDOWS return result.RemoveDirectoryName(); } // Functions for processing the gtest_output flag. // Returns the output format, or "" for normal printed output. std::string UnitTestOptions::GetOutputFormat() { const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); if (gtest_output_flag == NULL) return std::string(""); const char* const colon = strchr(gtest_output_flag, ':'); return (colon == NULL) ? std::string(gtest_output_flag) : std::string(gtest_output_flag, colon - gtest_output_flag); } // Returns the name of the requested output file, or the default if none // was explicitly specified. std::string UnitTestOptions::GetAbsolutePathToOutputFile() { const char* const gtest_output_flag = GTEST_FLAG(output).c_str(); if (gtest_output_flag == NULL) return ""; const char* const colon = strchr(gtest_output_flag, ':'); if (colon == NULL) return internal::FilePath::ConcatPaths( internal::FilePath( UnitTest::GetInstance()->original_working_dir()), internal::FilePath(kDefaultOutputFile)).string(); internal::FilePath output_name(colon + 1); if (!output_name.IsAbsolutePath()) // TODO(wan@google.com): on Windows \some\path is not an absolute // path (as its meaning depends on the current drive), yet the // following logic for turning it into an absolute path is wrong. // Fix it. output_name = internal::FilePath::ConcatPaths( internal::FilePath(UnitTest::GetInstance()->original_working_dir()), internal::FilePath(colon + 1)); if (!output_name.IsDirectory()) return output_name.string(); internal::FilePath result(internal::FilePath::GenerateUniqueFileName( output_name, internal::GetCurrentExecutableName(), GetOutputFormat().c_str())); return result.string(); } // Returns true iff the wildcard pattern matches the string. The // first ':' or '\0' character in pattern marks the end of it. // // This recursive algorithm isn't very efficient, but is clear and // works well enough for matching test names, which are short. bool UnitTestOptions::PatternMatchesString(const char *pattern, const char *str) { switch (*pattern) { case '\0': case ':': // Either ':' or '\0' marks the end of the pattern. return *str == '\0'; case '?': // Matches any single character. return *str != '\0' && PatternMatchesString(pattern + 1, str + 1); case '*': // Matches any string (possibly empty) of characters. return (*str != '\0' && PatternMatchesString(pattern, str + 1)) || PatternMatchesString(pattern + 1, str); default: // Non-special character. Matches itself. return *pattern == *str && PatternMatchesString(pattern + 1, str + 1); } } bool UnitTestOptions::MatchesFilter( const std::string& name, const char* filter) { const char *cur_pattern = filter; for (;;) { if (PatternMatchesString(cur_pattern, name.c_str())) { return true; } // Finds the next pattern in the filter. cur_pattern = strchr(cur_pattern, ':'); // Returns if no more pattern can be found. if (cur_pattern == NULL) { return false; } // Skips the pattern separater (the ':' character). cur_pattern++; } } // Returns true iff the user-specified filter matches the test case // name and the test name. bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name, const std::string &test_name) { const std::string& full_name = test_case_name + "." + test_name.c_str(); // Split --gtest_filter at '-', if there is one, to separate into // positive filter and negative filter portions const char* const p = GTEST_FLAG(filter).c_str(); const char* const dash = strchr(p, '-'); std::string positive; std::string negative; if (dash == NULL) { positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter negative = ""; } else { positive = std::string(p, dash); // Everything up to the dash negative = std::string(dash + 1); // Everything after the dash if (positive.empty()) { // Treat '-test1' as the same as '*-test1' positive = kUniversalFilter; } } // A filter is a colon-separated list of patterns. It matches a // test if any pattern in it matches the test. return (MatchesFilter(full_name, positive.c_str()) && !MatchesFilter(full_name, negative.c_str())); } #if GTEST_HAS_SEH // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise. // This function is useful as an __except condition. int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) { // Google Test should handle a SEH exception if: // 1. the user wants it to, AND // 2. this is not a breakpoint exception, AND // 3. this is not a C++ exception (VC++ implements them via SEH, // apparently). // // SEH exception code for C++ exceptions. // (see http://support.microsoft.com/kb/185294 for more information). const DWORD kCxxExceptionCode = 0xe06d7363; bool should_handle = true; if (!GTEST_FLAG(catch_exceptions)) should_handle = false; else if (exception_code == EXCEPTION_BREAKPOINT) should_handle = false; else if (exception_code == kCxxExceptionCode) should_handle = false; return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; } #endif // GTEST_HAS_SEH } // namespace internal // The c'tor sets this object as the test part result reporter used by // Google Test. The 'result' parameter specifies where to report the // results. Intercepts only failures from the current thread. ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( TestPartResultArray* result) : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD), result_(result) { Init(); } // The c'tor sets this object as the test part result reporter used by // Google Test. The 'result' parameter specifies where to report the // results. ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter( InterceptMode intercept_mode, TestPartResultArray* result) : intercept_mode_(intercept_mode), result_(result) { Init(); } void ScopedFakeTestPartResultReporter::Init() { internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); if (intercept_mode_ == INTERCEPT_ALL_THREADS) { old_reporter_ = impl->GetGlobalTestPartResultReporter(); impl->SetGlobalTestPartResultReporter(this); } else { old_reporter_ = impl->GetTestPartResultReporterForCurrentThread(); impl->SetTestPartResultReporterForCurrentThread(this); } } // The d'tor restores the test part result reporter used by Google Test // before. ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() { internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); if (intercept_mode_ == INTERCEPT_ALL_THREADS) { impl->SetGlobalTestPartResultReporter(old_reporter_); } else { impl->SetTestPartResultReporterForCurrentThread(old_reporter_); } } // Increments the test part result count and remembers the result. // This method is from the TestPartResultReporterInterface interface. void ScopedFakeTestPartResultReporter::ReportTestPartResult( const TestPartResult& result) { result_->Append(result); } namespace internal { // Returns the type ID of ::testing::Test. We should always call this // instead of GetTypeId< ::testing::Test>() to get the type ID of // testing::Test. This is to work around a suspected linker bug when // using Google Test as a framework on Mac OS X. The bug causes // GetTypeId< ::testing::Test>() to return different values depending // on whether the call is from the Google Test framework itself or // from user test code. GetTestTypeId() is guaranteed to always // return the same value, as it always calls GetTypeId<>() from the // gtest.cc, which is within the Google Test framework. TypeId GetTestTypeId() { return GetTypeId(); } // The value of GetTestTypeId() as seen from within the Google Test // library. This is solely for testing GetTestTypeId(). extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); // This predicate-formatter checks that 'results' contains a test part // failure of the given type and that the failure message contains the // given substring. AssertionResult HasOneFailure(const char* /* results_expr */, const char* /* type_expr */, const char* /* substr_expr */, const TestPartResultArray& results, TestPartResult::Type type, const string& substr) { const std::string expected(type == TestPartResult::kFatalFailure ? "1 fatal failure" : "1 non-fatal failure"); Message msg; if (results.size() != 1) { msg << "Expected: " << expected << "\n" << " Actual: " << results.size() << " failures"; for (int i = 0; i < results.size(); i++) { msg << "\n" << results.GetTestPartResult(i); } return AssertionFailure() << msg; } const TestPartResult& r = results.GetTestPartResult(0); if (r.type() != type) { return AssertionFailure() << "Expected: " << expected << "\n" << " Actual:\n" << r; } if (strstr(r.message(), substr.c_str()) == NULL) { return AssertionFailure() << "Expected: " << expected << " containing \"" << substr << "\"\n" << " Actual:\n" << r; } return AssertionSuccess(); } // The constructor of SingleFailureChecker remembers where to look up // test part results, what type of failure we expect, and what // substring the failure message should contain. SingleFailureChecker:: SingleFailureChecker( const TestPartResultArray* results, TestPartResult::Type type, const string& substr) : results_(results), type_(type), substr_(substr) {} // The destructor of SingleFailureChecker verifies that the given // TestPartResultArray contains exactly one failure that has the given // type and contains the given substring. If that's not the case, a // non-fatal failure will be generated. SingleFailureChecker::~SingleFailureChecker() { EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_); } DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter( UnitTestImpl* unit_test) : unit_test_(unit_test) {} void DefaultGlobalTestPartResultReporter::ReportTestPartResult( const TestPartResult& result) { unit_test_->current_test_result()->AddTestPartResult(result); unit_test_->listeners()->repeater()->OnTestPartResult(result); } DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter( UnitTestImpl* unit_test) : unit_test_(unit_test) {} void DefaultPerThreadTestPartResultReporter::ReportTestPartResult( const TestPartResult& result) { unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result); } // Returns the global test part result reporter. TestPartResultReporterInterface* UnitTestImpl::GetGlobalTestPartResultReporter() { internal::MutexLock lock(&global_test_part_result_reporter_mutex_); return global_test_part_result_repoter_; } // Sets the global test part result reporter. void UnitTestImpl::SetGlobalTestPartResultReporter( TestPartResultReporterInterface* reporter) { internal::MutexLock lock(&global_test_part_result_reporter_mutex_); global_test_part_result_repoter_ = reporter; } // Returns the test part result reporter for the current thread. TestPartResultReporterInterface* UnitTestImpl::GetTestPartResultReporterForCurrentThread() { return per_thread_test_part_result_reporter_.get(); } // Sets the test part result reporter for the current thread. void UnitTestImpl::SetTestPartResultReporterForCurrentThread( TestPartResultReporterInterface* reporter) { per_thread_test_part_result_reporter_.set(reporter); } // Gets the number of successful test cases. int UnitTestImpl::successful_test_case_count() const { return CountIf(test_cases_, TestCasePassed); } // Gets the number of failed test cases. int UnitTestImpl::failed_test_case_count() const { return CountIf(test_cases_, TestCaseFailed); } // Gets the number of all test cases. int UnitTestImpl::total_test_case_count() const { return static_cast(test_cases_.size()); } // Gets the number of all test cases that contain at least one test // that should run. int UnitTestImpl::test_case_to_run_count() const { return CountIf(test_cases_, ShouldRunTestCase); } // Gets the number of successful tests. int UnitTestImpl::successful_test_count() const { return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count); } // Gets the number of failed tests. int UnitTestImpl::failed_test_count() const { return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count); } // Gets the number of disabled tests that will be reported in the XML report. int UnitTestImpl::reportable_disabled_test_count() const { return SumOverTestCaseList(test_cases_, &TestCase::reportable_disabled_test_count); } // Gets the number of disabled tests. int UnitTestImpl::disabled_test_count() const { return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count); } // Gets the number of tests to be printed in the XML report. int UnitTestImpl::reportable_test_count() const { return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count); } // Gets the number of all tests. int UnitTestImpl::total_test_count() const { return SumOverTestCaseList(test_cases_, &TestCase::total_test_count); } // Gets the number of tests that should run. int UnitTestImpl::test_to_run_count() const { return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count); } // Returns the current OS stack trace as an std::string. // // The maximum number of stack frames to be included is specified by // the gtest_stack_trace_depth flag. The skip_count parameter // specifies the number of top frames to be skipped, which doesn't // count against the number of frames to be included. // // For example, if Foo() calls Bar(), which in turn calls // CurrentOsStackTraceExceptTop(1), Foo() will be included in the // trace but Bar() and CurrentOsStackTraceExceptTop() won't. std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { (void)skip_count; return ""; } // Returns the current time in milliseconds. TimeInMillis GetTimeInMillis() { #if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__) // Difference between 1970-01-01 and 1601-01-01 in milliseconds. // http://analogous.blogspot.com/2005/04/epoch.html const TimeInMillis kJavaEpochToWinFileTimeDelta = static_cast(116444736UL) * 100000UL; const DWORD kTenthMicrosInMilliSecond = 10000; SYSTEMTIME now_systime; FILETIME now_filetime; ULARGE_INTEGER now_int64; // TODO(kenton@google.com): Shouldn't this just use // GetSystemTimeAsFileTime()? GetSystemTime(&now_systime); if (SystemTimeToFileTime(&now_systime, &now_filetime)) { now_int64.LowPart = now_filetime.dwLowDateTime; now_int64.HighPart = now_filetime.dwHighDateTime; now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) - kJavaEpochToWinFileTimeDelta; return now_int64.QuadPart; } return 0; #elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ __timeb64 now; # ifdef _MSC_VER // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 // (deprecated function) there. // TODO(kenton@google.com): Use GetTickCount()? Or use // SystemTimeToFileTime() # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4996) // Temporarily disables warning 4996. _ftime64(&now); # pragma warning(pop) // Restores the warning state. # else _ftime64(&now); # endif // _MSC_VER return static_cast(now.time) * 1000 + now.millitm; #elif GTEST_HAS_GETTIMEOFDAY_ struct timeval now; gettimeofday(&now, NULL); return static_cast(now.tv_sec) * 1000 + now.tv_usec / 1000; #else # error "Don't know how to get the current time on your system." #endif } // Utilities // class String. #if GTEST_OS_WINDOWS_MOBILE // Creates a UTF-16 wide string from the given ANSI string, allocating // memory using new. The caller is responsible for deleting the return // value using delete[]. Returns the wide string, or NULL if the // input is NULL. LPCWSTR String::AnsiToUtf16(const char* ansi) { if (!ansi) return NULL; const int length = strlen(ansi); const int unicode_length = MultiByteToWideChar(CP_ACP, 0, ansi, length, NULL, 0); WCHAR* unicode = new WCHAR[unicode_length + 1]; MultiByteToWideChar(CP_ACP, 0, ansi, length, unicode, unicode_length); unicode[unicode_length] = 0; return unicode; } // Creates an ANSI string from the given wide string, allocating // memory using new. The caller is responsible for deleting the return // value using delete[]. Returns the ANSI string, or NULL if the // input is NULL. const char* String::Utf16ToAnsi(LPCWSTR utf16_str) { if (!utf16_str) return NULL; const int ansi_length = WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, NULL, 0, NULL, NULL); char* ansi = new char[ansi_length + 1]; WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, ansi, ansi_length, NULL, NULL); ansi[ansi_length] = 0; return ansi; } #endif // GTEST_OS_WINDOWS_MOBILE // Compares two C strings. Returns true iff they have the same content. // // Unlike strcmp(), this function can handle NULL argument(s). A NULL // C string is considered different to any non-NULL C string, // including the empty string. bool String::CStringEquals(const char * lhs, const char * rhs) { if ( lhs == NULL ) return rhs == NULL; if ( rhs == NULL ) return false; return strcmp(lhs, rhs) == 0; } #if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING // Converts an array of wide chars to a narrow string using the UTF-8 // encoding, and streams the result to the given Message object. static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length, Message* msg) { for (size_t i = 0; i != length; ) { // NOLINT if (wstr[i] != L'\0') { *msg << WideStringToUtf8(wstr + i, static_cast(length - i)); while (i != length && wstr[i] != L'\0') i++; } else { *msg << '\0'; i++; } } } #endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING } // namespace internal // Constructs an empty Message. // We allocate the stringstream separately because otherwise each use of // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's // stack frame leading to huge stack frames in some cases; gcc does not reuse // the stack space. Message::Message() : ss_(new ::std::stringstream) { // By default, we want there to be enough precision when printing // a double to a Message. *ss_ << std::setprecision(std::numeric_limits::digits10 + 2); } // These two overloads allow streaming a wide C string to a Message // using the UTF-8 encoding. Message& Message::operator <<(const wchar_t* wide_c_str) { return *this << internal::String::ShowWideCString(wide_c_str); } Message& Message::operator <<(wchar_t* wide_c_str) { return *this << internal::String::ShowWideCString(wide_c_str); } #if GTEST_HAS_STD_WSTRING // Converts the given wide string to a narrow string using the UTF-8 // encoding, and streams the result to this Message object. Message& Message::operator <<(const ::std::wstring& wstr) { internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); return *this; } #endif // GTEST_HAS_STD_WSTRING #if GTEST_HAS_GLOBAL_WSTRING // Converts the given wide string to a narrow string using the UTF-8 // encoding, and streams the result to this Message object. Message& Message::operator <<(const ::wstring& wstr) { internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this); return *this; } #endif // GTEST_HAS_GLOBAL_WSTRING // Gets the text streamed to this object so far as an std::string. // Each '\0' character in the buffer is replaced with "\\0". std::string Message::GetString() const { return internal::StringStreamToString(ss_.get()); } // AssertionResult constructors. // Used in EXPECT_TRUE/FALSE(assertion_result). AssertionResult::AssertionResult(const AssertionResult& other) : success_(other.success_), message_(other.message_.get() != NULL ? new ::std::string(*other.message_) : static_cast< ::std::string*>(NULL)) { } // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. AssertionResult AssertionResult::operator!() const { AssertionResult negation(!success_); if (message_.get() != NULL) negation << *message_; return negation; } // Makes a successful assertion result. AssertionResult AssertionSuccess() { return AssertionResult(true); } // Makes a failed assertion result. AssertionResult AssertionFailure() { return AssertionResult(false); } // Makes a failed assertion result with the given failure message. // Deprecated; use AssertionFailure() << message. AssertionResult AssertionFailure(const Message& message) { return AssertionFailure() << message; } namespace internal { // Constructs and returns the message for an equality assertion // (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. // // The first four parameters are the expressions used in the assertion // and their values, as strings. For example, for ASSERT_EQ(foo, bar) // where foo is 5 and bar is 6, we have: // // expected_expression: "foo" // actual_expression: "bar" // expected_value: "5" // actual_value: "6" // // The ignoring_case parameter is true iff the assertion is a // *_STRCASEEQ*. When it's true, the string " (ignoring case)" will // be inserted into the message. AssertionResult EqFailure(const char* expected_expression, const char* actual_expression, const std::string& expected_value, const std::string& actual_value, bool ignoring_case) { Message msg; msg << "Value of: " << actual_expression; if (actual_value != actual_expression) { msg << "\n Actual: " << actual_value; } msg << "\nExpected: " << expected_expression; if (ignoring_case) { msg << " (ignoring case)"; } if (expected_value != expected_expression) { msg << "\nWhich is: " << expected_value; } return AssertionFailure() << msg; } // Constructs a failure message for Boolean assertions such as EXPECT_TRUE. std::string GetBoolAssertionFailureMessage( const AssertionResult& assertion_result, const char* expression_text, const char* actual_predicate_value, const char* expected_predicate_value) { const char* actual_message = assertion_result.message(); Message msg; msg << "Value of: " << expression_text << "\n Actual: " << actual_predicate_value; if (actual_message[0] != '\0') msg << " (" << actual_message << ")"; msg << "\nExpected: " << expected_predicate_value; return msg.GetString(); } // Helper function for implementing ASSERT_NEAR. AssertionResult DoubleNearPredFormat(const char* expr1, const char* expr2, const char* abs_error_expr, double val1, double val2, double abs_error) { const double diff = fabs(val1 - val2); if (diff <= abs_error) return AssertionSuccess(); // TODO(wan): do not print the value of an expression if it's // already a literal. return AssertionFailure() << "The difference between " << expr1 << " and " << expr2 << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n" << expr1 << " evaluates to " << val1 << ",\n" << expr2 << " evaluates to " << val2 << ", and\n" << abs_error_expr << " evaluates to " << abs_error << "."; } // Helper template for implementing FloatLE() and DoubleLE(). template AssertionResult FloatingPointLE(const char* expr1, const char* expr2, RawType val1, RawType val2) { // Returns success if val1 is less than val2, if (val1 < val2) { return AssertionSuccess(); } // or if val1 is almost equal to val2. const FloatingPoint lhs(val1), rhs(val2); if (lhs.AlmostEquals(rhs)) { return AssertionSuccess(); } // Note that the above two checks will both fail if either val1 or // val2 is NaN, as the IEEE floating-point standard requires that // any predicate involving a NaN must return false. ::std::stringstream val1_ss; val1_ss << std::setprecision(std::numeric_limits::digits10 + 2) << val1; ::std::stringstream val2_ss; val2_ss << std::setprecision(std::numeric_limits::digits10 + 2) << val2; return AssertionFailure() << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n" << " Actual: " << StringStreamToString(&val1_ss) << " vs " << StringStreamToString(&val2_ss); } } // namespace internal // Asserts that val1 is less than, or almost equal to, val2. Fails // otherwise. In particular, it fails if either val1 or val2 is NaN. AssertionResult FloatLE(const char* expr1, const char* expr2, float val1, float val2) { return internal::FloatingPointLE(expr1, expr2, val1, val2); } // Asserts that val1 is less than, or almost equal to, val2. Fails // otherwise. In particular, it fails if either val1 or val2 is NaN. AssertionResult DoubleLE(const char* expr1, const char* expr2, double val1, double val2) { return internal::FloatingPointLE(expr1, expr2, val1, val2); } namespace internal { // The helper function for {ASSERT|EXPECT}_EQ with int or enum // arguments. AssertionResult CmpHelperEQ(const char* expected_expression, const char* actual_expression, BiggestInt expected, BiggestInt actual) { if (expected == actual) { return AssertionSuccess(); } return EqFailure(expected_expression, actual_expression, FormatForComparisonFailureMessage(expected, actual), FormatForComparisonFailureMessage(actual, expected), false); } // A macro for implementing the helper functions needed to implement // ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here // just to avoid copy-and-paste of similar code. #define GTEST_IMPL_CMP_HELPER_(op_name, op)\ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ BiggestInt val1, BiggestInt val2) {\ if (val1 op val2) {\ return AssertionSuccess();\ } else {\ return AssertionFailure() \ << "Expected: (" << expr1 << ") " #op " (" << expr2\ << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\ << " vs " << FormatForComparisonFailureMessage(val2, val1);\ }\ } // Implements the helper function for {ASSERT|EXPECT}_NE with int or // enum arguments. GTEST_IMPL_CMP_HELPER_(NE, !=) // Implements the helper function for {ASSERT|EXPECT}_LE with int or // enum arguments. GTEST_IMPL_CMP_HELPER_(LE, <=) // Implements the helper function for {ASSERT|EXPECT}_LT with int or // enum arguments. GTEST_IMPL_CMP_HELPER_(LT, < ) // Implements the helper function for {ASSERT|EXPECT}_GE with int or // enum arguments. GTEST_IMPL_CMP_HELPER_(GE, >=) // Implements the helper function for {ASSERT|EXPECT}_GT with int or // enum arguments. GTEST_IMPL_CMP_HELPER_(GT, > ) #undef GTEST_IMPL_CMP_HELPER_ // The helper function for {ASSERT|EXPECT}_STREQ. AssertionResult CmpHelperSTREQ(const char* expected_expression, const char* actual_expression, const char* expected, const char* actual) { if (String::CStringEquals(expected, actual)) { return AssertionSuccess(); } return EqFailure(expected_expression, actual_expression, PrintToString(expected), PrintToString(actual), false); } // The helper function for {ASSERT|EXPECT}_STRCASEEQ. AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression, const char* actual_expression, const char* expected, const char* actual) { if (String::CaseInsensitiveCStringEquals(expected, actual)) { return AssertionSuccess(); } return EqFailure(expected_expression, actual_expression, PrintToString(expected), PrintToString(actual), true); } // The helper function for {ASSERT|EXPECT}_STRNE. AssertionResult CmpHelperSTRNE(const char* s1_expression, const char* s2_expression, const char* s1, const char* s2) { if (!String::CStringEquals(s1, s2)) { return AssertionSuccess(); } else { return AssertionFailure() << "Expected: (" << s1_expression << ") != (" << s2_expression << "), actual: \"" << s1 << "\" vs \"" << s2 << "\""; } } // The helper function for {ASSERT|EXPECT}_STRCASENE. AssertionResult CmpHelperSTRCASENE(const char* s1_expression, const char* s2_expression, const char* s1, const char* s2) { if (!String::CaseInsensitiveCStringEquals(s1, s2)) { return AssertionSuccess(); } else { return AssertionFailure() << "Expected: (" << s1_expression << ") != (" << s2_expression << ") (ignoring case), actual: \"" << s1 << "\" vs \"" << s2 << "\""; } } } // namespace internal namespace { // Helper functions for implementing IsSubString() and IsNotSubstring(). // This group of overloaded functions return true iff needle is a // substring of haystack. NULL is considered a substring of itself // only. bool IsSubstringPred(const char* needle, const char* haystack) { if (needle == NULL || haystack == NULL) return needle == haystack; return strstr(haystack, needle) != NULL; } bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) { if (needle == NULL || haystack == NULL) return needle == haystack; return wcsstr(haystack, needle) != NULL; } // StringType here can be either ::std::string or ::std::wstring. template bool IsSubstringPred(const StringType& needle, const StringType& haystack) { return haystack.find(needle) != StringType::npos; } // This function implements either IsSubstring() or IsNotSubstring(), // depending on the value of the expected_to_be_substring parameter. // StringType here can be const char*, const wchar_t*, ::std::string, // or ::std::wstring. template AssertionResult IsSubstringImpl( bool expected_to_be_substring, const char* needle_expr, const char* haystack_expr, const StringType& needle, const StringType& haystack) { if (IsSubstringPred(needle, haystack) == expected_to_be_substring) return AssertionSuccess(); const bool is_wide_string = sizeof(needle[0]) > 1; const char* const begin_string_quote = is_wide_string ? "L\"" : "\""; return AssertionFailure() << "Value of: " << needle_expr << "\n" << " Actual: " << begin_string_quote << needle << "\"\n" << "Expected: " << (expected_to_be_substring ? "" : "not ") << "a substring of " << haystack_expr << "\n" << "Which is: " << begin_string_quote << haystack << "\""; } } // namespace // IsSubstring() and IsNotSubstring() check whether needle is a // substring of haystack (NULL is considered a substring of itself // only), and return an appropriate error message when they fail. AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const char* needle, const char* haystack) { return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); } AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const wchar_t* needle, const wchar_t* haystack) { return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); } AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const char* needle, const char* haystack) { return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); } AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const wchar_t* needle, const wchar_t* haystack) { return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); } AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack) { return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); } AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const ::std::string& needle, const ::std::string& haystack) { return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); } #if GTEST_HAS_STD_WSTRING AssertionResult IsSubstring( const char* needle_expr, const char* haystack_expr, const ::std::wstring& needle, const ::std::wstring& haystack) { return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack); } AssertionResult IsNotSubstring( const char* needle_expr, const char* haystack_expr, const ::std::wstring& needle, const ::std::wstring& haystack) { return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack); } #endif // GTEST_HAS_STD_WSTRING namespace internal { #if GTEST_OS_WINDOWS namespace { // Helper function for IsHRESULT{SuccessFailure} predicates AssertionResult HRESULTFailureHelper(const char* expr, const char* expected, long hr) { // NOLINT # if GTEST_OS_WINDOWS_MOBILE // Windows CE doesn't support FormatMessage. const char error_text[] = ""; # else // Looks up the human-readable system message for the HRESULT code // and since we're not passing any params to FormatMessage, we don't // want inserts expanded. const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; const DWORD kBufSize = 4096; // Gets the system's human readable message string for this HRESULT. char error_text[kBufSize] = { '\0' }; DWORD message_length = ::FormatMessageA(kFlags, 0, // no source, we're asking system hr, // the error 0, // no line width restrictions error_text, // output buffer kBufSize, // buf size NULL); // no arguments for inserts // Trims tailing white space (FormatMessage leaves a trailing CR-LF) for (; message_length && IsSpace(error_text[message_length - 1]); --message_length) { error_text[message_length - 1] = '\0'; } # endif // GTEST_OS_WINDOWS_MOBILE const std::string error_hex("0x" + String::FormatHexInt(hr)); return ::testing::AssertionFailure() << "Expected: " << expr << " " << expected << ".\n" << " Actual: " << error_hex << " " << error_text << "\n"; } } // namespace AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT if (SUCCEEDED(hr)) { return AssertionSuccess(); } return HRESULTFailureHelper(expr, "succeeds", hr); } AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT if (FAILED(hr)) { return AssertionSuccess(); } return HRESULTFailureHelper(expr, "fails", hr); } #endif // GTEST_OS_WINDOWS // Utility functions for encoding Unicode text (wide strings) in // UTF-8. // A Unicode code-point can have upto 21 bits, and is encoded in UTF-8 // like this: // // Code-point length Encoding // 0 - 7 bits 0xxxxxxx // 8 - 11 bits 110xxxxx 10xxxxxx // 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx // 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // The maximum code-point a one-byte UTF-8 sequence can represent. const UInt32 kMaxCodePoint1 = (static_cast(1) << 7) - 1; // The maximum code-point a two-byte UTF-8 sequence can represent. const UInt32 kMaxCodePoint2 = (static_cast(1) << (5 + 6)) - 1; // The maximum code-point a three-byte UTF-8 sequence can represent. const UInt32 kMaxCodePoint3 = (static_cast(1) << (4 + 2*6)) - 1; // The maximum code-point a four-byte UTF-8 sequence can represent. const UInt32 kMaxCodePoint4 = (static_cast(1) << (3 + 3*6)) - 1; // Chops off the n lowest bits from a bit pattern. Returns the n // lowest bits. As a side effect, the original bit pattern will be // shifted to the right by n bits. inline UInt32 ChopLowBits(UInt32* bits, int n) { const UInt32 low_bits = *bits & ((static_cast(1) << n) - 1); *bits >>= n; return low_bits; } // Converts a Unicode code point to a narrow string in UTF-8 encoding. // code_point parameter is of type UInt32 because wchar_t may not be // wide enough to contain a code point. // If the code_point is not a valid Unicode code point // (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted // to "(Invalid Unicode 0xXXXXXXXX)". std::string CodePointToUtf8(UInt32 code_point) { if (code_point > kMaxCodePoint4) { return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")"; } char str[5]; // Big enough for the largest valid code point. if (code_point <= kMaxCodePoint1) { str[1] = '\0'; str[0] = static_cast(code_point); // 0xxxxxxx } else if (code_point <= kMaxCodePoint2) { str[2] = '\0'; str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[0] = static_cast(0xC0 | code_point); // 110xxxxx } else if (code_point <= kMaxCodePoint3) { str[3] = '\0'; str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[0] = static_cast(0xE0 | code_point); // 1110xxxx } else { // code_point <= kMaxCodePoint4 str[4] = '\0'; str[3] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[2] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[1] = static_cast(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx str[0] = static_cast(0xF0 | code_point); // 11110xxx } return str; } // The following two functions only make sense if the the system // uses UTF-16 for wide string encoding. All supported systems // with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16. // Determines if the arguments constitute UTF-16 surrogate pair // and thus should be combined into a single Unicode code point // using CreateCodePointFromUtf16SurrogatePair. inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) { return sizeof(wchar_t) == 2 && (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00; } // Creates a Unicode code point from UTF16 surrogate pair. inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first, wchar_t second) { const UInt32 mask = (1 << 10) - 1; return (sizeof(wchar_t) == 2) ? (((first & mask) << 10) | (second & mask)) + 0x10000 : // This function should not be called when the condition is // false, but we provide a sensible default in case it is. static_cast(first); } // Converts a wide string to a narrow string in UTF-8 encoding. // The wide string is assumed to have the following encoding: // UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS) // UTF-32 if sizeof(wchar_t) == 4 (on Linux) // Parameter str points to a null-terminated wide string. // Parameter num_chars may additionally limit the number // of wchar_t characters processed. -1 is used when the entire string // should be processed. // If the string contains code points that are not valid Unicode code points // (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output // as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding // and contains invalid UTF-16 surrogate pairs, values in those pairs // will be encoded as individual Unicode characters from Basic Normal Plane. std::string WideStringToUtf8(const wchar_t* str, int num_chars) { if (num_chars == -1) num_chars = static_cast(wcslen(str)); ::std::stringstream stream; for (int i = 0; i < num_chars; ++i) { UInt32 unicode_code_point; if (str[i] == L'\0') { break; } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) { unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i], str[i + 1]); i++; } else { unicode_code_point = static_cast(str[i]); } stream << CodePointToUtf8(unicode_code_point); } return StringStreamToString(&stream); } // Converts a wide C string to an std::string using the UTF-8 encoding. // NULL will be converted to "(null)". std::string String::ShowWideCString(const wchar_t * wide_c_str) { if (wide_c_str == NULL) return "(null)"; return internal::WideStringToUtf8(wide_c_str, -1); } // Compares two wide C strings. Returns true iff they have the same // content. // // Unlike wcscmp(), this function can handle NULL argument(s). A NULL // C string is considered different to any non-NULL C string, // including the empty string. bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) { if (lhs == NULL) return rhs == NULL; if (rhs == NULL) return false; return wcscmp(lhs, rhs) == 0; } // Helper function for *_STREQ on wide strings. AssertionResult CmpHelperSTREQ(const char* expected_expression, const char* actual_expression, const wchar_t* expected, const wchar_t* actual) { if (String::WideCStringEquals(expected, actual)) { return AssertionSuccess(); } return EqFailure(expected_expression, actual_expression, PrintToString(expected), PrintToString(actual), false); } // Helper function for *_STRNE on wide strings. AssertionResult CmpHelperSTRNE(const char* s1_expression, const char* s2_expression, const wchar_t* s1, const wchar_t* s2) { if (!String::WideCStringEquals(s1, s2)) { return AssertionSuccess(); } return AssertionFailure() << "Expected: (" << s1_expression << ") != (" << s2_expression << "), actual: " << PrintToString(s1) << " vs " << PrintToString(s2); } // Compares two C strings, ignoring case. Returns true iff they have // the same content. // // Unlike strcasecmp(), this function can handle NULL argument(s). A // NULL C string is considered different to any non-NULL C string, // including the empty string. bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) { if (lhs == NULL) return rhs == NULL; if (rhs == NULL) return false; return posix::StrCaseCmp(lhs, rhs) == 0; } // Compares two wide C strings, ignoring case. Returns true iff they // have the same content. // // Unlike wcscasecmp(), this function can handle NULL argument(s). // A NULL C string is considered different to any non-NULL wide C string, // including the empty string. // NB: The implementations on different platforms slightly differ. // On windows, this method uses _wcsicmp which compares according to LC_CTYPE // environment variable. On GNU platform this method uses wcscasecmp // which compares according to LC_CTYPE category of the current locale. // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the // current locale. bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs, const wchar_t* rhs) { if (lhs == NULL) return rhs == NULL; if (rhs == NULL) return false; #if GTEST_OS_WINDOWS return _wcsicmp(lhs, rhs) == 0; #elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID return wcscasecmp(lhs, rhs) == 0; #else // Android, Mac OS X and Cygwin don't define wcscasecmp. // Other unknown OSes may not define it either. wint_t left, right; do { left = towlower(*lhs++); right = towlower(*rhs++); } while (left && left == right); return left == right; #endif // OS selector } // Returns true iff str ends with the given suffix, ignoring case. // Any string is considered to end with an empty suffix. bool String::EndsWithCaseInsensitive( const std::string& str, const std::string& suffix) { const size_t str_len = str.length(); const size_t suffix_len = suffix.length(); return (str_len >= suffix_len) && CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len, suffix.c_str()); } // Formats an int value as "%02d". std::string String::FormatIntWidth2(int value) { std::stringstream ss; ss << std::setfill('0') << std::setw(2) << value; return ss.str(); } // Formats an int value as "%X". std::string String::FormatHexInt(int value) { std::stringstream ss; ss << std::hex << std::uppercase << value; return ss.str(); } // Formats a byte as "%02X". std::string String::FormatByte(unsigned char value) { std::stringstream ss; ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << static_cast(value); return ss.str(); } // Converts the buffer in a stringstream to an std::string, converting NUL // bytes to "\\0" along the way. std::string StringStreamToString(::std::stringstream* ss) { const ::std::string& str = ss->str(); const char* const start = str.c_str(); const char* const end = start + str.length(); std::string result; result.reserve(2 * (end - start)); for (const char* ch = start; ch != end; ++ch) { if (*ch == '\0') { result += "\\0"; // Replaces NUL with "\\0"; } else { result += *ch; } } return result; } // Appends the user-supplied message to the Google-Test-generated message. std::string AppendUserMessage(const std::string& gtest_msg, const Message& user_msg) { // Appends the user message if it's non-empty. const std::string user_msg_string = user_msg.GetString(); if (user_msg_string.empty()) { return gtest_msg; } return gtest_msg + "\n" + user_msg_string; } } // namespace internal // class TestResult // Creates an empty TestResult. TestResult::TestResult() : death_test_count_(0), elapsed_time_(0) { } // D'tor. TestResult::~TestResult() { } // Returns the i-th test part result among all the results. i can // range from 0 to total_part_count() - 1. If i is not in that range, // aborts the program. const TestPartResult& TestResult::GetTestPartResult(int i) const { if (i < 0 || i >= total_part_count()) internal::posix::Abort(); return test_part_results_.at(i); } // Returns the i-th test property. i can range from 0 to // test_property_count() - 1. If i is not in that range, aborts the // program. const TestProperty& TestResult::GetTestProperty(int i) const { if (i < 0 || i >= test_property_count()) internal::posix::Abort(); return test_properties_.at(i); } // Clears the test part results. void TestResult::ClearTestPartResults() { test_part_results_.clear(); } // Adds a test part result to the list. void TestResult::AddTestPartResult(const TestPartResult& test_part_result) { test_part_results_.push_back(test_part_result); } // Adds a test property to the list. If a property with the same key as the // supplied property is already represented, the value of this test_property // replaces the old value for that key. void TestResult::RecordProperty(const std::string& xml_element, const TestProperty& test_property) { if (!ValidateTestProperty(xml_element, test_property)) { return; } internal::MutexLock lock(&test_properites_mutex_); const std::vector::iterator property_with_matching_key = std::find_if(test_properties_.begin(), test_properties_.end(), internal::TestPropertyKeyIs(test_property.key())); if (property_with_matching_key == test_properties_.end()) { test_properties_.push_back(test_property); return; } property_with_matching_key->SetValue(test_property.value()); } // The list of reserved attributes used in the element of XML // output. static const char* const kReservedTestSuitesAttributes[] = { "disabled", "errors", "failures", "name", "random_seed", "tests", "time", "timestamp" }; // The list of reserved attributes used in the element of XML // output. static const char* const kReservedTestSuiteAttributes[] = { "disabled", "errors", "failures", "name", "tests", "time" }; // The list of reserved attributes used in the element of XML output. static const char* const kReservedTestCaseAttributes[] = { "classname", "name", "status", "time", "type_param", "value_param" }; template std::vector ArrayAsVector(const char* const (&array)[kSize]) { return std::vector(array, array + kSize); } static std::vector GetReservedAttributesForElement( const std::string& xml_element) { if (xml_element == "testsuites") { return ArrayAsVector(kReservedTestSuitesAttributes); } else if (xml_element == "testsuite") { return ArrayAsVector(kReservedTestSuiteAttributes); } else if (xml_element == "testcase") { return ArrayAsVector(kReservedTestCaseAttributes); } else { GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element; } // This code is unreachable but some compilers may not realizes that. return std::vector(); } static std::string FormatWordList(const std::vector& words) { Message word_list; for (size_t i = 0; i < words.size(); ++i) { if (i > 0 && words.size() > 2) { word_list << ", "; } if (i == words.size() - 1) { word_list << "and "; } word_list << "'" << words[i] << "'"; } return word_list.GetString(); } bool ValidateTestPropertyName(const std::string& property_name, const std::vector& reserved_names) { if (std::find(reserved_names.begin(), reserved_names.end(), property_name) != reserved_names.end()) { ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name << " (" << FormatWordList(reserved_names) << " are reserved by " << GTEST_NAME_ << ")"; return false; } return true; } // Adds a failure if the key is a reserved attribute of the element named // xml_element. Returns true if the property is valid. bool TestResult::ValidateTestProperty(const std::string& xml_element, const TestProperty& test_property) { return ValidateTestPropertyName(test_property.key(), GetReservedAttributesForElement(xml_element)); } // Clears the object. void TestResult::Clear() { test_part_results_.clear(); test_properties_.clear(); death_test_count_ = 0; elapsed_time_ = 0; } // Returns true iff the test failed. bool TestResult::Failed() const { for (int i = 0; i < total_part_count(); ++i) { if (GetTestPartResult(i).failed()) return true; } return false; } // Returns true iff the test part fatally failed. static bool TestPartFatallyFailed(const TestPartResult& result) { return result.fatally_failed(); } // Returns true iff the test fatally failed. bool TestResult::HasFatalFailure() const { return CountIf(test_part_results_, TestPartFatallyFailed) > 0; } // Returns true iff the test part non-fatally failed. static bool TestPartNonfatallyFailed(const TestPartResult& result) { return result.nonfatally_failed(); } // Returns true iff the test has a non-fatal failure. bool TestResult::HasNonfatalFailure() const { return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0; } // Gets the number of all test parts. This is the sum of the number // of successful test parts and the number of failed test parts. int TestResult::total_part_count() const { return static_cast(test_part_results_.size()); } // Returns the number of the test properties. int TestResult::test_property_count() const { return static_cast(test_properties_.size()); } // class Test // Creates a Test object. // The c'tor saves the values of all Google Test flags. Test::Test() : gtest_flag_saver_(new internal::GTestFlagSaver) { } // The d'tor restores the values of all Google Test flags. Test::~Test() { delete gtest_flag_saver_; } // Sets up the test fixture. // // A sub-class may override this. void Test::SetUp() { } // Tears down the test fixture. // // A sub-class may override this. void Test::TearDown() { } // Allows user supplied key value pairs to be recorded for later output. void Test::RecordProperty(const std::string& key, const std::string& value) { UnitTest::GetInstance()->RecordProperty(key, value); } // Allows user supplied key value pairs to be recorded for later output. void Test::RecordProperty(const std::string& key, int value) { Message value_message; value_message << value; RecordProperty(key, value_message.GetString().c_str()); } namespace internal { void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message) { // This function is a friend of UnitTest and as such has access to // AddTestPartResult. UnitTest::GetInstance()->AddTestPartResult( result_type, NULL, // No info about the source file where the exception occurred. -1, // We have no info on which line caused the exception. message, ""); // No stack trace, either. } } // namespace internal // Google Test requires all tests in the same test case to use the same test // fixture class. This function checks if the current test has the // same fixture class as the first test in the current test case. If // yes, it returns true; otherwise it generates a Google Test failure and // returns false. bool Test::HasSameFixtureClass() { internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); const TestCase* const test_case = impl->current_test_case(); // Info about the first test in the current test case. const TestInfo* const first_test_info = test_case->test_info_list()[0]; const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_; const char* const first_test_name = first_test_info->name(); // Info about the current test. const TestInfo* const this_test_info = impl->current_test_info(); const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_; const char* const this_test_name = this_test_info->name(); if (this_fixture_id != first_fixture_id) { // Is the first test defined using TEST? const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); // Is this test defined using TEST? const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); if (first_is_TEST || this_is_TEST) { // The user mixed TEST and TEST_F in this test case - we'll tell // him/her how to fix it. // Gets the name of the TEST and the name of the TEST_F. Note // that first_is_TEST and this_is_TEST cannot both be true, as // the fixture IDs are different for the two tests. const char* const TEST_name = first_is_TEST ? first_test_name : this_test_name; const char* const TEST_F_name = first_is_TEST ? this_test_name : first_test_name; ADD_FAILURE() << "All tests in the same test case must use the same test fixture\n" << "class, so mixing TEST_F and TEST in the same test case is\n" << "illegal. In test case " << this_test_info->test_case_name() << ",\n" << "test " << TEST_F_name << " is defined using TEST_F but\n" << "test " << TEST_name << " is defined using TEST. You probably\n" << "want to change the TEST to TEST_F or move it to another test\n" << "case."; } else { // The user defined two fixture classes with the same name in // two namespaces - we'll tell him/her how to fix it. ADD_FAILURE() << "All tests in the same test case must use the same test fixture\n" << "class. However, in test case " << this_test_info->test_case_name() << ",\n" << "you defined test " << first_test_name << " and test " << this_test_name << "\n" << "using two different test fixture classes. This can happen if\n" << "the two classes are from different namespaces or translation\n" << "units and have the same name. You should probably rename one\n" << "of the classes to put the tests into different test cases."; } return false; } return true; } #if GTEST_HAS_SEH // Adds an "exception thrown" fatal failure to the current test. This // function returns its result via an output parameter pointer because VC++ // prohibits creation of objects with destructors on stack in functions // using __try (see error C2712). static std::string* FormatSehExceptionMessage(DWORD exception_code, const char* location) { Message message; message << "SEH exception with code 0x" << std::setbase(16) << exception_code << std::setbase(10) << " thrown in " << location << "."; return new std::string(message.GetString()); } #endif // GTEST_HAS_SEH namespace internal { #if GTEST_HAS_EXCEPTIONS // Adds an "exception thrown" fatal failure to the current test. static std::string FormatCxxExceptionMessage(const char* description, const char* location) { Message message; if (description != NULL) { message << "C++ exception with description \"" << description << "\""; } else { message << "Unknown C++ exception"; } message << " thrown in " << location << "."; return message.GetString(); } static std::string PrintTestPartResultToString( const TestPartResult& test_part_result); GoogleTestFailureException::GoogleTestFailureException( const TestPartResult& failure) : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {} #endif // GTEST_HAS_EXCEPTIONS // We put these helper functions in the internal namespace as IBM's xlC // compiler rejects the code if they were declared static. // Runs the given method and handles SEH exceptions it throws, when // SEH is supported; returns the 0-value for type Result in case of an // SEH exception. (Microsoft compilers cannot handle SEH and C++ // exceptions in the same function. Therefore, we provide a separate // wrapper function for handling SEH exceptions.) template Result HandleSehExceptionsInMethodIfSupported( T* object, Result (T::*method)(), const char* location) { #if GTEST_HAS_SEH __try { return (object->*method)(); } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT GetExceptionCode())) { // We create the exception message on the heap because VC++ prohibits // creation of objects with destructors on stack in functions using __try // (see error C2712). std::string* exception_message = FormatSehExceptionMessage( GetExceptionCode(), location); internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure, *exception_message); delete exception_message; return static_cast(0); } #else (void)location; return (object->*method)(); #endif // GTEST_HAS_SEH } // Runs the given method and catches and reports C++ and/or SEH-style // exceptions, if they are supported; returns the 0-value for type // Result in case of an SEH exception. template Result HandleExceptionsInMethodIfSupported( T* object, Result (T::*method)(), const char* location) { // NOTE: The user code can affect the way in which Google Test handles // exceptions by setting GTEST_FLAG(catch_exceptions), but only before // RUN_ALL_TESTS() starts. It is technically possible to check the flag // after the exception is caught and either report or re-throw the // exception based on the flag's value: // // try { // // Perform the test method. // } catch (...) { // if (GTEST_FLAG(catch_exceptions)) // // Report the exception as failure. // else // throw; // Re-throws the original exception. // } // // However, the purpose of this flag is to allow the program to drop into // the debugger when the exception is thrown. On most platforms, once the // control enters the catch block, the exception origin information is // lost and the debugger will stop the program at the point of the // re-throw in this function -- instead of at the point of the original // throw statement in the code under test. For this reason, we perform // the check early, sacrificing the ability to affect Google Test's // exception handling in the method where the exception is thrown. if (internal::GetUnitTestImpl()->catch_exceptions()) { #if GTEST_HAS_EXCEPTIONS try { return HandleSehExceptionsInMethodIfSupported(object, method, location); } catch (const internal::GoogleTestFailureException&) { // NOLINT // This exception type can only be thrown by a failed Google // Test assertion with the intention of letting another testing // framework catch it. Therefore we just re-throw it. throw; } catch (const std::exception& e) { // NOLINT internal::ReportFailureInUnknownLocation( TestPartResult::kFatalFailure, FormatCxxExceptionMessage(e.what(), location)); } catch (...) { // NOLINT internal::ReportFailureInUnknownLocation( TestPartResult::kFatalFailure, FormatCxxExceptionMessage(NULL, location)); } return static_cast(0); #else return HandleSehExceptionsInMethodIfSupported(object, method, location); #endif // GTEST_HAS_EXCEPTIONS } else { return (object->*method)(); } } } // namespace internal // Runs the test and updates the test result. void Test::Run() { if (!HasSameFixtureClass()) return; internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()"); // We will run the test only if SetUp() was successful. if (!HasFatalFailure()) { impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( this, &Test::TestBody, "the test body"); } // However, we want to clean up as much as possible. Hence we will // always call TearDown(), even if SetUp() or the test body has // failed. impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( this, &Test::TearDown, "TearDown()"); } // Returns true iff the current test has a fatal failure. bool Test::HasFatalFailure() { return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure(); } // Returns true iff the current test has a non-fatal failure. bool Test::HasNonfatalFailure() { return internal::GetUnitTestImpl()->current_test_result()-> HasNonfatalFailure(); } // class TestInfo // Constructs a TestInfo object. It assumes ownership of the test factory // object. TestInfo::TestInfo(const std::string& a_test_case_name, const std::string& a_name, const char* a_type_param, const char* a_value_param, internal::TypeId fixture_class_id, internal::TestFactoryBase* factory) : test_case_name_(a_test_case_name), name_(a_name), type_param_(a_type_param ? new std::string(a_type_param) : NULL), value_param_(a_value_param ? new std::string(a_value_param) : NULL), fixture_class_id_(fixture_class_id), should_run_(false), is_disabled_(false), matches_filter_(false), factory_(factory), result_() {} // Destructs a TestInfo object. TestInfo::~TestInfo() { delete factory_; } namespace internal { // Creates a new TestInfo object and registers it with Google Test; // returns the created object. // // Arguments: // // test_case_name: name of the test case // name: name of the test // type_param: the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. // value_param: text representation of the test's value parameter, // or NULL if this is not a value-parameterized test. // fixture_class_id: ID of the test fixture class // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case // factory: pointer to the factory that creates a test object. // The newly created TestInfo instance will assume // ownership of the factory object. TestInfo* MakeAndRegisterTestInfo( const char* test_case_name, const char* name, const char* type_param, const char* value_param, TypeId fixture_class_id, SetUpTestCaseFunc set_up_tc, TearDownTestCaseFunc tear_down_tc, TestFactoryBase* factory) { TestInfo* const test_info = new TestInfo(test_case_name, name, type_param, value_param, fixture_class_id, factory); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); return test_info; } #if GTEST_HAS_PARAM_TEST void ReportInvalidTestCaseType(const char* test_case_name, const char* file, int line) { Message errors; errors << "Attempted redefinition of test case " << test_case_name << ".\n" << "All tests in the same test case must use the same test fixture\n" << "class. However, in test case " << test_case_name << ", you tried\n" << "to define a test using a fixture class different from the one\n" << "used earlier. This can happen if the two fixture classes are\n" << "from different namespaces and have the same name. You should\n" << "probably rename one of the classes to put the tests into different\n" << "test cases."; fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), errors.GetString().c_str()); } #endif // GTEST_HAS_PARAM_TEST } // namespace internal namespace { // A predicate that checks the test name of a TestInfo against a known // value. // // This is used for implementation of the TestCase class only. We put // it in the anonymous namespace to prevent polluting the outer // namespace. // // TestNameIs is copyable. class TestNameIs { public: // Constructor. // // TestNameIs has NO default constructor. explicit TestNameIs(const char* name) : name_(name) {} // Returns true iff the test name of test_info matches name_. bool operator()(const TestInfo * test_info) const { return test_info && test_info->name() == name_; } private: std::string name_; }; } // namespace namespace internal { // This method expands all parameterized tests registered with macros TEST_P // and INSTANTIATE_TEST_CASE_P into regular tests and registers those. // This will be done just once during the program runtime. void UnitTestImpl::RegisterParameterizedTests() { #if GTEST_HAS_PARAM_TEST if (!parameterized_tests_registered_) { parameterized_test_registry_.RegisterTests(); parameterized_tests_registered_ = true; } #endif } } // namespace internal // Creates the test object, runs it, records its result, and then // deletes it. void TestInfo::Run() { if (!should_run_) return; // Tells UnitTest where to store test result. internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->set_current_test_info(this); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); // Notifies the unit test event listeners that a test is about to start. repeater->OnTestStart(*this); const TimeInMillis start = internal::GetTimeInMillis(); impl->os_stack_trace_getter()->UponLeavingGTest(); // Creates the test object. Test* const test = internal::HandleExceptionsInMethodIfSupported( factory_, &internal::TestFactoryBase::CreateTest, "the test fixture's constructor"); // Runs the test only if the test object was created and its // constructor didn't generate a fatal failure. if ((test != NULL) && !Test::HasFatalFailure()) { // This doesn't throw as all user code that can throw are wrapped into // exception handling code. test->Run(); } // Deletes the test object. impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( test, &Test::DeleteSelf_, "the test fixture's destructor"); result_.set_elapsed_time(internal::GetTimeInMillis() - start); // Notifies the unit test event listener that a test has just finished. repeater->OnTestEnd(*this); // Tells UnitTest to stop associating assertion results to this // test. impl->set_current_test_info(NULL); } // class TestCase // Gets the number of successful tests in this test case. int TestCase::successful_test_count() const { return CountIf(test_info_list_, TestPassed); } // Gets the number of failed tests in this test case. int TestCase::failed_test_count() const { return CountIf(test_info_list_, TestFailed); } // Gets the number of disabled tests that will be reported in the XML report. int TestCase::reportable_disabled_test_count() const { return CountIf(test_info_list_, TestReportableDisabled); } // Gets the number of disabled tests in this test case. int TestCase::disabled_test_count() const { return CountIf(test_info_list_, TestDisabled); } // Gets the number of tests to be printed in the XML report. int TestCase::reportable_test_count() const { return CountIf(test_info_list_, TestReportable); } // Get the number of tests in this test case that should run. int TestCase::test_to_run_count() const { return CountIf(test_info_list_, ShouldRunTest); } // Gets the number of all tests. int TestCase::total_test_count() const { return static_cast(test_info_list_.size()); } // Creates a TestCase with the given name. // // Arguments: // // name: name of the test case // a_type_param: the name of the test case's type parameter, or NULL if // this is not a typed or a type-parameterized test case. // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case TestCase::TestCase(const char* a_name, const char* a_type_param, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc) : name_(a_name), type_param_(a_type_param ? new std::string(a_type_param) : NULL), set_up_tc_(set_up_tc), tear_down_tc_(tear_down_tc), should_run_(false), elapsed_time_(0) { } // Destructor of TestCase. TestCase::~TestCase() { // Deletes every Test in the collection. ForEach(test_info_list_, internal::Delete); } // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. const TestInfo* TestCase::GetTestInfo(int i) const { const int index = GetElementOr(test_indices_, i, -1); return index < 0 ? NULL : test_info_list_[index]; } // Returns the i-th test among all the tests. i can range from 0 to // total_test_count() - 1. If i is not in that range, returns NULL. TestInfo* TestCase::GetMutableTestInfo(int i) { const int index = GetElementOr(test_indices_, i, -1); return index < 0 ? NULL : test_info_list_[index]; } // Adds a test to this test case. Will delete the test upon // destruction of the TestCase object. void TestCase::AddTestInfo(TestInfo * test_info) { test_info_list_.push_back(test_info); test_indices_.push_back(static_cast(test_indices_.size())); } // Runs every test in this TestCase. void TestCase::Run() { if (!should_run_) return; internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->set_current_test_case(this); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); repeater->OnTestCaseStart(*this); impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); const internal::TimeInMillis start = internal::GetTimeInMillis(); for (int i = 0; i < total_test_count(); i++) { GetMutableTestInfo(i)->Run(); } elapsed_time_ = internal::GetTimeInMillis() - start; impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); repeater->OnTestCaseEnd(*this); impl->set_current_test_case(NULL); } // Clears the results of all tests in this test case. void TestCase::ClearResult() { ad_hoc_test_result_.Clear(); ForEach(test_info_list_, TestInfo::ClearTestResult); } // Shuffles the tests in this test case. void TestCase::ShuffleTests(internal::Random* random) { Shuffle(random, &test_indices_); } // Restores the test order to before the first shuffle. void TestCase::UnshuffleTests() { for (size_t i = 0; i < test_indices_.size(); i++) { test_indices_[i] = static_cast(i); } } // Formats a countable noun. Depending on its quantity, either the // singular form or the plural form is used. e.g. // // FormatCountableNoun(1, "formula", "formuli") returns "1 formula". // FormatCountableNoun(5, "book", "books") returns "5 books". static std::string FormatCountableNoun(int count, const char * singular_form, const char * plural_form) { return internal::StreamableToString(count) + " " + (count == 1 ? singular_form : plural_form); } // Formats the count of tests. static std::string FormatTestCount(int test_count) { return FormatCountableNoun(test_count, "test", "tests"); } // Formats the count of test cases. static std::string FormatTestCaseCount(int test_case_count) { return FormatCountableNoun(test_case_count, "test case", "test cases"); } // Converts a TestPartResult::Type enum to human-friendly string // representation. Both kNonFatalFailure and kFatalFailure are translated // to "Failure", as the user usually doesn't care about the difference // between the two when viewing the test result. static const char * TestPartResultTypeToString(TestPartResult::Type type) { switch (type) { case TestPartResult::kSuccess: return "Success"; case TestPartResult::kNonFatalFailure: case TestPartResult::kFatalFailure: #ifdef _MSC_VER return "error: "; #else return "Failure\n"; #endif default: return "Unknown result type"; } } namespace internal { // Prints a TestPartResult to an std::string. static std::string PrintTestPartResultToString( const TestPartResult& test_part_result) { return (Message() << internal::FormatFileLocation(test_part_result.file_name(), test_part_result.line_number()) << " " << TestPartResultTypeToString(test_part_result.type()) << test_part_result.message()).GetString(); } // Prints a TestPartResult. static void PrintTestPartResult(const TestPartResult& test_part_result) { const std::string& result = PrintTestPartResultToString(test_part_result); printf("%s\n", result.c_str()); fflush(stdout); // If the test program runs in Visual Studio or a debugger, the // following statements add the test part result message to the Output // window such that the user can double-click on it to jump to the // corresponding source code location; otherwise they do nothing. #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE // We don't call OutputDebugString*() on Windows Mobile, as printing // to stdout is done by OutputDebugString() there already - we don't // want the same message printed twice. ::OutputDebugStringA(result.c_str()); ::OutputDebugStringA("\n"); #endif } // class PrettyUnitTestResultPrinter enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE // Returns the character attribute for the given color. WORD GetColorAttribute(GTestColor color) { switch (color) { case COLOR_RED: return FOREGROUND_RED; case COLOR_GREEN: return FOREGROUND_GREEN; case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN; default: return 0; } } #else // Returns the ANSI color code for the given color. COLOR_DEFAULT is // an invalid input. const char* GetAnsiColorCode(GTestColor color) { switch (color) { case COLOR_RED: return "1"; case COLOR_GREEN: return "2"; case COLOR_YELLOW: return "3"; default: return NULL; }; } #endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE // Returns true iff Google Test should use colors in the output. bool ShouldUseColor(bool stdout_is_tty) { const char* const gtest_color = GTEST_FLAG(color).c_str(); if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) { #if GTEST_OS_WINDOWS // On Windows the TERM variable is usually not set, but the // console there does support colors. return stdout_is_tty; #else // On non-Windows platforms, we rely on the TERM variable. const char* const term = posix::GetEnv("TERM"); const bool term_supports_color = String::CStringEquals(term, "xterm") || String::CStringEquals(term, "xterm-color") || String::CStringEquals(term, "xterm-256color") || String::CStringEquals(term, "screen") || String::CStringEquals(term, "screen-256color") || String::CStringEquals(term, "linux") || String::CStringEquals(term, "cygwin"); return stdout_is_tty && term_supports_color; #endif // GTEST_OS_WINDOWS } return String::CaseInsensitiveCStringEquals(gtest_color, "yes") || String::CaseInsensitiveCStringEquals(gtest_color, "true") || String::CaseInsensitiveCStringEquals(gtest_color, "t") || String::CStringEquals(gtest_color, "1"); // We take "yes", "true", "t", and "1" as meaning "yes". If the // value is neither one of these nor "auto", we treat it as "no" to // be conservative. } // Helpers for printing colored strings to stdout. Note that on Windows, we // cannot simply emit special characters and have the terminal change colors. // This routine must actually emit the characters rather than return a string // that would be colored when printed, as can be done on Linux. void ColoredPrintf(GTestColor color, const char* fmt, ...) { va_list args; va_start(args, fmt); #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS const bool use_color = false; #else static const bool in_color_mode = ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); const bool use_color = in_color_mode && (color != COLOR_DEFAULT); #endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS // The '!= 0' comparison is necessary to satisfy MSVC 7.1. if (!use_color) { vprintf(fmt, args); va_end(args); return; } #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); // Gets the current text color. CONSOLE_SCREEN_BUFFER_INFO buffer_info; GetConsoleScreenBufferInfo(stdout_handle, &buffer_info); const WORD old_color_attrs = buffer_info.wAttributes; // We need to flush the stream buffers into the console before each // SetConsoleTextAttribute call lest it affect the text that is already // printed but has not yet reached the console. fflush(stdout); SetConsoleTextAttribute(stdout_handle, GetColorAttribute(color) | FOREGROUND_INTENSITY); vprintf(fmt, args); fflush(stdout); // Restores the text color. SetConsoleTextAttribute(stdout_handle, old_color_attrs); #else printf("\033[0;3%sm", GetAnsiColorCode(color)); vprintf(fmt, args); printf("\033[m"); // Resets the terminal to default. #endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE va_end(args); } // Text printed in Google Test's text output and --gunit_list_tests // output to label the type parameter and value parameter for a test. static const char kTypeParamLabel[] = "TypeParam"; static const char kValueParamLabel[] = "GetParam()"; void PrintFullTestCommentIfPresent(const TestInfo& test_info) { const char* const type_param = test_info.type_param(); const char* const value_param = test_info.value_param(); if (type_param != NULL || value_param != NULL) { printf(", where "); if (type_param != NULL) { printf("%s = %s", kTypeParamLabel, type_param); if (value_param != NULL) printf(" and "); } if (value_param != NULL) { printf("%s = %s", kValueParamLabel, value_param); } } } // This class implements the TestEventListener interface. // // Class PrettyUnitTestResultPrinter is copyable. class PrettyUnitTestResultPrinter : public TestEventListener { public: PrettyUnitTestResultPrinter() {} static void PrintTestName(const char * test_case, const char * test) { printf("%s.%s", test_case, test); } // The following methods override what's in the TestEventListener class. virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} virtual void OnTestCaseStart(const TestCase& test_case); virtual void OnTestStart(const TestInfo& test_info); virtual void OnTestPartResult(const TestPartResult& result); virtual void OnTestEnd(const TestInfo& test_info); virtual void OnTestCaseEnd(const TestCase& test_case); virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} private: static void PrintFailedTests(const UnitTest& unit_test); }; // Fired before each iteration of tests starts. void PrettyUnitTestResultPrinter::OnTestIterationStart( const UnitTest& unit_test, int iteration) { if (GTEST_FLAG(repeat) != 1) printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1); const char* const filter = GTEST_FLAG(filter).c_str(); // Prints the filter if it's not *. This reminds the user that some // tests may be skipped. if (!String::CStringEquals(filter, kUniversalFilter)) { ColoredPrintf(COLOR_YELLOW, "Note: %s filter = %s\n", GTEST_NAME_, filter); } if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) { const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1); ColoredPrintf(COLOR_YELLOW, "Note: This is test shard %d of %s.\n", static_cast(shard_index) + 1, internal::posix::GetEnv(kTestTotalShards)); } if (GTEST_FLAG(shuffle)) { ColoredPrintf(COLOR_YELLOW, "Note: Randomizing tests' orders with a seed of %d .\n", unit_test.random_seed()); } ColoredPrintf(COLOR_GREEN, "[==========] "); printf("Running %s from %s.\n", FormatTestCount(unit_test.test_to_run_count()).c_str(), FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); fflush(stdout); } void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart( const UnitTest& /*unit_test*/) { ColoredPrintf(COLOR_GREEN, "[----------] "); printf("Global test environment set-up.\n"); fflush(stdout); } void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) { const std::string counts = FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); ColoredPrintf(COLOR_GREEN, "[----------] "); printf("%s from %s", counts.c_str(), test_case.name()); if (test_case.type_param() == NULL) { printf("\n"); } else { printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param()); } fflush(stdout); } void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) { ColoredPrintf(COLOR_GREEN, "[ RUN ] "); PrintTestName(test_info.test_case_name(), test_info.name()); printf("\n"); fflush(stdout); } // Called after an assertion failure. void PrettyUnitTestResultPrinter::OnTestPartResult( const TestPartResult& result) { // If the test part succeeded, we don't need to do anything. if (result.type() == TestPartResult::kSuccess) return; // Print failure message from the assertion (e.g. expected this and got that). PrintTestPartResult(result); fflush(stdout); } void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) { if (test_info.result()->Passed()) { ColoredPrintf(COLOR_GREEN, "[ OK ] "); } else { ColoredPrintf(COLOR_RED, "[ FAILED ] "); } PrintTestName(test_info.test_case_name(), test_info.name()); if (test_info.result()->Failed()) PrintFullTestCommentIfPresent(test_info); if (GTEST_FLAG(print_time)) { printf(" (%s ms)\n", internal::StreamableToString( test_info.result()->elapsed_time()).c_str()); } else { printf("\n"); } fflush(stdout); } void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) { if (!GTEST_FLAG(print_time)) return; const std::string counts = FormatCountableNoun(test_case.test_to_run_count(), "test", "tests"); ColoredPrintf(COLOR_GREEN, "[----------] "); printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_case.name(), internal::StreamableToString(test_case.elapsed_time()).c_str()); fflush(stdout); } void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart( const UnitTest& /*unit_test*/) { ColoredPrintf(COLOR_GREEN, "[----------] "); printf("Global test environment tear-down\n"); fflush(stdout); } // Internal helper for printing the list of failed tests. void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) { const int failed_test_count = unit_test.failed_test_count(); if (failed_test_count == 0) { return; } for (int i = 0; i < unit_test.total_test_case_count(); ++i) { const TestCase& test_case = *unit_test.GetTestCase(i); if (!test_case.should_run() || (test_case.failed_test_count() == 0)) { continue; } for (int j = 0; j < test_case.total_test_count(); ++j) { const TestInfo& test_info = *test_case.GetTestInfo(j); if (!test_info.should_run() || test_info.result()->Passed()) { continue; } ColoredPrintf(COLOR_RED, "[ FAILED ] "); printf("%s.%s", test_case.name(), test_info.name()); PrintFullTestCommentIfPresent(test_info); printf("\n"); } } } void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, int /*iteration*/) { ColoredPrintf(COLOR_GREEN, "[==========] "); printf("%s from %s ran.", FormatTestCount(unit_test.test_to_run_count()).c_str(), FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str()); if (GTEST_FLAG(print_time)) { printf(" (%s ms total)", internal::StreamableToString(unit_test.elapsed_time()).c_str()); } printf("\n"); ColoredPrintf(COLOR_GREEN, "[ PASSED ] "); printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str()); int num_failures = unit_test.failed_test_count(); if (!unit_test.Passed()) { const int failed_test_count = unit_test.failed_test_count(); ColoredPrintf(COLOR_RED, "[ FAILED ] "); printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str()); PrintFailedTests(unit_test); printf("\n%2d FAILED %s\n", num_failures, num_failures == 1 ? "TEST" : "TESTS"); } int num_disabled = unit_test.reportable_disabled_test_count(); if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) { if (!num_failures) { printf("\n"); // Add a spacer if no FAILURE banner is displayed. } ColoredPrintf(COLOR_YELLOW, " YOU HAVE %d DISABLED %s\n\n", num_disabled, num_disabled == 1 ? "TEST" : "TESTS"); } // Ensure that Google Test output is printed before, e.g., heapchecker output. fflush(stdout); } // End PrettyUnitTestResultPrinter // class TestEventRepeater // // This class forwards events to other event listeners. class TestEventRepeater : public TestEventListener { public: TestEventRepeater() : forwarding_enabled_(true) {} virtual ~TestEventRepeater(); void Append(TestEventListener *listener); TestEventListener* Release(TestEventListener* listener); // Controls whether events will be forwarded to listeners_. Set to false // in death test child processes. bool forwarding_enabled() const { return forwarding_enabled_; } void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; } virtual void OnTestProgramStart(const UnitTest& unit_test); virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration); virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test); virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test); virtual void OnTestCaseStart(const TestCase& test_case); virtual void OnTestStart(const TestInfo& test_info); virtual void OnTestPartResult(const TestPartResult& result); virtual void OnTestEnd(const TestInfo& test_info); virtual void OnTestCaseEnd(const TestCase& test_case); virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test); virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test); virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); virtual void OnTestProgramEnd(const UnitTest& unit_test); private: // Controls whether events will be forwarded to listeners_. Set to false // in death test child processes. bool forwarding_enabled_; // The list of listeners that receive events. std::vector listeners_; GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater); }; TestEventRepeater::~TestEventRepeater() { ForEach(listeners_, Delete); } void TestEventRepeater::Append(TestEventListener *listener) { listeners_.push_back(listener); } // TODO(vladl@google.com): Factor the search functionality into Vector::Find. TestEventListener* TestEventRepeater::Release(TestEventListener *listener) { for (size_t i = 0; i < listeners_.size(); ++i) { if (listeners_[i] == listener) { listeners_.erase(listeners_.begin() + i); return listener; } } return NULL; } // Since most methods are very similar, use macros to reduce boilerplate. // This defines a member that forwards the call to all listeners. #define GTEST_REPEATER_METHOD_(Name, Type) \ void TestEventRepeater::Name(const Type& parameter) { \ if (forwarding_enabled_) { \ for (size_t i = 0; i < listeners_.size(); i++) { \ listeners_[i]->Name(parameter); \ } \ } \ } // This defines a member that forwards the call to all listeners in reverse // order. #define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \ void TestEventRepeater::Name(const Type& parameter) { \ if (forwarding_enabled_) { \ for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { \ listeners_[i]->Name(parameter); \ } \ } \ } GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest) GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest) GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase) GTEST_REPEATER_METHOD_(OnTestStart, TestInfo) GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult) GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest) GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest) GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest) GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo) GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase) GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest) #undef GTEST_REPEATER_METHOD_ #undef GTEST_REVERSE_REPEATER_METHOD_ void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test, int iteration) { if (forwarding_enabled_) { for (size_t i = 0; i < listeners_.size(); i++) { listeners_[i]->OnTestIterationStart(unit_test, iteration); } } } void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test, int iteration) { if (forwarding_enabled_) { for (int i = static_cast(listeners_.size()) - 1; i >= 0; i--) { listeners_[i]->OnTestIterationEnd(unit_test, iteration); } } } // End TestEventRepeater // This class generates an XML output file. class XmlUnitTestResultPrinter : public EmptyTestEventListener { public: explicit XmlUnitTestResultPrinter(const char* output_file); virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration); private: // Is c a whitespace character that is normalized to a space character // when it appears in an XML attribute value? static bool IsNormalizableWhitespace(char c) { return c == 0x9 || c == 0xA || c == 0xD; } // May c appear in a well-formed XML document? static bool IsValidXmlCharacter(char c) { return IsNormalizableWhitespace(c) || c >= 0x20; } // Returns an XML-escaped copy of the input string str. If // is_attribute is true, the text is meant to appear as an attribute // value, and normalizable whitespace is preserved by replacing it // with character references. static std::string EscapeXml(const std::string& str, bool is_attribute); // Returns the given string with all characters invalid in XML removed. static std::string RemoveInvalidXmlCharacters(const std::string& str); // Convenience wrapper around EscapeXml when str is an attribute value. static std::string EscapeXmlAttribute(const std::string& str) { return EscapeXml(str, true); } // Convenience wrapper around EscapeXml when str is not an attribute value. static std::string EscapeXmlText(const char* str) { return EscapeXml(str, false); } // Verifies that the given attribute belongs to the given element and // streams the attribute as XML. static void OutputXmlAttribute(std::ostream* stream, const std::string& element_name, const std::string& name, const std::string& value); // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. static void OutputXmlCDataSection(::std::ostream* stream, const char* data); // Streams an XML representation of a TestInfo object. static void OutputXmlTestInfo(::std::ostream* stream, const char* test_case_name, const TestInfo& test_info); // Prints an XML representation of a TestCase object static void PrintXmlTestCase(::std::ostream* stream, const TestCase& test_case); // Prints an XML summary of unit_test to output stream out. static void PrintXmlUnitTest(::std::ostream* stream, const UnitTest& unit_test); // Produces a string representing the test properties in a result as space // delimited XML attributes based on the property key="value" pairs. // When the std::string is not empty, it includes a space at the beginning, // to delimit this attribute from prior attributes. static std::string TestPropertiesAsXmlAttributes(const TestResult& result); // The output file. const std::string output_file_; GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter); }; // Creates a new XmlUnitTestResultPrinter. XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file) : output_file_(output_file) { if (output_file_.c_str() == NULL || output_file_.empty()) { fprintf(stderr, "XML output file may not be null\n"); fflush(stderr); exit(EXIT_FAILURE); } } // Called after the unit test ends. void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test, int /*iteration*/) { FILE* xmlout = NULL; FilePath output_file(output_file_); FilePath output_dir(output_file.RemoveFileName()); if (output_dir.CreateDirectoriesRecursively()) { xmlout = posix::FOpen(output_file_.c_str(), "w"); } if (xmlout == NULL) { // TODO(wan): report the reason of the failure. // // We don't do it for now as: // // 1. There is no urgent need for it. // 2. It's a bit involved to make the errno variable thread-safe on // all three operating systems (Linux, Windows, and Mac OS). // 3. To interpret the meaning of errno in a thread-safe way, // we need the strerror_r() function, which is not available on // Windows. fprintf(stderr, "Unable to open file \"%s\"\n", output_file_.c_str()); fflush(stderr); exit(EXIT_FAILURE); } std::stringstream stream; PrintXmlUnitTest(&stream, unit_test); fprintf(xmlout, "%s", StringStreamToString(&stream).c_str()); fclose(xmlout); } // Returns an XML-escaped copy of the input string str. If is_attribute // is true, the text is meant to appear as an attribute value, and // normalizable whitespace is preserved by replacing it with character // references. // // Invalid XML characters in str, if any, are stripped from the output. // It is expected that most, if not all, of the text processed by this // module will consist of ordinary English text. // If this module is ever modified to produce version 1.1 XML output, // most invalid characters can be retained using character references. // TODO(wan): It might be nice to have a minimally invasive, human-readable // escaping scheme for invalid characters, rather than dropping them. std::string XmlUnitTestResultPrinter::EscapeXml( const std::string& str, bool is_attribute) { Message m; for (size_t i = 0; i < str.size(); ++i) { const char ch = str[i]; switch (ch) { case '<': m << "<"; break; case '>': m << ">"; break; case '&': m << "&"; break; case '\'': if (is_attribute) m << "'"; else m << '\''; break; case '"': if (is_attribute) m << """; else m << '"'; break; default: if (IsValidXmlCharacter(ch)) { if (is_attribute && IsNormalizableWhitespace(ch)) m << "&#x" << String::FormatByte(static_cast(ch)) << ";"; else m << ch; } break; } } return m.GetString(); } // Returns the given string with all characters invalid in XML removed. // Currently invalid characters are dropped from the string. An // alternative is to replace them with certain characters such as . or ?. std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters( const std::string& str) { std::string output; output.reserve(str.size()); for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) if (IsValidXmlCharacter(*it)) output.push_back(*it); return output; } // The following routines generate an XML representation of a UnitTest // object. // // This is how Google Test concepts map to the DTD: // // <-- corresponds to a UnitTest object // <-- corresponds to a TestCase object // <-- corresponds to a TestInfo object // ... // ... // ... // <-- individual assertion failures // // // // Formats the given time in milliseconds as seconds. std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { ::std::stringstream ss; ss << ms/1000.0; return ss.str(); } // Converts the given epoch time in milliseconds to a date string in the ISO // 8601 format, without the timezone information. std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { // Using non-reentrant version as localtime_r is not portable. time_t seconds = static_cast(ms / 1000); #ifdef _MSC_VER # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4996) // Temporarily disables warning 4996 // (function or variable may be unsafe). const struct tm* const time_struct = localtime(&seconds); // NOLINT # pragma warning(pop) // Restores the warning state again. #else const struct tm* const time_struct = localtime(&seconds); // NOLINT #endif if (time_struct == NULL) return ""; // Invalid ms value // YYYY-MM-DDThh:mm:ss return StreamableToString(time_struct->tm_year + 1900) + "-" + String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + String::FormatIntWidth2(time_struct->tm_mday) + "T" + String::FormatIntWidth2(time_struct->tm_hour) + ":" + String::FormatIntWidth2(time_struct->tm_min) + ":" + String::FormatIntWidth2(time_struct->tm_sec); } // Streams an XML CDATA section, escaping invalid CDATA sequences as needed. void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream, const char* data) { const char* segment = data; *stream << ""); if (next_segment != NULL) { stream->write( segment, static_cast(next_segment - segment)); *stream << "]]>]]>"); } else { *stream << segment; break; } } *stream << "]]>"; } void XmlUnitTestResultPrinter::OutputXmlAttribute( std::ostream* stream, const std::string& element_name, const std::string& name, const std::string& value) { const std::vector& allowed_names = GetReservedAttributesForElement(element_name); GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) != allowed_names.end()) << "Attribute " << name << " is not allowed for element <" << element_name << ">."; *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\""; } // Prints an XML representation of a TestInfo object. // TODO(wan): There is also value in printing properties with the plain printer. void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream, const char* test_case_name, const TestInfo& test_info) { const TestResult& result = *test_info.result(); const std::string kTestcase = "testcase"; *stream << " \n"; } const string location = internal::FormatCompilerIndependentFileLocation( part.file_name(), part.line_number()); const string summary = location + "\n" + part.summary(); *stream << " "; const string detail = location + "\n" + part.message(); OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str()); *stream << "\n"; } } if (failures == 0) *stream << " />\n"; else *stream << " \n"; } // Prints an XML representation of a TestCase object void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream, const TestCase& test_case) { const std::string kTestsuite = "testsuite"; *stream << " <" << kTestsuite; OutputXmlAttribute(stream, kTestsuite, "name", test_case.name()); OutputXmlAttribute(stream, kTestsuite, "tests", StreamableToString(test_case.reportable_test_count())); OutputXmlAttribute(stream, kTestsuite, "failures", StreamableToString(test_case.failed_test_count())); OutputXmlAttribute( stream, kTestsuite, "disabled", StreamableToString(test_case.reportable_disabled_test_count())); OutputXmlAttribute(stream, kTestsuite, "errors", "0"); OutputXmlAttribute(stream, kTestsuite, "time", FormatTimeInMillisAsSeconds(test_case.elapsed_time())); *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result()) << ">\n"; for (int i = 0; i < test_case.total_test_count(); ++i) { if (test_case.GetTestInfo(i)->is_reportable()) OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i)); } *stream << " \n"; } // Prints an XML summary of unit_test to output stream out. void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream, const UnitTest& unit_test) { const std::string kTestsuites = "testsuites"; *stream << "\n"; *stream << "<" << kTestsuites; OutputXmlAttribute(stream, kTestsuites, "tests", StreamableToString(unit_test.reportable_test_count())); OutputXmlAttribute(stream, kTestsuites, "failures", StreamableToString(unit_test.failed_test_count())); OutputXmlAttribute( stream, kTestsuites, "disabled", StreamableToString(unit_test.reportable_disabled_test_count())); OutputXmlAttribute(stream, kTestsuites, "errors", "0"); OutputXmlAttribute( stream, kTestsuites, "timestamp", FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp())); OutputXmlAttribute(stream, kTestsuites, "time", FormatTimeInMillisAsSeconds(unit_test.elapsed_time())); if (GTEST_FLAG(shuffle)) { OutputXmlAttribute(stream, kTestsuites, "random_seed", StreamableToString(unit_test.random_seed())); } *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result()); OutputXmlAttribute(stream, kTestsuites, "name", "AllTests"); *stream << ">\n"; for (int i = 0; i < unit_test.total_test_case_count(); ++i) { if (unit_test.GetTestCase(i)->reportable_test_count() > 0) PrintXmlTestCase(stream, *unit_test.GetTestCase(i)); } *stream << "\n"; } // Produces a string representing the test properties in a result as space // delimited XML attributes based on the property key="value" pairs. std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes( const TestResult& result) { Message attributes; for (int i = 0; i < result.test_property_count(); ++i) { const TestProperty& property = result.GetTestProperty(i); attributes << " " << property.key() << "=" << "\"" << EscapeXmlAttribute(property.value()) << "\""; } return attributes.GetString(); } // End XmlUnitTestResultPrinter #if GTEST_CAN_STREAM_RESULTS_ // Checks if str contains '=', '&', '%' or '\n' characters. If yes, // replaces them by "%xx" where xx is their hexadecimal value. For // example, replaces "=" with "%3D". This algorithm is O(strlen(str)) // in both time and space -- important as the input str may contain an // arbitrarily long test failure message and stack trace. string StreamingListener::UrlEncode(const char* str) { string result; result.reserve(strlen(str) + 1); for (char ch = *str; ch != '\0'; ch = *++str) { switch (ch) { case '%': case '=': case '&': case '\n': result.append("%" + String::FormatByte(static_cast(ch))); break; default: result.push_back(ch); break; } } return result; } void StreamingListener::SocketWriter::MakeConnection() { GTEST_CHECK_(sockfd_ == -1) << "MakeConnection() can't be called when there is already a connection."; addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses. hints.ai_socktype = SOCK_STREAM; addrinfo* servinfo = NULL; // Use the getaddrinfo() to get a linked list of IP addresses for // the given host name. const int error_num = getaddrinfo( host_name_.c_str(), port_num_.c_str(), &hints, &servinfo); if (error_num != 0) { GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: " << gai_strerror(error_num); } // Loop through all the results and connect to the first we can. for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL; cur_addr = cur_addr->ai_next) { sockfd_ = socket( cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol); if (sockfd_ != -1) { // Connect the client socket to the server socket. if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) { close(sockfd_); sockfd_ = -1; } } } freeaddrinfo(servinfo); // all done with this structure if (sockfd_ == -1) { GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to " << host_name_ << ":" << port_num_; } } // End of class Streaming Listener #endif // GTEST_CAN_STREAM_RESULTS__ // Class ScopedTrace // Pushes the given source file location and message onto a per-thread // trace stack maintained by Google Test. ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { TraceInfo trace; trace.file = file; trace.line = line; trace.message = message.GetString(); UnitTest::GetInstance()->PushGTestTrace(trace); } // Pops the info pushed by the c'tor. ScopedTrace::~ScopedTrace() GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) { UnitTest::GetInstance()->PopGTestTrace(); } // class OsStackTraceGetter // Returns the current OS stack trace as an std::string. Parameters: // // max_depth - the maximum number of stack frames to be included // in the trace. // skip_count - the number of top frames to be skipped; doesn't count // against max_depth. // string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */, int /* skip_count */) GTEST_LOCK_EXCLUDED_(mutex_) { return ""; } void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) { } const char* const OsStackTraceGetter::kElidedFramesMarker = "... " GTEST_NAME_ " internal frames ..."; // A helper class that creates the premature-exit file in its // constructor and deletes the file in its destructor. class ScopedPrematureExitFile { public: explicit ScopedPrematureExitFile(const char* premature_exit_filepath) : premature_exit_filepath_(premature_exit_filepath) { // If a path to the premature-exit file is specified... if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') { // create the file with a single "0" character in it. I/O // errors are ignored as there's nothing better we can do and we // don't want to fail the test because of this. FILE* pfile = posix::FOpen(premature_exit_filepath, "w"); fwrite("0", 1, 1, pfile); fclose(pfile); } } ~ScopedPrematureExitFile() { if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') { remove(premature_exit_filepath_); } } private: const char* const premature_exit_filepath_; GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile); }; } // namespace internal // class TestEventListeners TestEventListeners::TestEventListeners() : repeater_(new internal::TestEventRepeater()), default_result_printer_(NULL), default_xml_generator_(NULL) { } TestEventListeners::~TestEventListeners() { delete repeater_; } // Returns the standard listener responsible for the default console // output. Can be removed from the listeners list to shut down default // console output. Note that removing this object from the listener list // with Release transfers its ownership to the user. void TestEventListeners::Append(TestEventListener* listener) { repeater_->Append(listener); } // Removes the given event listener from the list and returns it. It then // becomes the caller's responsibility to delete the listener. Returns // NULL if the listener is not found in the list. TestEventListener* TestEventListeners::Release(TestEventListener* listener) { if (listener == default_result_printer_) default_result_printer_ = NULL; else if (listener == default_xml_generator_) default_xml_generator_ = NULL; return repeater_->Release(listener); } // Returns repeater that broadcasts the TestEventListener events to all // subscribers. TestEventListener* TestEventListeners::repeater() { return repeater_; } // Sets the default_result_printer attribute to the provided listener. // The listener is also added to the listener list and previous // default_result_printer is removed from it and deleted. The listener can // also be NULL in which case it will not be added to the list. Does // nothing if the previous and the current listener objects are the same. void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) { if (default_result_printer_ != listener) { // It is an error to pass this method a listener that is already in the // list. delete Release(default_result_printer_); default_result_printer_ = listener; if (listener != NULL) Append(listener); } } // Sets the default_xml_generator attribute to the provided listener. The // listener is also added to the listener list and previous // default_xml_generator is removed from it and deleted. The listener can // also be NULL in which case it will not be added to the list. Does // nothing if the previous and the current listener objects are the same. void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) { if (default_xml_generator_ != listener) { // It is an error to pass this method a listener that is already in the // list. delete Release(default_xml_generator_); default_xml_generator_ = listener; if (listener != NULL) Append(listener); } } // Controls whether events will be forwarded by the repeater to the // listeners in the list. bool TestEventListeners::EventForwardingEnabled() const { return repeater_->forwarding_enabled(); } void TestEventListeners::SuppressEventForwarding() { repeater_->set_forwarding_enabled(false); } // class UnitTest // Gets the singleton UnitTest object. The first time this method is // called, a UnitTest object is constructed and returned. Consecutive // calls will return the same object. // // We don't protect this under mutex_ as a user is not supposed to // call this before main() starts, from which point on the return // value will never change. UnitTest* UnitTest::GetInstance() { // When compiled with MSVC 7.1 in optimized mode, destroying the // UnitTest object upon exiting the program messes up the exit code, // causing successful tests to appear failed. We have to use a // different implementation in this case to bypass the compiler bug. // This implementation makes the compiler happy, at the cost of // leaking the UnitTest object. // CodeGear C++Builder insists on a public destructor for the // default implementation. Use this implementation to keep good OO // design with private destructor. #if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) static UnitTest* const instance = new UnitTest; return instance; #else static UnitTest instance; return &instance; #endif // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__) } // Gets the number of successful test cases. int UnitTest::successful_test_case_count() const { return impl()->successful_test_case_count(); } // Gets the number of failed test cases. int UnitTest::failed_test_case_count() const { return impl()->failed_test_case_count(); } // Gets the number of all test cases. int UnitTest::total_test_case_count() const { return impl()->total_test_case_count(); } // Gets the number of all test cases that contain at least one test // that should run. int UnitTest::test_case_to_run_count() const { return impl()->test_case_to_run_count(); } // Gets the number of successful tests. int UnitTest::successful_test_count() const { return impl()->successful_test_count(); } // Gets the number of failed tests. int UnitTest::failed_test_count() const { return impl()->failed_test_count(); } // Gets the number of disabled tests that will be reported in the XML report. int UnitTest::reportable_disabled_test_count() const { return impl()->reportable_disabled_test_count(); } // Gets the number of disabled tests. int UnitTest::disabled_test_count() const { return impl()->disabled_test_count(); } // Gets the number of tests to be printed in the XML report. int UnitTest::reportable_test_count() const { return impl()->reportable_test_count(); } // Gets the number of all tests. int UnitTest::total_test_count() const { return impl()->total_test_count(); } // Gets the number of tests that should run. int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); } // Gets the time of the test program start, in ms from the start of the // UNIX epoch. internal::TimeInMillis UnitTest::start_timestamp() const { return impl()->start_timestamp(); } // Gets the elapsed time, in milliseconds. internal::TimeInMillis UnitTest::elapsed_time() const { return impl()->elapsed_time(); } // Returns true iff the unit test passed (i.e. all test cases passed). bool UnitTest::Passed() const { return impl()->Passed(); } // Returns true iff the unit test failed (i.e. some test case failed // or something outside of all tests failed). bool UnitTest::Failed() const { return impl()->Failed(); } // Gets the i-th test case among all the test cases. i can range from 0 to // total_test_case_count() - 1. If i is not in that range, returns NULL. const TestCase* UnitTest::GetTestCase(int i) const { return impl()->GetTestCase(i); } // Returns the TestResult containing information on test failures and // properties logged outside of individual test cases. const TestResult& UnitTest::ad_hoc_test_result() const { return *impl()->ad_hoc_test_result(); } // Gets the i-th test case among all the test cases. i can range from 0 to // total_test_case_count() - 1. If i is not in that range, returns NULL. TestCase* UnitTest::GetMutableTestCase(int i) { return impl()->GetMutableTestCase(i); } // Returns the list of event listeners that can be used to track events // inside Google Test. TestEventListeners& UnitTest::listeners() { return *impl()->listeners(); } // Registers and returns a global test environment. When a test // program is run, all global test environments will be set-up in the // order they were registered. After all tests in the program have // finished, all global test environments will be torn-down in the // *reverse* order they were registered. // // The UnitTest object takes ownership of the given environment. // // We don't protect this under mutex_, as we only support calling it // from the main thread. Environment* UnitTest::AddEnvironment(Environment* env) { if (env == NULL) { return NULL; } impl_->environments().push_back(env); return env; } // Adds a TestPartResult to the current TestResult object. All Google Test // assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call // this to report their results. The user code should use the // assertion macros instead of calling this directly. void UnitTest::AddTestPartResult( TestPartResult::Type result_type, const char* file_name, int line_number, const std::string& message, const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) { Message msg; msg << message; internal::MutexLock lock(&mutex_); if (impl_->gtest_trace_stack().size() > 0) { msg << "\n" << GTEST_NAME_ << " trace:"; for (int i = static_cast(impl_->gtest_trace_stack().size()); i > 0; --i) { const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1]; msg << "\n" << internal::FormatFileLocation(trace.file, trace.line) << " " << trace.message; } } if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) { msg << internal::kStackTraceMarker << os_stack_trace; } const TestPartResult result = TestPartResult(result_type, file_name, line_number, msg.GetString().c_str()); impl_->GetTestPartResultReporterForCurrentThread()-> ReportTestPartResult(result); if (result_type != TestPartResult::kSuccess) { // gtest_break_on_failure takes precedence over // gtest_throw_on_failure. This allows a user to set the latter // in the code (perhaps in order to use Google Test assertions // with another testing framework) and specify the former on the // command line for debugging. if (GTEST_FLAG(break_on_failure)) { #if GTEST_OS_WINDOWS // Using DebugBreak on Windows allows gtest to still break into a debugger // when a failure happens and both the --gtest_break_on_failure and // the --gtest_catch_exceptions flags are specified. DebugBreak(); #else // Dereference NULL through a volatile pointer to prevent the compiler // from removing. We use this rather than abort() or __builtin_trap() for // portability: Symbian doesn't implement abort() well, and some debuggers // don't correctly trap abort(). *static_cast(NULL) = 1; #endif // GTEST_OS_WINDOWS } else if (GTEST_FLAG(throw_on_failure)) { #if GTEST_HAS_EXCEPTIONS throw internal::GoogleTestFailureException(result); #else // We cannot call abort() as it generates a pop-up in debug mode // that cannot be suppressed in VC 7.1 or below. exit(1); #endif } } } // Adds a TestProperty to the current TestResult object when invoked from // inside a test, to current TestCase's ad_hoc_test_result_ when invoked // from SetUpTestCase or TearDownTestCase, or to the global property set // when invoked elsewhere. If the result already contains a property with // the same key, the value will be updated. void UnitTest::RecordProperty(const std::string& key, const std::string& value) { impl_->RecordProperty(TestProperty(key, value)); } // Runs all tests in this UnitTest object and prints the result. // Returns 0 if successful, or 1 otherwise. // // We don't protect this under mutex_, as we only support calling it // from the main thread. int UnitTest::Run() { const bool in_death_test_child_process = internal::GTEST_FLAG(internal_run_death_test).length() > 0; // Google Test implements this protocol for catching that a test // program exits before returning control to Google Test: // // 1. Upon start, Google Test creates a file whose absolute path // is specified by the environment variable // TEST_PREMATURE_EXIT_FILE. // 2. When Google Test has finished its work, it deletes the file. // // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before // running a Google-Test-based test program and check the existence // of the file at the end of the test execution to see if it has // exited prematurely. // If we are in the child process of a death test, don't // create/delete the premature exit file, as doing so is unnecessary // and will confuse the parent process. Otherwise, create/delete // the file upon entering/leaving this function. If the program // somehow exits before this function has a chance to return, the // premature-exit file will be left undeleted, causing a test runner // that understands the premature-exit-file protocol to report the // test as having failed. const internal::ScopedPrematureExitFile premature_exit_file( in_death_test_child_process ? NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); // Captures the value of GTEST_FLAG(catch_exceptions). This value will be // used for the duration of the program. impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); #if GTEST_HAS_SEH // Either the user wants Google Test to catch exceptions thrown by the // tests or this is executing in the context of death test child // process. In either case the user does not want to see pop-up dialogs // about crashes - they are expected. if (impl()->catch_exceptions() || in_death_test_child_process) { # if !GTEST_OS_WINDOWS_MOBILE // SetErrorMode doesn't exist on CE. SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); # endif // !GTEST_OS_WINDOWS_MOBILE # if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE // Death test children can be terminated with _abort(). On Windows, // _abort() can show a dialog with a warning message. This forces the // abort message to go to stderr instead. _set_error_mode(_OUT_TO_STDERR); # endif # if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE // In the debug version, Visual Studio pops up a separate dialog // offering a choice to debug the aborted program. We need to suppress // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement // executed. Google Test will notify the user of any unexpected // failure via stderr. // // VC++ doesn't define _set_abort_behavior() prior to the version 8.0. // Users of prior VC versions shall suffer the agony and pain of // clicking through the countless debug dialogs. // TODO(vladl@google.com): find a way to suppress the abort dialog() in the // debug mode when compiled with VC 7.1 or lower. if (!GTEST_FLAG(break_on_failure)) _set_abort_behavior( 0x0, // Clear the following flags: _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. # endif } #endif // GTEST_HAS_SEH return internal::HandleExceptionsInMethodIfSupported( impl(), &internal::UnitTestImpl::RunAllTests, "auxiliary test code (environments or event listeners)") ? 0 : 1; } // Returns the working directory when the first TEST() or TEST_F() was // executed. const char* UnitTest::original_working_dir() const { return impl_->original_working_dir_.c_str(); } // Returns the TestCase object for the test that's currently running, // or NULL if no test is running. const TestCase* UnitTest::current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_) { internal::MutexLock lock(&mutex_); return impl_->current_test_case(); } // Returns the TestInfo object for the test that's currently running, // or NULL if no test is running. const TestInfo* UnitTest::current_test_info() const GTEST_LOCK_EXCLUDED_(mutex_) { internal::MutexLock lock(&mutex_); return impl_->current_test_info(); } // Returns the random seed used at the start of the current test run. int UnitTest::random_seed() const { return impl_->random_seed(); } #if GTEST_HAS_PARAM_TEST // Returns ParameterizedTestCaseRegistry object used to keep track of // value-parameterized tests and instantiate and register them. internal::ParameterizedTestCaseRegistry& UnitTest::parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_) { return impl_->parameterized_test_registry(); } #endif // GTEST_HAS_PARAM_TEST // Creates an empty UnitTest. UnitTest::UnitTest() { impl_ = new internal::UnitTestImpl(this); } // Destructor of UnitTest. UnitTest::~UnitTest() { delete impl_; } // Pushes a trace defined by SCOPED_TRACE() on to the per-thread // Google Test trace stack. void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) GTEST_LOCK_EXCLUDED_(mutex_) { internal::MutexLock lock(&mutex_); impl_->gtest_trace_stack().push_back(trace); } // Pops a trace from the per-thread Google Test trace stack. void UnitTest::PopGTestTrace() GTEST_LOCK_EXCLUDED_(mutex_) { internal::MutexLock lock(&mutex_); impl_->gtest_trace_stack().pop_back(); } namespace internal { UnitTestImpl::UnitTestImpl(UnitTest* parent) : parent_(parent), #ifdef _MSC_VER # pragma warning(push) // Saves the current warning state. # pragma warning(disable:4355) // Temporarily disables warning 4355 // (using this in initializer). default_global_test_part_result_reporter_(this), default_per_thread_test_part_result_reporter_(this), # pragma warning(pop) // Restores the warning state again. #else default_global_test_part_result_reporter_(this), default_per_thread_test_part_result_reporter_(this), #endif // _MSC_VER global_test_part_result_repoter_( &default_global_test_part_result_reporter_), per_thread_test_part_result_reporter_( &default_per_thread_test_part_result_reporter_), #if GTEST_HAS_PARAM_TEST parameterized_test_registry_(), parameterized_tests_registered_(false), #endif // GTEST_HAS_PARAM_TEST last_death_test_case_(-1), current_test_case_(NULL), current_test_info_(NULL), ad_hoc_test_result_(), os_stack_trace_getter_(NULL), post_flag_parse_init_performed_(false), random_seed_(0), // Will be overridden by the flag before first use. random_(0), // Will be reseeded before first use. start_timestamp_(0), elapsed_time_(0), #if GTEST_HAS_DEATH_TEST death_test_factory_(new DefaultDeathTestFactory), #endif // Will be overridden by the flag before first use. catch_exceptions_(false) { listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter); } UnitTestImpl::~UnitTestImpl() { // Deletes every TestCase. ForEach(test_cases_, internal::Delete); // Deletes every Environment. ForEach(environments_, internal::Delete); delete os_stack_trace_getter_; } // Adds a TestProperty to the current TestResult object when invoked in a // context of a test, to current test case's ad_hoc_test_result when invoke // from SetUpTestCase/TearDownTestCase, or to the global property set // otherwise. If the result already contains a property with the same key, // the value will be updated. void UnitTestImpl::RecordProperty(const TestProperty& test_property) { std::string xml_element; TestResult* test_result; // TestResult appropriate for property recording. if (current_test_info_ != NULL) { xml_element = "testcase"; test_result = &(current_test_info_->result_); } else if (current_test_case_ != NULL) { xml_element = "testsuite"; test_result = &(current_test_case_->ad_hoc_test_result_); } else { xml_element = "testsuites"; test_result = &ad_hoc_test_result_; } test_result->RecordProperty(xml_element, test_property); } #if GTEST_HAS_DEATH_TEST // Disables event forwarding if the control is currently in a death test // subprocess. Must not be called before InitGoogleTest. void UnitTestImpl::SuppressTestEventsIfInSubprocess() { if (internal_run_death_test_flag_.get() != NULL) listeners()->SuppressEventForwarding(); } #endif // GTEST_HAS_DEATH_TEST // Initializes event listeners performing XML output as specified by // UnitTestOptions. Must not be called before InitGoogleTest. void UnitTestImpl::ConfigureXmlOutput() { const std::string& output_format = UnitTestOptions::GetOutputFormat(); if (output_format == "xml") { listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter( UnitTestOptions::GetAbsolutePathToOutputFile().c_str())); } else if (output_format != "") { printf("WARNING: unrecognized output format \"%s\" ignored.\n", output_format.c_str()); fflush(stdout); } } #if GTEST_CAN_STREAM_RESULTS_ // Initializes event listeners for streaming test results in string form. // Must not be called before InitGoogleTest. void UnitTestImpl::ConfigureStreamingOutput() { const std::string& target = GTEST_FLAG(stream_result_to); if (!target.empty()) { const size_t pos = target.find(':'); if (pos != std::string::npos) { listeners()->Append(new StreamingListener(target.substr(0, pos), target.substr(pos+1))); } else { printf("WARNING: unrecognized streaming target \"%s\" ignored.\n", target.c_str()); fflush(stdout); } } } #endif // GTEST_CAN_STREAM_RESULTS_ // Performs initialization dependent upon flag values obtained in // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest // this function is also called from RunAllTests. Since this function can be // called more than once, it has to be idempotent. void UnitTestImpl::PostFlagParsingInit() { // Ensures that this function does not execute more than once. if (!post_flag_parse_init_performed_) { post_flag_parse_init_performed_ = true; #if GTEST_HAS_DEATH_TEST InitDeathTestSubprocessControlInfo(); SuppressTestEventsIfInSubprocess(); #endif // GTEST_HAS_DEATH_TEST // Registers parameterized tests. This makes parameterized tests // available to the UnitTest reflection API without running // RUN_ALL_TESTS. RegisterParameterizedTests(); // Configures listeners for XML output. This makes it possible for users // to shut down the default XML output before invoking RUN_ALL_TESTS. ConfigureXmlOutput(); #if GTEST_CAN_STREAM_RESULTS_ // Configures listeners for streaming test results to the specified server. ConfigureStreamingOutput(); #endif // GTEST_CAN_STREAM_RESULTS_ } } // A predicate that checks the name of a TestCase against a known // value. // // This is used for implementation of the UnitTest class only. We put // it in the anonymous namespace to prevent polluting the outer // namespace. // // TestCaseNameIs is copyable. class TestCaseNameIs { public: // Constructor. explicit TestCaseNameIs(const std::string& name) : name_(name) {} // Returns true iff the name of test_case matches name_. bool operator()(const TestCase* test_case) const { return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0; } private: std::string name_; }; // Finds and returns a TestCase with the given name. If one doesn't // exist, creates one and returns it. It's the CALLER'S // RESPONSIBILITY to ensure that this function is only called WHEN THE // TESTS ARE NOT SHUFFLED. // // Arguments: // // test_case_name: name of the test case // type_param: the name of the test case's type parameter, or NULL if // this is not a typed or a type-parameterized test case. // set_up_tc: pointer to the function that sets up the test case // tear_down_tc: pointer to the function that tears down the test case TestCase* UnitTestImpl::GetTestCase(const char* test_case_name, const char* type_param, Test::SetUpTestCaseFunc set_up_tc, Test::TearDownTestCaseFunc tear_down_tc) { // Can we find a TestCase with the given name? const std::vector::const_iterator test_case = std::find_if(test_cases_.begin(), test_cases_.end(), TestCaseNameIs(test_case_name)); if (test_case != test_cases_.end()) return *test_case; // No. Let's create one. TestCase* const new_test_case = new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc); // Is this a death test case? if (internal::UnitTestOptions::MatchesFilter(test_case_name, kDeathTestCaseFilter)) { // Yes. Inserts the test case after the last death test case // defined so far. This only works when the test cases haven't // been shuffled. Otherwise we may end up running a death test // after a non-death test. ++last_death_test_case_; test_cases_.insert(test_cases_.begin() + last_death_test_case_, new_test_case); } else { // No. Appends to the end of the list. test_cases_.push_back(new_test_case); } test_case_indices_.push_back(static_cast(test_case_indices_.size())); return new_test_case; } // Helpers for setting up / tearing down the given environment. They // are for use in the ForEach() function. static void SetUpEnvironment(Environment* env) { env->SetUp(); } static void TearDownEnvironment(Environment* env) { env->TearDown(); } // Runs all tests in this UnitTest object, prints the result, and // returns true if all tests are successful. If any exception is // thrown during a test, the test is considered to be failed, but the // rest of the tests will still be run. // // When parameterized tests are enabled, it expands and registers // parameterized tests first in RegisterParameterizedTests(). // All other functions called from RunAllTests() may safely assume that // parameterized tests are ready to be counted and run. bool UnitTestImpl::RunAllTests() { // Makes sure InitGoogleTest() was called. if (!GTestIsInitialized()) { printf("%s", "\nThis test program did NOT call ::testing::InitGoogleTest " "before calling RUN_ALL_TESTS(). Please fix it.\n"); return false; } // Do not run any test if the --help flag was specified. if (g_help_flag) return true; // Repeats the call to the post-flag parsing initialization in case the // user didn't call InitGoogleTest. PostFlagParsingInit(); // Even if sharding is not on, test runners may want to use the // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding // protocol. internal::WriteToShardStatusFileIfNeeded(); // True iff we are in a subprocess for running a thread-safe-style // death test. bool in_subprocess_for_death_test = false; #if GTEST_HAS_DEATH_TEST in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); #endif // GTEST_HAS_DEATH_TEST const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, in_subprocess_for_death_test); // Compares the full test names with the filter to decide which // tests to run. const bool has_tests_to_run = FilterTests(should_shard ? HONOR_SHARDING_PROTOCOL : IGNORE_SHARDING_PROTOCOL) > 0; // Lists the tests and exits if the --gtest_list_tests flag was specified. if (GTEST_FLAG(list_tests)) { // This must be called *after* FilterTests() has been called. ListTestsMatchingFilter(); return true; } random_seed_ = GTEST_FLAG(shuffle) ? GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0; // True iff at least one test has failed. bool failed = false; TestEventListener* repeater = listeners()->repeater(); start_timestamp_ = GetTimeInMillis(); repeater->OnTestProgramStart(*parent_); // How many times to repeat the tests? We don't want to repeat them // when we are inside the subprocess of a death test. const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); // Repeats forever if the repeat count is negative. const bool forever = repeat < 0; for (int i = 0; forever || i != repeat; i++) { // We want to preserve failures generated by ad-hoc test // assertions executed before RUN_ALL_TESTS(). ClearNonAdHocTestResult(); const TimeInMillis start = GetTimeInMillis(); // Shuffles test cases and tests if requested. if (has_tests_to_run && GTEST_FLAG(shuffle)) { random()->Reseed(random_seed_); // This should be done before calling OnTestIterationStart(), // such that a test event listener can see the actual test order // in the event. ShuffleTests(); } // Tells the unit test event listeners that the tests are about to start. repeater->OnTestIterationStart(*parent_, i); // Runs each test case if there is at least one test to run. if (has_tests_to_run) { // Sets up all environments beforehand. repeater->OnEnvironmentsSetUpStart(*parent_); ForEach(environments_, SetUpEnvironment); repeater->OnEnvironmentsSetUpEnd(*parent_); // Runs the tests only if there was no fatal failure during global // set-up. if (!Test::HasFatalFailure()) { for (int test_index = 0; test_index < total_test_case_count(); test_index++) { GetMutableTestCase(test_index)->Run(); } } // Tears down all environments in reverse order afterwards. repeater->OnEnvironmentsTearDownStart(*parent_); std::for_each(environments_.rbegin(), environments_.rend(), TearDownEnvironment); repeater->OnEnvironmentsTearDownEnd(*parent_); } elapsed_time_ = GetTimeInMillis() - start; // Tells the unit test event listener that the tests have just finished. repeater->OnTestIterationEnd(*parent_, i); // Gets the result and clears it. if (!Passed()) { failed = true; } // Restores the original test order after the iteration. This // allows the user to quickly repro a failure that happens in the // N-th iteration without repeating the first (N - 1) iterations. // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in // case the user somehow changes the value of the flag somewhere // (it's always safe to unshuffle the tests). UnshuffleTests(); if (GTEST_FLAG(shuffle)) { // Picks a new random seed for each iteration. random_seed_ = GetNextRandomSeed(random_seed_); } } repeater->OnTestProgramEnd(*parent_); return !failed; } // Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file // if the variable is present. If a file already exists at this location, this // function will write over it. If the variable is present, but the file cannot // be created, prints an error and exits. void WriteToShardStatusFileIfNeeded() { const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile); if (test_shard_file != NULL) { FILE* const file = posix::FOpen(test_shard_file, "w"); if (file == NULL) { ColoredPrintf(COLOR_RED, "Could not write to the test shard status file \"%s\" " "specified by the %s environment variable.\n", test_shard_file, kTestShardStatusFile); fflush(stdout); exit(EXIT_FAILURE); } fclose(file); } } // Checks whether sharding is enabled by examining the relevant // environment variable values. If the variables are present, // but inconsistent (i.e., shard_index >= total_shards), prints // an error and exits. If in_subprocess_for_death_test, sharding is // disabled because it must only be applied to the original test // process. Otherwise, we could filter out death tests we intended to execute. bool ShouldShard(const char* total_shards_env, const char* shard_index_env, bool in_subprocess_for_death_test) { if (in_subprocess_for_death_test) { return false; } const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1); const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1); if (total_shards == -1 && shard_index == -1) { return false; } else if (total_shards == -1 && shard_index != -1) { const Message msg = Message() << "Invalid environment variables: you have " << kTestShardIndex << " = " << shard_index << ", but have left " << kTestTotalShards << " unset.\n"; ColoredPrintf(COLOR_RED, msg.GetString().c_str()); fflush(stdout); exit(EXIT_FAILURE); } else if (total_shards != -1 && shard_index == -1) { const Message msg = Message() << "Invalid environment variables: you have " << kTestTotalShards << " = " << total_shards << ", but have left " << kTestShardIndex << " unset.\n"; ColoredPrintf(COLOR_RED, msg.GetString().c_str()); fflush(stdout); exit(EXIT_FAILURE); } else if (shard_index < 0 || shard_index >= total_shards) { const Message msg = Message() << "Invalid environment variables: we require 0 <= " << kTestShardIndex << " < " << kTestTotalShards << ", but you have " << kTestShardIndex << "=" << shard_index << ", " << kTestTotalShards << "=" << total_shards << ".\n"; ColoredPrintf(COLOR_RED, msg.GetString().c_str()); fflush(stdout); exit(EXIT_FAILURE); } return total_shards > 1; } // Parses the environment variable var as an Int32. If it is unset, // returns default_val. If it is not an Int32, prints an error // and aborts. Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) { const char* str_val = posix::GetEnv(var); if (str_val == NULL) { return default_val; } Int32 result; if (!ParseInt32(Message() << "The value of environment variable " << var, str_val, &result)) { exit(EXIT_FAILURE); } return result; } // Given the total number of shards, the shard index, and the test id, // returns true iff the test should be run on this shard. The test id is // some arbitrary but unique non-negative integer assigned to each test // method. Assumes that 0 <= shard_index < total_shards. bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) { return (test_id % total_shards) == shard_index; } // Compares the name of each test with the user-specified filter to // decide whether the test should be run, then records the result in // each TestCase and TestInfo object. // If shard_tests == true, further filters tests based on sharding // variables in the environment - see // http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide. // Returns the number of tests that should run. int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) { const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ? Int32FromEnvOrDie(kTestTotalShards, -1) : -1; const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ? Int32FromEnvOrDie(kTestShardIndex, -1) : -1; // num_runnable_tests are the number of tests that will // run across all shards (i.e., match filter and are not disabled). // num_selected_tests are the number of tests to be run on // this shard. int num_runnable_tests = 0; int num_selected_tests = 0; for (size_t i = 0; i < test_cases_.size(); i++) { TestCase* const test_case = test_cases_[i]; const std::string &test_case_name = test_case->name(); test_case->set_should_run(false); for (size_t j = 0; j < test_case->test_info_list().size(); j++) { TestInfo* const test_info = test_case->test_info_list()[j]; const std::string test_name(test_info->name()); // A test is disabled if test case name or test name matches // kDisableTestFilter. const bool is_disabled = internal::UnitTestOptions::MatchesFilter(test_case_name, kDisableTestFilter) || internal::UnitTestOptions::MatchesFilter(test_name, kDisableTestFilter); test_info->is_disabled_ = is_disabled; const bool matches_filter = internal::UnitTestOptions::FilterMatchesTest(test_case_name, test_name); test_info->matches_filter_ = matches_filter; const bool is_runnable = (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) && matches_filter; const bool is_selected = is_runnable && (shard_tests == IGNORE_SHARDING_PROTOCOL || ShouldRunTestOnShard(total_shards, shard_index, num_runnable_tests)); num_runnable_tests += is_runnable; num_selected_tests += is_selected; test_info->should_run_ = is_selected; test_case->set_should_run(test_case->should_run() || is_selected); } } return num_selected_tests; } // Prints the given C-string on a single line by replacing all '\n' // characters with string "\\n". If the output takes more than // max_length characters, only prints the first max_length characters // and "...". static void PrintOnOneLine(const char* str, int max_length) { if (str != NULL) { for (int i = 0; *str != '\0'; ++str) { if (i >= max_length) { printf("..."); break; } if (*str == '\n') { printf("\\n"); i += 2; } else { printf("%c", *str); ++i; } } } } // Prints the names of the tests matching the user-specified filter flag. void UnitTestImpl::ListTestsMatchingFilter() { // Print at most this many characters for each type/value parameter. const int kMaxParamLength = 250; for (size_t i = 0; i < test_cases_.size(); i++) { const TestCase* const test_case = test_cases_[i]; bool printed_test_case_name = false; for (size_t j = 0; j < test_case->test_info_list().size(); j++) { const TestInfo* const test_info = test_case->test_info_list()[j]; if (test_info->matches_filter_) { if (!printed_test_case_name) { printed_test_case_name = true; printf("%s.", test_case->name()); if (test_case->type_param() != NULL) { printf(" # %s = ", kTypeParamLabel); // We print the type parameter on a single line to make // the output easy to parse by a program. PrintOnOneLine(test_case->type_param(), kMaxParamLength); } printf("\n"); } printf(" %s", test_info->name()); if (test_info->value_param() != NULL) { printf(" # %s = ", kValueParamLabel); // We print the value parameter on a single line to make the // output easy to parse by a program. PrintOnOneLine(test_info->value_param(), kMaxParamLength); } printf("\n"); } } } fflush(stdout); } // Sets the OS stack trace getter. // // Does nothing if the input and the current OS stack trace getter are // the same; otherwise, deletes the old getter and makes the input the // current getter. void UnitTestImpl::set_os_stack_trace_getter( OsStackTraceGetterInterface* getter) { if (os_stack_trace_getter_ != getter) { delete os_stack_trace_getter_; os_stack_trace_getter_ = getter; } } // Returns the current OS stack trace getter if it is not NULL; // otherwise, creates an OsStackTraceGetter, makes it the current // getter, and returns it. OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { if (os_stack_trace_getter_ == NULL) { os_stack_trace_getter_ = new OsStackTraceGetter; } return os_stack_trace_getter_; } // Returns the TestResult for the test that's currently running, or // the TestResult for the ad hoc test if no test is running. TestResult* UnitTestImpl::current_test_result() { return current_test_info_ ? &(current_test_info_->result_) : &ad_hoc_test_result_; } // Shuffles all test cases, and the tests within each test case, // making sure that death tests are still run first. void UnitTestImpl::ShuffleTests() { // Shuffles the death test cases. ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_); // Shuffles the non-death test cases. ShuffleRange(random(), last_death_test_case_ + 1, static_cast(test_cases_.size()), &test_case_indices_); // Shuffles the tests inside each test case. for (size_t i = 0; i < test_cases_.size(); i++) { test_cases_[i]->ShuffleTests(random()); } } // Restores the test cases and tests to their order before the first shuffle. void UnitTestImpl::UnshuffleTests() { for (size_t i = 0; i < test_cases_.size(); i++) { // Unshuffles the tests in each test case. test_cases_[i]->UnshuffleTests(); // Resets the index of each test case. test_case_indices_[i] = static_cast(i); } } // Returns the current OS stack trace as an std::string. // // The maximum number of stack frames to be included is specified by // the gtest_stack_trace_depth flag. The skip_count parameter // specifies the number of top frames to be skipped, which doesn't // count against the number of frames to be included. // // For example, if Foo() calls Bar(), which in turn calls // GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in // the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/, int skip_count) { // We pass skip_count + 1 to skip this wrapper function in addition // to what the user really wants to skip. return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1); } // Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to // suppress unreachable code warnings. namespace { class ClassUniqueToAlwaysTrue {}; } bool IsTrue(bool condition) { return condition; } bool AlwaysTrue() { #if GTEST_HAS_EXCEPTIONS // This condition is always false so AlwaysTrue() never actually throws, // but it makes the compiler think that it may throw. if (IsTrue(false)) throw ClassUniqueToAlwaysTrue(); #endif // GTEST_HAS_EXCEPTIONS return true; } // If *pstr starts with the given prefix, modifies *pstr to be right // past the prefix and returns true; otherwise leaves *pstr unchanged // and returns false. None of pstr, *pstr, and prefix can be NULL. bool SkipPrefix(const char* prefix, const char** pstr) { const size_t prefix_len = strlen(prefix); if (strncmp(*pstr, prefix, prefix_len) == 0) { *pstr += prefix_len; return true; } return false; } // Parses a string as a command line flag. The string should have // the format "--flag=value". When def_optional is true, the "=value" // part can be omitted. // // Returns the value of the flag, or NULL if the parsing failed. const char* ParseFlagValue(const char* str, const char* flag, bool def_optional) { // str and flag must not be NULL. if (str == NULL || flag == NULL) return NULL; // The flag must start with "--" followed by GTEST_FLAG_PREFIX_. const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag; const size_t flag_len = flag_str.length(); if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL; // Skips the flag name. const char* flag_end = str + flag_len; // When def_optional is true, it's OK to not have a "=value" part. if (def_optional && (flag_end[0] == '\0')) { return flag_end; } // If def_optional is true and there are more characters after the // flag name, or if def_optional is false, there must be a '=' after // the flag name. if (flag_end[0] != '=') return NULL; // Returns the string after "=". return flag_end + 1; } // Parses a string for a bool flag, in the form of either // "--flag=value" or "--flag". // // In the former case, the value is taken as true as long as it does // not start with '0', 'f', or 'F'. // // In the latter case, the value is taken as true. // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. bool ParseBoolFlag(const char* str, const char* flag, bool* value) { // Gets the value of the flag as a string. const char* const value_str = ParseFlagValue(str, flag, true); // Aborts if the parsing failed. if (value_str == NULL) return false; // Converts the string value to a bool. *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F'); return true; } // Parses a string for an Int32 flag, in the form of // "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. bool ParseInt32Flag(const char* str, const char* flag, Int32* value) { // Gets the value of the flag as a string. const char* const value_str = ParseFlagValue(str, flag, false); // Aborts if the parsing failed. if (value_str == NULL) return false; // Sets *value to the value of the flag. return ParseInt32(Message() << "The value of flag --" << flag, value_str, value); } // Parses a string for a string flag, in the form of // "--flag=value". // // On success, stores the value of the flag in *value, and returns // true. On failure, returns false without changing *value. bool ParseStringFlag(const char* str, const char* flag, std::string* value) { // Gets the value of the flag as a string. const char* const value_str = ParseFlagValue(str, flag, false); // Aborts if the parsing failed. if (value_str == NULL) return false; // Sets *value to the value of the flag. *value = value_str; return true; } // Determines whether a string has a prefix that Google Test uses for its // flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_. // If Google Test detects that a command line flag has its prefix but is not // recognized, it will print its help message. Flags starting with // GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test // internal flags and do not trigger the help message. static bool HasGoogleTestFlagPrefix(const char* str) { return (SkipPrefix("--", &str) || SkipPrefix("-", &str) || SkipPrefix("/", &str)) && !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) && (SkipPrefix(GTEST_FLAG_PREFIX_, &str) || SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str)); } // Prints a string containing code-encoded text. The following escape // sequences can be used in the string to control the text color: // // @@ prints a single '@' character. // @R changes the color to red. // @G changes the color to green. // @Y changes the color to yellow. // @D changes to the default terminal text color. // // TODO(wan@google.com): Write tests for this once we add stdout // capturing to Google Test. static void PrintColorEncoded(const char* str) { GTestColor color = COLOR_DEFAULT; // The current color. // Conceptually, we split the string into segments divided by escape // sequences. Then we print one segment at a time. At the end of // each iteration, the str pointer advances to the beginning of the // next segment. for (;;) { const char* p = strchr(str, '@'); if (p == NULL) { ColoredPrintf(color, "%s", str); return; } ColoredPrintf(color, "%s", std::string(str, p).c_str()); const char ch = p[1]; str = p + 2; if (ch == '@') { ColoredPrintf(color, "@"); } else if (ch == 'D') { color = COLOR_DEFAULT; } else if (ch == 'R') { color = COLOR_RED; } else if (ch == 'G') { color = COLOR_GREEN; } else if (ch == 'Y') { color = COLOR_YELLOW; } else { --str; } } } static const char kColorEncodedHelpMessage[] = "This program contains tests written using " GTEST_NAME_ ". You can use the\n" "following command line flags to control its behavior:\n" "\n" "Test Selection:\n" " @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n" " List the names of all tests instead of running them. The name of\n" " TEST(Foo, Bar) is \"Foo.Bar\".\n" " @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS" "[@G-@YNEGATIVE_PATTERNS]@D\n" " Run only the tests whose name matches one of the positive patterns but\n" " none of the negative patterns. '?' matches any single character; '*'\n" " matches any substring; ':' separates two patterns.\n" " @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n" " Run all disabled tests too.\n" "\n" "Test Execution:\n" " @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n" " Run the tests repeatedly; use a negative count to repeat forever.\n" " @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n" " Randomize tests' orders on every iteration.\n" " @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n" " Random number seed to use for shuffling test orders (between 1 and\n" " 99999, or 0 to use a seed based on the current time).\n" "\n" "Test Output:\n" " @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n" " Enable/disable colored output. The default is @Gauto@D.\n" " -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n" " Don't print the elapsed time of each test.\n" " @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G" GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n" " Generate an XML report in the given directory or with the given file\n" " name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n" #if GTEST_CAN_STREAM_RESULTS_ " @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n" " Stream test results to the given server.\n" #endif // GTEST_CAN_STREAM_RESULTS_ "\n" "Assertion Behavior:\n" #if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS " @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n" " Set the default death test style.\n" #endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS " @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n" " Turn assertion failures into debugger break-points.\n" " @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n" " Turn assertion failures into C++ exceptions.\n" " @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n" " Do not report exceptions as test failures. Instead, allow them\n" " to crash the program or throw a pop-up (on Windows).\n" "\n" "Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set " "the corresponding\n" "environment variable of a flag (all letters in upper-case). For example, to\n" "disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_ "color=no@D or set\n" "the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n" "\n" "For more information, please read the " GTEST_NAME_ " documentation at\n" "@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n" "(not one in your own code or tests), please report it to\n" "@G<" GTEST_DEV_EMAIL_ ">@D.\n"; // Parses the command line for Google Test flags, without initializing // other parts of Google Test. The type parameter CharType can be // instantiated to either char or wchar_t. template void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) { for (int i = 1; i < *argc; i++) { const std::string arg_string = StreamableToString(argv[i]); const char* const arg = arg_string.c_str(); using internal::ParseBoolFlag; using internal::ParseInt32Flag; using internal::ParseStringFlag; // Do we see a Google Test flag? if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag, >EST_FLAG(also_run_disabled_tests)) || ParseBoolFlag(arg, kBreakOnFailureFlag, >EST_FLAG(break_on_failure)) || ParseBoolFlag(arg, kCatchExceptionsFlag, >EST_FLAG(catch_exceptions)) || ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) || ParseStringFlag(arg, kDeathTestStyleFlag, >EST_FLAG(death_test_style)) || ParseBoolFlag(arg, kDeathTestUseFork, >EST_FLAG(death_test_use_fork)) || ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) || ParseStringFlag(arg, kInternalRunDeathTestFlag, >EST_FLAG(internal_run_death_test)) || ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) || ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) || ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) || ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) || ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) || ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) || ParseInt32Flag(arg, kStackTraceDepthFlag, >EST_FLAG(stack_trace_depth)) || ParseStringFlag(arg, kStreamResultToFlag, >EST_FLAG(stream_result_to)) || ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_FLAG(throw_on_failure)) ) { // Yes. Shift the remainder of the argv list left by one. Note // that argv has (*argc + 1) elements, the last one always being // NULL. The following loop moves the trailing NULL element as // well. for (int j = i; j != *argc; j++) { argv[j] = argv[j + 1]; } // Decrements the argument count. (*argc)--; // We also need to decrement the iterator as we just removed // an element. i--; } else if (arg_string == "--help" || arg_string == "-h" || arg_string == "-?" || arg_string == "/?" || HasGoogleTestFlagPrefix(arg)) { // Both help flag and unrecognized Google Test flags (excluding // internal ones) trigger help display. g_help_flag = true; } } if (g_help_flag) { // We print the help here instead of in RUN_ALL_TESTS(), as the // latter may not be called at all if the user is using Google // Test with another testing framework. PrintColorEncoded(kColorEncodedHelpMessage); } } // Parses the command line for Google Test flags, without initializing // other parts of Google Test. void ParseGoogleTestFlagsOnly(int* argc, char** argv) { ParseGoogleTestFlagsOnlyImpl(argc, argv); } void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) { ParseGoogleTestFlagsOnlyImpl(argc, argv); } // The internal implementation of InitGoogleTest(). // // The type parameter CharType can be instantiated to either char or // wchar_t. template void InitGoogleTestImpl(int* argc, CharType** argv) { g_init_gtest_count++; // We don't want to run the initialization code twice. if (g_init_gtest_count != 1) return; if (*argc <= 0) return; internal::g_executable_path = internal::StreamableToString(argv[0]); #if GTEST_HAS_DEATH_TEST g_argvs.clear(); for (int i = 0; i != *argc; i++) { g_argvs.push_back(StreamableToString(argv[i])); } #endif // GTEST_HAS_DEATH_TEST ParseGoogleTestFlagsOnly(argc, argv); GetUnitTestImpl()->PostFlagParsingInit(); } } // namespace internal // Initializes Google Test. This must be called before calling // RUN_ALL_TESTS(). In particular, it parses a command line for the // flags that Google Test recognizes. Whenever a Google Test flag is // seen, it is removed from argv, and *argc is decremented. // // No value is returned. Instead, the Google Test flag variables are // updated. // // Calling the function for the second time has no user-visible effect. void InitGoogleTest(int* argc, char** argv) { internal::InitGoogleTestImpl(argc, argv); } // This overloaded version can be used in Windows programs compiled in // UNICODE mode. void InitGoogleTest(int* argc, wchar_t** argv) { internal::InitGoogleTestImpl(argc, argv); } } // namespace testing // Copyright 2005, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev) // // This file implements death tests. #if GTEST_HAS_DEATH_TEST # if GTEST_OS_MAC # include # endif // GTEST_OS_MAC # include # include # include # if GTEST_OS_LINUX # include # endif // GTEST_OS_LINUX # include # if GTEST_OS_WINDOWS # include # else # include # include # endif // GTEST_OS_WINDOWS # if GTEST_OS_QNX # include # endif // GTEST_OS_QNX #endif // GTEST_HAS_DEATH_TEST // Indicates that this translation unit is part of Google Test's // implementation. It must come before gtest-internal-inl.h is // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. #define GTEST_IMPLEMENTATION_ 1 #undef GTEST_IMPLEMENTATION_ namespace testing { // Constants. // The default death test style. static const char kDefaultDeathTestStyle[] = "fast"; GTEST_DEFINE_string_( death_test_style, internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle), "Indicates how to run a death test in a forked child process: " "\"threadsafe\" (child process re-executes the test binary " "from the beginning, running only the specific death test) or " "\"fast\" (child process runs the death test immediately " "after forking)."); GTEST_DEFINE_bool_( death_test_use_fork, internal::BoolFromGTestEnv("death_test_use_fork", false), "Instructs to use fork()/_exit() instead of clone() in death tests. " "Ignored and always uses fork() on POSIX systems where clone() is not " "implemented. Useful when running under valgrind or similar tools if " "those do not support clone(). Valgrind 3.3.1 will just fail if " "it sees an unsupported combination of clone() flags. " "It is not recommended to use this flag w/o valgrind though it will " "work in 99% of the cases. Once valgrind is fixed, this flag will " "most likely be removed."); namespace internal { GTEST_DEFINE_string_( internal_run_death_test, "", "Indicates the file, line number, temporal index of " "the single death test to run, and a file descriptor to " "which a success code may be sent, all separated by " "the '|' characters. This flag is specified if and only if the current " "process is a sub-process launched for running a thread-safe " "death test. FOR INTERNAL USE ONLY."); } // namespace internal #if GTEST_HAS_DEATH_TEST namespace internal { // Valid only for fast death tests. Indicates the code is running in the // child process of a fast style death test. static bool g_in_fast_death_test_child = false; // Returns a Boolean value indicating whether the caller is currently // executing in the context of the death test child process. Tools such as // Valgrind heap checkers may need this to modify their behavior in death // tests. IMPORTANT: This is an internal utility. Using it may break the // implementation of death tests. User code MUST NOT use it. bool InDeathTestChild() { # if GTEST_OS_WINDOWS // On Windows, death tests are thread-safe regardless of the value of the // death_test_style flag. return !GTEST_FLAG(internal_run_death_test).empty(); # else if (GTEST_FLAG(death_test_style) == "threadsafe") return !GTEST_FLAG(internal_run_death_test).empty(); else return g_in_fast_death_test_child; #endif } } // namespace internal // ExitedWithCode constructor. ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) { } // ExitedWithCode function-call operator. bool ExitedWithCode::operator()(int exit_status) const { # if GTEST_OS_WINDOWS return exit_status == exit_code_; # else return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_; # endif // GTEST_OS_WINDOWS } # if !GTEST_OS_WINDOWS // KilledBySignal constructor. KilledBySignal::KilledBySignal(int signum) : signum_(signum) { } // KilledBySignal function-call operator. bool KilledBySignal::operator()(int exit_status) const { return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; } # endif // !GTEST_OS_WINDOWS namespace internal { // Utilities needed for death tests. // Generates a textual description of a given exit code, in the format // specified by wait(2). static std::string ExitSummary(int exit_code) { Message m; # if GTEST_OS_WINDOWS m << "Exited with exit status " << exit_code; # else if (WIFEXITED(exit_code)) { m << "Exited with exit status " << WEXITSTATUS(exit_code); } else if (WIFSIGNALED(exit_code)) { m << "Terminated by signal " << WTERMSIG(exit_code); } # ifdef WCOREDUMP if (WCOREDUMP(exit_code)) { m << " (core dumped)"; } # endif # endif // GTEST_OS_WINDOWS return m.GetString(); } // Returns true if exit_status describes a process that was terminated // by a signal, or exited normally with a nonzero exit code. bool ExitedUnsuccessfully(int exit_status) { return !ExitedWithCode(0)(exit_status); } # if !GTEST_OS_WINDOWS // Generates a textual failure message when a death test finds more than // one thread running, or cannot determine the number of threads, prior // to executing the given statement. It is the responsibility of the // caller not to pass a thread_count of 1. static std::string DeathTestThreadWarning(size_t thread_count) { Message msg; msg << "Death tests use fork(), which is unsafe particularly" << " in a threaded context. For this test, " << GTEST_NAME_ << " "; if (thread_count == 0) msg << "couldn't detect the number of threads."; else msg << "detected " << thread_count << " threads."; return msg.GetString(); } # endif // !GTEST_OS_WINDOWS // Flag characters for reporting a death test that did not die. static const char kDeathTestLived = 'L'; static const char kDeathTestReturned = 'R'; static const char kDeathTestThrew = 'T'; static const char kDeathTestInternalError = 'I'; // An enumeration describing all of the possible ways that a death test can // conclude. DIED means that the process died while executing the test // code; LIVED means that process lived beyond the end of the test code; // RETURNED means that the test statement attempted to execute a return // statement, which is not allowed; THREW means that the test statement // returned control by throwing an exception. IN_PROGRESS means the test // has not yet concluded. // TODO(vladl@google.com): Unify names and possibly values for // AbortReason, DeathTestOutcome, and flag characters above. enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW }; // Routine for aborting the program which is safe to call from an // exec-style death test child process, in which case the error // message is propagated back to the parent process. Otherwise, the // message is simply printed to stderr. In either case, the program // then exits with status 1. void DeathTestAbort(const std::string& message) { // On a POSIX system, this function may be called from a threadsafe-style // death test child process, which operates on a very small stack. Use // the heap for any additional non-minuscule memory requirements. const InternalRunDeathTestFlag* const flag = GetUnitTestImpl()->internal_run_death_test_flag(); if (flag != NULL) { FILE* parent = posix::FDOpen(flag->write_fd(), "w"); fputc(kDeathTestInternalError, parent); fprintf(parent, "%s", message.c_str()); fflush(parent); _exit(1); } else { fprintf(stderr, "%s", message.c_str()); fflush(stderr); posix::Abort(); } } // A replacement for CHECK that calls DeathTestAbort if the assertion // fails. # define GTEST_DEATH_TEST_CHECK_(expression) \ do { \ if (!::testing::internal::IsTrue(expression)) { \ DeathTestAbort( \ ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + ::testing::internal::StreamableToString(__LINE__) + ": " \ + #expression); \ } \ } while (::testing::internal::AlwaysFalse()) // This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for // evaluating any system call that fulfills two conditions: it must return // -1 on failure, and set errno to EINTR when it is interrupted and // should be tried again. The macro expands to a loop that repeatedly // evaluates the expression as long as it evaluates to -1 and sets // errno to EINTR. If the expression evaluates to -1 but errno is // something other than EINTR, DeathTestAbort is called. # define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \ do { \ int gtest_retval; \ do { \ gtest_retval = (expression); \ } while (gtest_retval == -1 && errno == EINTR); \ if (gtest_retval == -1) { \ DeathTestAbort( \ ::std::string("CHECK failed: File ") + __FILE__ + ", line " \ + ::testing::internal::StreamableToString(__LINE__) + ": " \ + #expression + " != -1"); \ } \ } while (::testing::internal::AlwaysFalse()) // Returns the message describing the last system error in errno. std::string GetLastErrnoDescription() { return errno == 0 ? "" : posix::StrError(errno); } // This is called from a death test parent process to read a failure // message from the death test child process and log it with the FATAL // severity. On Windows, the message is read from a pipe handle. On other // platforms, it is read from a file descriptor. static void FailFromInternalError(int fd) { Message error; char buffer[256]; int num_read; do { while ((num_read = posix::Read(fd, buffer, 255)) > 0) { buffer[num_read] = '\0'; error << buffer; } } while (num_read == -1 && errno == EINTR); if (num_read == 0) { GTEST_LOG_(FATAL) << error.GetString(); } else { const int last_error = errno; GTEST_LOG_(FATAL) << "Error while reading death test internal: " << GetLastErrnoDescription() << " [" << last_error << "]"; } } // Death test constructor. Increments the running death test count // for the current test. DeathTest::DeathTest() { TestInfo* const info = GetUnitTestImpl()->current_test_info(); if (info == NULL) { DeathTestAbort("Cannot run a death test outside of a TEST or " "TEST_F construct"); } } // Creates and returns a death test by dispatching to the current // death test factory. bool DeathTest::Create(const char* statement, const RE* regex, const char* file, int line, DeathTest** test) { return GetUnitTestImpl()->death_test_factory()->Create( statement, regex, file, line, test); } const char* DeathTest::LastMessage() { return last_death_test_message_.c_str(); } void DeathTest::set_last_death_test_message(const std::string& message) { last_death_test_message_ = message; } std::string DeathTest::last_death_test_message_; // Provides cross platform implementation for some death functionality. class DeathTestImpl : public DeathTest { protected: DeathTestImpl(const char* a_statement, const RE* a_regex) : statement_(a_statement), regex_(a_regex), spawned_(false), status_(-1), outcome_(IN_PROGRESS), read_fd_(-1), write_fd_(-1) {} // read_fd_ is expected to be closed and cleared by a derived class. ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); } void Abort(AbortReason reason); virtual bool Passed(bool status_ok); const char* statement() const { return statement_; } const RE* regex() const { return regex_; } bool spawned() const { return spawned_; } void set_spawned(bool is_spawned) { spawned_ = is_spawned; } int status() const { return status_; } void set_status(int a_status) { status_ = a_status; } DeathTestOutcome outcome() const { return outcome_; } void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; } int read_fd() const { return read_fd_; } void set_read_fd(int fd) { read_fd_ = fd; } int write_fd() const { return write_fd_; } void set_write_fd(int fd) { write_fd_ = fd; } // Called in the parent process only. Reads the result code of the death // test child process via a pipe, interprets it to set the outcome_ // member, and closes read_fd_. Outputs diagnostics and terminates in // case of unexpected codes. void ReadAndInterpretStatusByte(); private: // The textual content of the code this object is testing. This class // doesn't own this string and should not attempt to delete it. const char* const statement_; // The regular expression which test output must match. DeathTestImpl // doesn't own this object and should not attempt to delete it. const RE* const regex_; // True if the death test child process has been successfully spawned. bool spawned_; // The exit status of the child process. int status_; // How the death test concluded. DeathTestOutcome outcome_; // Descriptor to the read end of the pipe to the child process. It is // always -1 in the child process. The child keeps its write end of the // pipe in write_fd_. int read_fd_; // Descriptor to the child's write end of the pipe to the parent process. // It is always -1 in the parent process. The parent keeps its end of the // pipe in read_fd_. int write_fd_; }; // Called in the parent process only. Reads the result code of the death // test child process via a pipe, interprets it to set the outcome_ // member, and closes read_fd_. Outputs diagnostics and terminates in // case of unexpected codes. void DeathTestImpl::ReadAndInterpretStatusByte() { char flag; int bytes_read; // The read() here blocks until data is available (signifying the // failure of the death test) or until the pipe is closed (signifying // its success), so it's okay to call this in the parent before // the child process has exited. do { bytes_read = posix::Read(read_fd(), &flag, 1); } while (bytes_read == -1 && errno == EINTR); if (bytes_read == 0) { set_outcome(DIED); } else if (bytes_read == 1) { switch (flag) { case kDeathTestReturned: set_outcome(RETURNED); break; case kDeathTestThrew: set_outcome(THREW); break; case kDeathTestLived: set_outcome(LIVED); break; case kDeathTestInternalError: FailFromInternalError(read_fd()); // Does not return. break; default: GTEST_LOG_(FATAL) << "Death test child process reported " << "unexpected status byte (" << static_cast(flag) << ")"; } } else { GTEST_LOG_(FATAL) << "Read from death test child process failed: " << GetLastErrnoDescription(); } GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd())); set_read_fd(-1); } // Signals that the death test code which should have exited, didn't. // Should be called only in a death test child process. // Writes a status byte to the child's status file descriptor, then // calls _exit(1). void DeathTestImpl::Abort(AbortReason reason) { // The parent process considers the death test to be a failure if // it finds any data in our pipe. So, here we write a single flag byte // to the pipe, then exit. const char status_ch = reason == TEST_DID_NOT_DIE ? kDeathTestLived : reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned; GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1)); // We are leaking the descriptor here because on some platforms (i.e., // when built as Windows DLL), destructors of global objects will still // run after calling _exit(). On such systems, write_fd_ will be // indirectly closed from the destructor of UnitTestImpl, causing double // close if it is also closed here. On debug configurations, double close // may assert. As there are no in-process buffers to flush here, we are // relying on the OS to close the descriptor after the process terminates // when the destructors are not run. _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash) } // Returns an indented copy of stderr output for a death test. // This makes distinguishing death test output lines from regular log lines // much easier. static ::std::string FormatDeathTestOutput(const ::std::string& output) { ::std::string ret; for (size_t at = 0; ; ) { const size_t line_end = output.find('\n', at); ret += "[ DEATH ] "; if (line_end == ::std::string::npos) { ret += output.substr(at); break; } ret += output.substr(at, line_end + 1 - at); at = line_end + 1; } return ret; } // Assesses the success or failure of a death test, using both private // members which have previously been set, and one argument: // // Private data members: // outcome: An enumeration describing how the death test // concluded: DIED, LIVED, THREW, or RETURNED. The death test // fails in the latter three cases. // status: The exit status of the child process. On *nix, it is in the // in the format specified by wait(2). On Windows, this is the // value supplied to the ExitProcess() API or a numeric code // of the exception that terminated the program. // regex: A regular expression object to be applied to // the test's captured standard error output; the death test // fails if it does not match. // // Argument: // status_ok: true if exit_status is acceptable in the context of // this particular death test, which fails if it is false // // Returns true iff all of the above conditions are met. Otherwise, the // first failing condition, in the order given above, is the one that is // reported. Also sets the last death test message string. bool DeathTestImpl::Passed(bool status_ok) { if (!spawned()) return false; const std::string error_message = GetCapturedStderr(); bool success = false; Message buffer; buffer << "Death test: " << statement() << "\n"; switch (outcome()) { case LIVED: buffer << " Result: failed to die.\n" << " Error msg:\n" << FormatDeathTestOutput(error_message); break; case THREW: buffer << " Result: threw an exception.\n" << " Error msg:\n" << FormatDeathTestOutput(error_message); break; case RETURNED: buffer << " Result: illegal return in test statement.\n" << " Error msg:\n" << FormatDeathTestOutput(error_message); break; case DIED: if (status_ok) { const bool matched = RE::PartialMatch(error_message.c_str(), *regex()); if (matched) { success = true; } else { buffer << " Result: died but not with expected error.\n" << " Expected: " << regex()->pattern() << "\n" << "Actual msg:\n" << FormatDeathTestOutput(error_message); } } else { buffer << " Result: died but not with expected exit code:\n" << " " << ExitSummary(status()) << "\n" << "Actual msg:\n" << FormatDeathTestOutput(error_message); } break; case IN_PROGRESS: default: GTEST_LOG_(FATAL) << "DeathTest::Passed somehow called before conclusion of test"; } DeathTest::set_last_death_test_message(buffer.GetString()); return success; } # if GTEST_OS_WINDOWS // WindowsDeathTest implements death tests on Windows. Due to the // specifics of starting new processes on Windows, death tests there are // always threadsafe, and Google Test considers the // --gtest_death_test_style=fast setting to be equivalent to // --gtest_death_test_style=threadsafe there. // // A few implementation notes: Like the Linux version, the Windows // implementation uses pipes for child-to-parent communication. But due to // the specifics of pipes on Windows, some extra steps are required: // // 1. The parent creates a communication pipe and stores handles to both // ends of it. // 2. The parent starts the child and provides it with the information // necessary to acquire the handle to the write end of the pipe. // 3. The child acquires the write end of the pipe and signals the parent // using a Windows event. // 4. Now the parent can release the write end of the pipe on its side. If // this is done before step 3, the object's reference count goes down to // 0 and it is destroyed, preventing the child from acquiring it. The // parent now has to release it, or read operations on the read end of // the pipe will not return when the child terminates. // 5. The parent reads child's output through the pipe (outcome code and // any possible error messages) from the pipe, and its stderr and then // determines whether to fail the test. // // Note: to distinguish Win32 API calls from the local method and function // calls, the former are explicitly resolved in the global namespace. // class WindowsDeathTest : public DeathTestImpl { public: WindowsDeathTest(const char* a_statement, const RE* a_regex, const char* file, int line) : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {} // All of these virtual functions are inherited from DeathTest. virtual int Wait(); virtual TestRole AssumeRole(); private: // The name of the file in which the death test is located. const char* const file_; // The line number on which the death test is located. const int line_; // Handle to the write end of the pipe to the child process. AutoHandle write_handle_; // Child process handle. AutoHandle child_handle_; // Event the child process uses to signal the parent that it has // acquired the handle to the write end of the pipe. After seeing this // event the parent can release its own handles to make sure its // ReadFile() calls return when the child terminates. AutoHandle event_handle_; }; // Waits for the child in a death test to exit, returning its exit // status, or 0 if no child process exists. As a side effect, sets the // outcome data member. int WindowsDeathTest::Wait() { if (!spawned()) return 0; // Wait until the child either signals that it has acquired the write end // of the pipe or it dies. const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() }; switch (::WaitForMultipleObjects(2, wait_handles, FALSE, // Waits for any of the handles. INFINITE)) { case WAIT_OBJECT_0: case WAIT_OBJECT_0 + 1: break; default: GTEST_DEATH_TEST_CHECK_(false); // Should not get here. } // The child has acquired the write end of the pipe or exited. // We release the handle on our side and continue. write_handle_.Reset(); event_handle_.Reset(); ReadAndInterpretStatusByte(); // Waits for the child process to exit if it haven't already. This // returns immediately if the child has already exited, regardless of // whether previous calls to WaitForMultipleObjects synchronized on this // handle or not. GTEST_DEATH_TEST_CHECK_( WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(), INFINITE)); DWORD status_code; GTEST_DEATH_TEST_CHECK_( ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE); child_handle_.Reset(); set_status(static_cast(status_code)); return status(); } // The AssumeRole process for a Windows death test. It creates a child // process with the same executable as the current process to run the // death test. The child process is given the --gtest_filter and // --gtest_internal_run_death_test flags such that it knows to run the // current death test only. DeathTest::TestRole WindowsDeathTest::AssumeRole() { const UnitTestImpl* const impl = GetUnitTestImpl(); const InternalRunDeathTestFlag* const flag = impl->internal_run_death_test_flag(); const TestInfo* const info = impl->current_test_info(); const int death_test_index = info->result()->death_test_count(); if (flag != NULL) { // ParseInternalRunDeathTestFlag() has performed all the necessary // processing. set_write_fd(flag->write_fd()); return EXECUTE_TEST; } // WindowsDeathTest uses an anonymous pipe to communicate results of // a death test. SECURITY_ATTRIBUTES handles_are_inheritable = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; HANDLE read_handle, write_handle; GTEST_DEATH_TEST_CHECK_( ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable, 0) // Default buffer size. != FALSE); set_read_fd(::_open_osfhandle(reinterpret_cast(read_handle), O_RDONLY)); write_handle_.Reset(write_handle); event_handle_.Reset(::CreateEvent( &handles_are_inheritable, TRUE, // The event will automatically reset to non-signaled state. FALSE, // The initial state is non-signalled. NULL)); // The even is unnamed. GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL); const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + info->test_case_name() + "." + info->name(); const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + file_ + "|" + StreamableToString(line_) + "|" + StreamableToString(death_test_index) + "|" + StreamableToString(static_cast(::GetCurrentProcessId())) + // size_t has the same width as pointers on both 32-bit and 64-bit // Windows platforms. // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx. "|" + StreamableToString(reinterpret_cast(write_handle)) + "|" + StreamableToString(reinterpret_cast(event_handle_.Get())); char executable_path[_MAX_PATH + 1]; // NOLINT GTEST_DEATH_TEST_CHECK_( _MAX_PATH + 1 != ::GetModuleFileNameA(NULL, executable_path, _MAX_PATH)); std::string command_line = std::string(::GetCommandLineA()) + " " + filter_flag + " \"" + internal_flag + "\""; DeathTest::set_last_death_test_message(""); CaptureStderr(); // Flush the log buffers since the log streams are shared with the child. FlushInfoLog(); // The child process will share the standard handles with the parent. STARTUPINFOA startup_info; memset(&startup_info, 0, sizeof(STARTUPINFO)); startup_info.dwFlags = STARTF_USESTDHANDLES; startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); PROCESS_INFORMATION process_info; GTEST_DEATH_TEST_CHECK_(::CreateProcessA( executable_path, const_cast(command_line.c_str()), NULL, // Retuned process handle is not inheritable. NULL, // Retuned thread handle is not inheritable. TRUE, // Child inherits all inheritable handles (for write_handle_). 0x0, // Default creation flags. NULL, // Inherit the parent's environment. UnitTest::GetInstance()->original_working_dir(), &startup_info, &process_info) != FALSE); child_handle_.Reset(process_info.hProcess); ::CloseHandle(process_info.hThread); set_spawned(true); return OVERSEE_TEST; } # else // We are not on Windows. // ForkingDeathTest provides implementations for most of the abstract // methods of the DeathTest interface. Only the AssumeRole method is // left undefined. class ForkingDeathTest : public DeathTestImpl { public: ForkingDeathTest(const char* statement, const RE* regex); // All of these virtual functions are inherited from DeathTest. virtual int Wait(); protected: void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; } private: // PID of child process during death test; 0 in the child process itself. pid_t child_pid_; }; // Constructs a ForkingDeathTest. ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex) : DeathTestImpl(a_statement, a_regex), child_pid_(-1) {} // Waits for the child in a death test to exit, returning its exit // status, or 0 if no child process exists. As a side effect, sets the // outcome data member. int ForkingDeathTest::Wait() { if (!spawned()) return 0; ReadAndInterpretStatusByte(); int status_value; GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0)); set_status(status_value); return status_value; } // A concrete death test class that forks, then immediately runs the test // in the child process. class NoExecDeathTest : public ForkingDeathTest { public: NoExecDeathTest(const char* a_statement, const RE* a_regex) : ForkingDeathTest(a_statement, a_regex) { } virtual TestRole AssumeRole(); }; // The AssumeRole process for a fork-and-run death test. It implements a // straightforward fork, with a simple pipe to transmit the status byte. DeathTest::TestRole NoExecDeathTest::AssumeRole() { const size_t thread_count = GetThreadCount(); if (thread_count != 1) { GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count); } int pipe_fd[2]; GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); DeathTest::set_last_death_test_message(""); CaptureStderr(); // When we fork the process below, the log file buffers are copied, but the // file descriptors are shared. We flush all log files here so that closing // the file descriptors in the child process doesn't throw off the // synchronization between descriptors and buffers in the parent process. // This is as close to the fork as possible to avoid a race condition in case // there are multiple threads running before the death test, and another // thread writes to the log file. FlushInfoLog(); const pid_t child_pid = fork(); GTEST_DEATH_TEST_CHECK_(child_pid != -1); set_child_pid(child_pid); if (child_pid == 0) { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0])); set_write_fd(pipe_fd[1]); // Redirects all logging to stderr in the child process to prevent // concurrent writes to the log files. We capture stderr in the parent // process and append the child process' output to a log. LogToStderr(); // Event forwarding to the listeners of event listener API mush be shut // down in death test subprocesses. GetUnitTestImpl()->listeners()->SuppressEventForwarding(); g_in_fast_death_test_child = true; return EXECUTE_TEST; } else { GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); set_read_fd(pipe_fd[0]); set_spawned(true); return OVERSEE_TEST; } } // A concrete death test class that forks and re-executes the main // program from the beginning, with command-line flags set that cause // only this specific death test to be run. class ExecDeathTest : public ForkingDeathTest { public: ExecDeathTest(const char* a_statement, const RE* a_regex, const char* file, int line) : ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { } virtual TestRole AssumeRole(); private: static ::std::vector GetArgvsForDeathTestChildProcess() { ::std::vector args = GetInjectableArgvs(); return args; } // The name of the file in which the death test is located. const char* const file_; // The line number on which the death test is located. const int line_; }; // Utility class for accumulating command-line arguments. class Arguments { public: Arguments() { args_.push_back(NULL); } ~Arguments() { for (std::vector::iterator i = args_.begin(); i != args_.end(); ++i) { free(*i); } } void AddArgument(const char* argument) { args_.insert(args_.end() - 1, posix::StrDup(argument)); } template void AddArguments(const ::std::vector& arguments) { for (typename ::std::vector::const_iterator i = arguments.begin(); i != arguments.end(); ++i) { args_.insert(args_.end() - 1, posix::StrDup(i->c_str())); } } char* const* Argv() { return &args_[0]; } private: std::vector args_; }; // A struct that encompasses the arguments to the child process of a // threadsafe-style death test process. struct ExecDeathTestArgs { char* const* argv; // Command-line arguments for the child's call to exec int close_fd; // File descriptor to close; the read end of a pipe }; # if GTEST_OS_MAC inline char** GetEnviron() { // When Google Test is built as a framework on MacOS X, the environ variable // is unavailable. Apple's documentation (man environ) recommends using // _NSGetEnviron() instead. return *_NSGetEnviron(); } # else // Some POSIX platforms expect you to declare environ. extern "C" makes // it reside in the global namespace. extern "C" char** environ; inline char** GetEnviron() { return environ; } # endif // GTEST_OS_MAC # if !GTEST_OS_QNX // The main function for a threadsafe-style death test child process. // This function is called in a clone()-ed process and thus must avoid // any potentially unsafe operations like malloc or libc functions. static int ExecDeathTestChildMain(void* child_arg) { ExecDeathTestArgs* const args = static_cast(child_arg); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd)); // We need to execute the test program in the same environment where // it was originally invoked. Therefore we change to the original // working directory first. const char* const original_dir = UnitTest::GetInstance()->original_working_dir(); // We can safely call chdir() as it's a direct system call. if (chdir(original_dir) != 0) { DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + GetLastErrnoDescription()); return EXIT_FAILURE; } // We can safely call execve() as it's a direct system call. We // cannot use execvp() as it's a libc function and thus potentially // unsafe. Since execve() doesn't search the PATH, the user must // invoke the test program via a valid path that contains at least // one path separator. execve(args->argv[0], args->argv, GetEnviron()); DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " + original_dir + " failed: " + GetLastErrnoDescription()); return EXIT_FAILURE; } # endif // !GTEST_OS_QNX // Two utility routines that together determine the direction the stack // grows. // This could be accomplished more elegantly by a single recursive // function, but we want to guard against the unlikely possibility of // a smart compiler optimizing the recursion away. // // GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining // StackLowerThanAddress into StackGrowsDown, which then doesn't give // correct answer. void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_; void StackLowerThanAddress(const void* ptr, bool* result) { int dummy; *result = (&dummy < ptr); } bool StackGrowsDown() { int dummy; bool result; StackLowerThanAddress(&dummy, &result); return result; } // Spawns a child process with the same executable as the current process in // a thread-safe manner and instructs it to run the death test. The // implementation uses fork(2) + exec. On systems where clone(2) is // available, it is used instead, being slightly more thread-safe. On QNX, // fork supports only single-threaded environments, so this function uses // spawn(2) there instead. The function dies with an error message if // anything goes wrong. static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) { ExecDeathTestArgs args = { argv, close_fd }; pid_t child_pid = -1; # if GTEST_OS_QNX // Obtains the current directory and sets it to be closed in the child // process. const int cwd_fd = open(".", O_RDONLY); GTEST_DEATH_TEST_CHECK_(cwd_fd != -1); GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC)); // We need to execute the test program in the same environment where // it was originally invoked. Therefore we change to the original // working directory first. const char* const original_dir = UnitTest::GetInstance()->original_working_dir(); // We can safely call chdir() as it's a direct system call. if (chdir(original_dir) != 0) { DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " + GetLastErrnoDescription()); return EXIT_FAILURE; } int fd_flags; // Set close_fd to be closed after spawn. GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD)); GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD, fd_flags | FD_CLOEXEC)); struct inheritance inherit = {0}; // spawn is a system call. child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron()); // Restores the current working directory. GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd)); # else // GTEST_OS_QNX # if GTEST_OS_LINUX // When a SIGPROF signal is received while fork() or clone() are executing, // the process may hang. To avoid this, we ignore SIGPROF here and re-enable // it after the call to fork()/clone() is complete. struct sigaction saved_sigprof_action; struct sigaction ignore_sigprof_action; memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action)); sigemptyset(&ignore_sigprof_action.sa_mask); ignore_sigprof_action.sa_handler = SIG_IGN; GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction( SIGPROF, &ignore_sigprof_action, &saved_sigprof_action)); # endif // GTEST_OS_LINUX # if GTEST_HAS_CLONE const bool use_fork = GTEST_FLAG(death_test_use_fork); if (!use_fork) { static const bool stack_grows_down = StackGrowsDown(); const size_t stack_size = getpagesize(); // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead. void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED); // Maximum stack alignment in bytes: For a downward-growing stack, this // amount is subtracted from size of the stack space to get an address // that is within the stack space and is aligned on all systems we care // about. As far as I know there is no ABI with stack alignment greater // than 64. We assume stack and stack_size already have alignment of // kMaxStackAlignment. const size_t kMaxStackAlignment = 64; void* const stack_top = static_cast(stack) + (stack_grows_down ? stack_size - kMaxStackAlignment : 0); GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment && reinterpret_cast(stack_top) % kMaxStackAlignment == 0); child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args); GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1); } # else const bool use_fork = true; # endif // GTEST_HAS_CLONE if (use_fork && (child_pid = fork()) == 0) { ExecDeathTestChildMain(&args); _exit(0); } # endif // GTEST_OS_QNX # if GTEST_OS_LINUX GTEST_DEATH_TEST_CHECK_SYSCALL_( sigaction(SIGPROF, &saved_sigprof_action, NULL)); # endif // GTEST_OS_LINUX GTEST_DEATH_TEST_CHECK_(child_pid != -1); return child_pid; } // The AssumeRole process for a fork-and-exec death test. It re-executes the // main program from the beginning, setting the --gtest_filter // and --gtest_internal_run_death_test flags to cause only the current // death test to be re-run. DeathTest::TestRole ExecDeathTest::AssumeRole() { const UnitTestImpl* const impl = GetUnitTestImpl(); const InternalRunDeathTestFlag* const flag = impl->internal_run_death_test_flag(); const TestInfo* const info = impl->current_test_info(); const int death_test_index = info->result()->death_test_count(); if (flag != NULL) { set_write_fd(flag->write_fd()); return EXECUTE_TEST; } int pipe_fd[2]; GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1); // Clear the close-on-exec flag on the write end of the pipe, lest // it be closed when the child process does an exec: GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1); const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" + info->test_case_name() + "." + info->name(); const std::string internal_flag = std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "=" + file_ + "|" + StreamableToString(line_) + "|" + StreamableToString(death_test_index) + "|" + StreamableToString(pipe_fd[1]); Arguments args; args.AddArguments(GetArgvsForDeathTestChildProcess()); args.AddArgument(filter_flag.c_str()); args.AddArgument(internal_flag.c_str()); DeathTest::set_last_death_test_message(""); CaptureStderr(); // See the comment in NoExecDeathTest::AssumeRole for why the next line // is necessary. FlushInfoLog(); const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]); GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1])); set_child_pid(child_pid); set_read_fd(pipe_fd[0]); set_spawned(true); return OVERSEE_TEST; } # endif // !GTEST_OS_WINDOWS // Creates a concrete DeathTest-derived class that depends on the // --gtest_death_test_style flag, and sets the pointer pointed to // by the "test" argument to its address. If the test should be // skipped, sets that pointer to NULL. Returns true, unless the // flag is set to an invalid value. bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex, const char* file, int line, DeathTest** test) { UnitTestImpl* const impl = GetUnitTestImpl(); const InternalRunDeathTestFlag* const flag = impl->internal_run_death_test_flag(); const int death_test_index = impl->current_test_info() ->increment_death_test_count(); if (flag != NULL) { if (death_test_index > flag->index()) { DeathTest::set_last_death_test_message( "Death test count (" + StreamableToString(death_test_index) + ") somehow exceeded expected maximum (" + StreamableToString(flag->index()) + ")"); return false; } if (!(flag->file() == file && flag->line() == line && flag->index() == death_test_index)) { *test = NULL; return true; } } # if GTEST_OS_WINDOWS if (GTEST_FLAG(death_test_style) == "threadsafe" || GTEST_FLAG(death_test_style) == "fast") { *test = new WindowsDeathTest(statement, regex, file, line); } # else if (GTEST_FLAG(death_test_style) == "threadsafe") { *test = new ExecDeathTest(statement, regex, file, line); } else if (GTEST_FLAG(death_test_style) == "fast") { *test = new NoExecDeathTest(statement, regex); } # endif // GTEST_OS_WINDOWS else { // NOLINT - this is more readable than unbalanced brackets inside #if. DeathTest::set_last_death_test_message( "Unknown death test style \"" + GTEST_FLAG(death_test_style) + "\" encountered"); return false; } return true; } // Splits a given string on a given delimiter, populating a given // vector with the fields. GTEST_HAS_DEATH_TEST implies that we have // ::std::string, so we can use it here. static void SplitString(const ::std::string& str, char delimiter, ::std::vector< ::std::string>* dest) { ::std::vector< ::std::string> parsed; ::std::string::size_type pos = 0; while (::testing::internal::AlwaysTrue()) { const ::std::string::size_type colon = str.find(delimiter, pos); if (colon == ::std::string::npos) { parsed.push_back(str.substr(pos)); break; } else { parsed.push_back(str.substr(pos, colon - pos)); pos = colon + 1; } } dest->swap(parsed); } # if GTEST_OS_WINDOWS // Recreates the pipe and event handles from the provided parameters, // signals the event, and returns a file descriptor wrapped around the pipe // handle. This function is called in the child process only. int GetStatusFileDescriptor(unsigned int parent_process_id, size_t write_handle_as_size_t, size_t event_handle_as_size_t) { AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE, FALSE, // Non-inheritable. parent_process_id)); if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) { DeathTestAbort("Unable to open parent process " + StreamableToString(parent_process_id)); } // TODO(vladl@google.com): Replace the following check with a // compile-time assertion when available. GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t)); const HANDLE write_handle = reinterpret_cast(write_handle_as_size_t); HANDLE dup_write_handle; // The newly initialized handle is accessible only in in the parent // process. To obtain one accessible within the child, we need to use // DuplicateHandle. if (!::DuplicateHandle(parent_process_handle.Get(), write_handle, ::GetCurrentProcess(), &dup_write_handle, 0x0, // Requested privileges ignored since // DUPLICATE_SAME_ACCESS is used. FALSE, // Request non-inheritable handler. DUPLICATE_SAME_ACCESS)) { DeathTestAbort("Unable to duplicate the pipe handle " + StreamableToString(write_handle_as_size_t) + " from the parent process " + StreamableToString(parent_process_id)); } const HANDLE event_handle = reinterpret_cast(event_handle_as_size_t); HANDLE dup_event_handle; if (!::DuplicateHandle(parent_process_handle.Get(), event_handle, ::GetCurrentProcess(), &dup_event_handle, 0x0, FALSE, DUPLICATE_SAME_ACCESS)) { DeathTestAbort("Unable to duplicate the event handle " + StreamableToString(event_handle_as_size_t) + " from the parent process " + StreamableToString(parent_process_id)); } const int write_fd = ::_open_osfhandle(reinterpret_cast(dup_write_handle), O_APPEND); if (write_fd == -1) { DeathTestAbort("Unable to convert pipe handle " + StreamableToString(write_handle_as_size_t) + " to a file descriptor"); } // Signals the parent that the write end of the pipe has been acquired // so the parent can release its own write end. ::SetEvent(dup_event_handle); return write_fd; } # endif // GTEST_OS_WINDOWS // Returns a newly created InternalRunDeathTestFlag object with fields // initialized from the GTEST_FLAG(internal_run_death_test) flag if // the flag is specified; otherwise returns NULL. InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() { if (GTEST_FLAG(internal_run_death_test) == "") return NULL; // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we // can use it here. int line = -1; int index = -1; ::std::vector< ::std::string> fields; SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields); int write_fd = -1; # if GTEST_OS_WINDOWS unsigned int parent_process_id = 0; size_t write_handle_as_size_t = 0; size_t event_handle_as_size_t = 0; if (fields.size() != 6 || !ParseNaturalNumber(fields[1], &line) || !ParseNaturalNumber(fields[2], &index) || !ParseNaturalNumber(fields[3], &parent_process_id) || !ParseNaturalNumber(fields[4], &write_handle_as_size_t) || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) { DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + GTEST_FLAG(internal_run_death_test)); } write_fd = GetStatusFileDescriptor(parent_process_id, write_handle_as_size_t, event_handle_as_size_t); # else if (fields.size() != 4 || !ParseNaturalNumber(fields[1], &line) || !ParseNaturalNumber(fields[2], &index) || !ParseNaturalNumber(fields[3], &write_fd)) { DeathTestAbort("Bad --gtest_internal_run_death_test flag: " + GTEST_FLAG(internal_run_death_test)); } # endif // GTEST_OS_WINDOWS return new InternalRunDeathTestFlag(fields[0], line, index, write_fd); } } // namespace internal #endif // GTEST_HAS_DEATH_TEST } // namespace testing // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: keith.ray@gmail.com (Keith Ray) #include #if GTEST_OS_WINDOWS_MOBILE # include #elif GTEST_OS_WINDOWS # include # include #elif GTEST_OS_SYMBIAN // Symbian OpenC has PATH_MAX in sys/syslimits.h # include #else # include # include // Some Linux distributions define PATH_MAX here. #endif // GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS # define GTEST_PATH_MAX_ _MAX_PATH #elif defined(PATH_MAX) # define GTEST_PATH_MAX_ PATH_MAX #elif defined(_XOPEN_PATH_MAX) # define GTEST_PATH_MAX_ _XOPEN_PATH_MAX #else # define GTEST_PATH_MAX_ _POSIX_PATH_MAX #endif // GTEST_OS_WINDOWS namespace testing { namespace internal { #if GTEST_OS_WINDOWS // On Windows, '\\' is the standard path separator, but many tools and the // Windows API also accept '/' as an alternate path separator. Unless otherwise // noted, a file path can contain either kind of path separators, or a mixture // of them. const char kPathSeparator = '\\'; const char kAlternatePathSeparator = '/'; const char kPathSeparatorString[] = "\\"; const char kAlternatePathSeparatorString[] = "/"; # if GTEST_OS_WINDOWS_MOBILE // Windows CE doesn't have a current directory. You should not use // the current directory in tests on Windows CE, but this at least // provides a reasonable fallback. const char kCurrentDirectoryString[] = "\\"; // Windows CE doesn't define INVALID_FILE_ATTRIBUTES const DWORD kInvalidFileAttributes = 0xffffffff; # else const char kCurrentDirectoryString[] = ".\\"; # endif // GTEST_OS_WINDOWS_MOBILE #else const char kPathSeparator = '/'; const char kPathSeparatorString[] = "/"; const char kCurrentDirectoryString[] = "./"; #endif // GTEST_OS_WINDOWS // Returns whether the given character is a valid path separator. static bool IsPathSeparator(char c) { #if GTEST_HAS_ALT_PATH_SEP_ return (c == kPathSeparator) || (c == kAlternatePathSeparator); #else return c == kPathSeparator; #endif } // Returns the current working directory, or "" if unsuccessful. FilePath FilePath::GetCurrentDir() { #if GTEST_OS_WINDOWS_MOBILE // Windows CE doesn't have a current directory, so we just return // something reasonable. return FilePath(kCurrentDirectoryString); #elif GTEST_OS_WINDOWS char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); #else char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); #endif // GTEST_OS_WINDOWS_MOBILE } // Returns a copy of the FilePath with the case-insensitive extension removed. // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns // FilePath("dir/file"). If a case-insensitive extension is not // found, returns a copy of the original FilePath. FilePath FilePath::RemoveExtension(const char* extension) const { const std::string dot_extension = std::string(".") + extension; if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) { return FilePath(pathname_.substr( 0, pathname_.length() - dot_extension.length())); } return *this; } // Returns a pointer to the last occurence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FilePath::FindLastPathSeparator() const { const char* const last_sep = strrchr(c_str(), kPathSeparator); #if GTEST_HAS_ALT_PATH_SEP_ const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator); // Comparing two pointers of which only one is NULL is undefined. if (last_alt_sep != NULL && (last_sep == NULL || last_alt_sep > last_sep)) { return last_alt_sep; } #endif return last_sep; } // Returns a copy of the FilePath with the directory part removed. // Example: FilePath("path/to/file").RemoveDirectoryName() returns // FilePath("file"). If there is no directory part ("just_a_file"), it returns // the FilePath unmodified. If there is no file part ("just_a_dir/") it // returns an empty FilePath (""). // On Windows platform, '\' is the path separator, otherwise it is '/'. FilePath FilePath::RemoveDirectoryName() const { const char* const last_sep = FindLastPathSeparator(); return last_sep ? FilePath(last_sep + 1) : *this; } // RemoveFileName returns the directory path with the filename removed. // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/". // If the FilePath is "a_file" or "/a_file", RemoveFileName returns // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does // not have a file, like "just/a/dir/", it returns the FilePath unmodified. // On Windows platform, '\' is the path separator, otherwise it is '/'. FilePath FilePath::RemoveFileName() const { const char* const last_sep = FindLastPathSeparator(); std::string dir; if (last_sep) { dir = std::string(c_str(), last_sep + 1 - c_str()); } else { dir = kCurrentDirectoryString; } return FilePath(dir); } // Helper functions for naming files in a directory for xml output. // Given directory = "dir", base_name = "test", number = 0, // extension = "xml", returns "dir/test.xml". If number is greater // than zero (e.g., 12), returns "dir/test_12.xml". // On Windows platform, uses \ as the separator rather than /. FilePath FilePath::MakeFileName(const FilePath& directory, const FilePath& base_name, int number, const char* extension) { std::string file; if (number == 0) { file = base_name.string() + "." + extension; } else { file = base_name.string() + "_" + StreamableToString(number) + "." + extension; } return ConcatPaths(directory, FilePath(file)); } // Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml". // On Windows, uses \ as the separator rather than /. FilePath FilePath::ConcatPaths(const FilePath& directory, const FilePath& relative_path) { if (directory.IsEmpty()) return relative_path; const FilePath dir(directory.RemoveTrailingPathSeparator()); return FilePath(dir.string() + kPathSeparator + relative_path.string()); } // Returns true if pathname describes something findable in the file-system, // either a file, directory, or whatever. bool FilePath::FileOrDirectoryExists() const { #if GTEST_OS_WINDOWS_MOBILE LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str()); const DWORD attributes = GetFileAttributes(unicode); delete [] unicode; return attributes != kInvalidFileAttributes; #else posix::StatStruct file_stat; return posix::Stat(pathname_.c_str(), &file_stat) == 0; #endif // GTEST_OS_WINDOWS_MOBILE } // Returns true if pathname describes a directory in the file-system // that exists. bool FilePath::DirectoryExists() const { bool result = false; #if GTEST_OS_WINDOWS // Don't strip off trailing separator if path is a root directory on // Windows (like "C:\\"). const FilePath& path(IsRootDirectory() ? *this : RemoveTrailingPathSeparator()); #else const FilePath& path(*this); #endif #if GTEST_OS_WINDOWS_MOBILE LPCWSTR unicode = String::AnsiToUtf16(path.c_str()); const DWORD attributes = GetFileAttributes(unicode); delete [] unicode; if ((attributes != kInvalidFileAttributes) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { result = true; } #else posix::StatStruct file_stat; result = posix::Stat(path.c_str(), &file_stat) == 0 && posix::IsDir(file_stat); #endif // GTEST_OS_WINDOWS_MOBILE return result; } // Returns true if pathname describes a root directory. (Windows has one // root directory per disk drive.) bool FilePath::IsRootDirectory() const { #if GTEST_OS_WINDOWS // TODO(wan@google.com): on Windows a network share like // \\server\share can be a root directory, although it cannot be the // current directory. Handle this properly. return pathname_.length() == 3 && IsAbsolutePath(); #else return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]); #endif } // Returns true if pathname describes an absolute path. bool FilePath::IsAbsolutePath() const { const char* const name = pathname_.c_str(); #if GTEST_OS_WINDOWS return pathname_.length() >= 3 && ((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z')) && name[1] == ':' && IsPathSeparator(name[2]); #else return IsPathSeparator(name[0]); #endif } // Returns a pathname for a file that does not currently exist. The pathname // will be directory/base_name.extension or // directory/base_name_.extension if directory/base_name.extension // already exists. The number will be incremented until a pathname is found // that does not already exist. // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'. // There could be a race condition if two or more processes are calling this // function at the same time -- they could both pick the same filename. FilePath FilePath::GenerateUniqueFileName(const FilePath& directory, const FilePath& base_name, const char* extension) { FilePath full_pathname; int number = 0; do { full_pathname.Set(MakeFileName(directory, base_name, number++, extension)); } while (full_pathname.FileOrDirectoryExists()); return full_pathname; } // Returns true if FilePath ends with a path separator, which indicates that // it is intended to represent a directory. Returns false otherwise. // This does NOT check that a directory (or file) actually exists. bool FilePath::IsDirectory() const { return !pathname_.empty() && IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]); } // Create directories so that path exists. Returns true if successful or if // the directories already exist; returns false if unable to create directories // for any reason. bool FilePath::CreateDirectoriesRecursively() const { if (!this->IsDirectory()) { return false; } if (pathname_.length() == 0 || this->DirectoryExists()) { return true; } const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName()); return parent.CreateDirectoriesRecursively() && this->CreateFolder(); } // Create the directory so that path exists. Returns true if successful or // if the directory already exists; returns false if unable to create the // directory for any reason, including if the parent directory does not // exist. Not named "CreateDirectory" because that's a macro on Windows. bool FilePath::CreateFolder() const { #if GTEST_OS_WINDOWS_MOBILE FilePath removed_sep(this->RemoveTrailingPathSeparator()); LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str()); int result = CreateDirectory(unicode, NULL) ? 0 : -1; delete [] unicode; #elif GTEST_OS_WINDOWS int result = _mkdir(pathname_.c_str()); #else int result = mkdir(pathname_.c_str(), 0777); #endif // GTEST_OS_WINDOWS_MOBILE if (result == -1) { return this->DirectoryExists(); // An error is OK if the directory exists. } return true; // No error. } // If input name has a trailing separator character, remove it and return the // name, otherwise return the name string unmodified. // On Windows platform, uses \ as the separator, other platforms use /. FilePath FilePath::RemoveTrailingPathSeparator() const { return IsDirectory() ? FilePath(pathname_.substr(0, pathname_.length() - 1)) : *this; } // Removes any redundant separators that might be in the pathname. // For example, "bar///foo" becomes "bar/foo". Does not eliminate other // redundancies that might be in a pathname involving "." or "..". // TODO(wan@google.com): handle Windows network shares (e.g. \\server\share). void FilePath::Normalize() { if (pathname_.c_str() == NULL) { pathname_ = ""; return; } const char* src = pathname_.c_str(); char* const dest = new char[pathname_.length() + 1]; char* dest_ptr = dest; memset(dest_ptr, 0, pathname_.length() + 1); while (*src != '\0') { *dest_ptr = *src; if (!IsPathSeparator(*src)) { src++; } else { #if GTEST_HAS_ALT_PATH_SEP_ if (*dest_ptr == kAlternatePathSeparator) { *dest_ptr = kPathSeparator; } #endif while (IsPathSeparator(*src)) src++; } dest_ptr++; } *dest_ptr = '\0'; pathname_ = dest; delete[] dest; } } // namespace internal } // namespace testing // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) #include #include #include #include #if GTEST_OS_WINDOWS_MOBILE # include // For TerminateProcess() #elif GTEST_OS_WINDOWS # include # include #else # include #endif // GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_MAC # include # include # include #endif // GTEST_OS_MAC #if GTEST_OS_QNX # include # include #endif // GTEST_OS_QNX // Indicates that this translation unit is part of Google Test's // implementation. It must come before gtest-internal-inl.h is // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. #define GTEST_IMPLEMENTATION_ 1 #undef GTEST_IMPLEMENTATION_ namespace testing { namespace internal { #if defined(_MSC_VER) || defined(__BORLANDC__) // MSVC and C++Builder do not provide a definition of STDERR_FILENO. const int kStdOutFileno = 1; const int kStdErrFileno = 2; #else const int kStdOutFileno = STDOUT_FILENO; const int kStdErrFileno = STDERR_FILENO; #endif // _MSC_VER #if GTEST_OS_MAC // Returns the number of threads running in the process, or 0 to indicate that // we cannot detect it. size_t GetThreadCount() { const task_t task = mach_task_self(); mach_msg_type_number_t thread_count; thread_act_array_t thread_list; const kern_return_t status = task_threads(task, &thread_list, &thread_count); if (status == KERN_SUCCESS) { // task_threads allocates resources in thread_list and we need to free them // to avoid leaks. vm_deallocate(task, reinterpret_cast(thread_list), sizeof(thread_t) * thread_count); return static_cast(thread_count); } else { return 0; } } #elif GTEST_OS_QNX // Returns the number of threads running in the process, or 0 to indicate that // we cannot detect it. size_t GetThreadCount() { const int fd = open("/proc/self/as", O_RDONLY); if (fd < 0) { return 0; } procfs_info process_info; const int status = devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL); close(fd); if (status == EOK) { return static_cast(process_info.num_threads); } else { return 0; } } #else size_t GetThreadCount() { // There's no portable way to detect the number of threads, so we just // return 0 to indicate that we cannot detect it. return 0; } #endif // GTEST_OS_MAC #if GTEST_USES_POSIX_RE // Implements RE. Currently only needed for death tests. RE::~RE() { if (is_valid_) { // regfree'ing an invalid regex might crash because the content // of the regex is undefined. Since the regex's are essentially // the same, one cannot be valid (or invalid) without the other // being so too. regfree(&partial_regex_); regfree(&full_regex_); } free(const_cast(pattern_)); } // Returns true iff regular expression re matches the entire str. bool RE::FullMatch(const char* str, const RE& re) { if (!re.is_valid_) return false; regmatch_t match; return regexec(&re.full_regex_, str, 1, &match, 0) == 0; } // Returns true iff regular expression re matches a substring of str // (including str itself). bool RE::PartialMatch(const char* str, const RE& re) { if (!re.is_valid_) return false; regmatch_t match; return regexec(&re.partial_regex_, str, 1, &match, 0) == 0; } // Initializes an RE from its string representation. void RE::Init(const char* regex) { pattern_ = posix::StrDup(regex); // Reserves enough bytes to hold the regular expression used for a // full match. const size_t full_regex_len = strlen(regex) + 10; char* const full_pattern = new char[full_regex_len]; snprintf(full_pattern, full_regex_len, "^(%s)$", regex); is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0; // We want to call regcomp(&partial_regex_, ...) even if the // previous expression returns false. Otherwise partial_regex_ may // not be properly initialized can may cause trouble when it's // freed. // // Some implementation of POSIX regex (e.g. on at least some // versions of Cygwin) doesn't accept the empty string as a valid // regex. We change it to an equivalent form "()" to be safe. if (is_valid_) { const char* const partial_regex = (*regex == '\0') ? "()" : regex; is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0; } EXPECT_TRUE(is_valid_) << "Regular expression \"" << regex << "\" is not a valid POSIX Extended regular expression."; delete[] full_pattern; } #elif GTEST_USES_SIMPLE_RE // Returns true iff ch appears anywhere in str (excluding the // terminating '\0' character). bool IsInSet(char ch, const char* str) { return ch != '\0' && strchr(str, ch) != NULL; } // Returns true iff ch belongs to the given classification. Unlike // similar functions in , these aren't affected by the // current locale. bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; } bool IsAsciiPunct(char ch) { return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"); } bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); } bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); } bool IsAsciiWordChar(char ch) { return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') || ch == '_'; } // Returns true iff "\\c" is a supported escape sequence. bool IsValidEscape(char c) { return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW")); } // Returns true iff the given atom (specified by escaped and pattern) // matches ch. The result is undefined if the atom is invalid. bool AtomMatchesChar(bool escaped, char pattern_char, char ch) { if (escaped) { // "\\p" where p is pattern_char. switch (pattern_char) { case 'd': return IsAsciiDigit(ch); case 'D': return !IsAsciiDigit(ch); case 'f': return ch == '\f'; case 'n': return ch == '\n'; case 'r': return ch == '\r'; case 's': return IsAsciiWhiteSpace(ch); case 'S': return !IsAsciiWhiteSpace(ch); case 't': return ch == '\t'; case 'v': return ch == '\v'; case 'w': return IsAsciiWordChar(ch); case 'W': return !IsAsciiWordChar(ch); } return IsAsciiPunct(pattern_char) && pattern_char == ch; } return (pattern_char == '.' && ch != '\n') || pattern_char == ch; } // Helper function used by ValidateRegex() to format error messages. std::string FormatRegexSyntaxError(const char* regex, int index) { return (Message() << "Syntax error at index " << index << " in simple regular expression \"" << regex << "\": ").GetString(); } // Generates non-fatal failures and returns false if regex is invalid; // otherwise returns true. bool ValidateRegex(const char* regex) { if (regex == NULL) { // TODO(wan@google.com): fix the source file location in the // assertion failures to match where the regex is used in user // code. ADD_FAILURE() << "NULL is not a valid simple regular expression."; return false; } bool is_valid = true; // True iff ?, *, or + can follow the previous atom. bool prev_repeatable = false; for (int i = 0; regex[i]; i++) { if (regex[i] == '\\') { // An escape sequence i++; if (regex[i] == '\0') { ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) << "'\\' cannot appear at the end."; return false; } if (!IsValidEscape(regex[i])) { ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1) << "invalid escape sequence \"\\" << regex[i] << "\"."; is_valid = false; } prev_repeatable = true; } else { // Not an escape sequence. const char ch = regex[i]; if (ch == '^' && i > 0) { ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'^' can only appear at the beginning."; is_valid = false; } else if (ch == '$' && regex[i + 1] != '\0') { ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'$' can only appear at the end."; is_valid = false; } else if (IsInSet(ch, "()[]{}|")) { ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch << "' is unsupported."; is_valid = false; } else if (IsRepeat(ch) && !prev_repeatable) { ADD_FAILURE() << FormatRegexSyntaxError(regex, i) << "'" << ch << "' can only follow a repeatable token."; is_valid = false; } prev_repeatable = !IsInSet(ch, "^$?*+"); } } return is_valid; } // Matches a repeated regex atom followed by a valid simple regular // expression. The regex atom is defined as c if escaped is false, // or \c otherwise. repeat is the repetition meta character (?, *, // or +). The behavior is undefined if str contains too many // characters to be indexable by size_t, in which case the test will // probably time out anyway. We are fine with this limitation as // std::string has it too. bool MatchRepetitionAndRegexAtHead( bool escaped, char c, char repeat, const char* regex, const char* str) { const size_t min_count = (repeat == '+') ? 1 : 0; const size_t max_count = (repeat == '?') ? 1 : static_cast(-1) - 1; // We cannot call numeric_limits::max() as it conflicts with the // max() macro on Windows. for (size_t i = 0; i <= max_count; ++i) { // We know that the atom matches each of the first i characters in str. if (i >= min_count && MatchRegexAtHead(regex, str + i)) { // We have enough matches at the head, and the tail matches too. // Since we only care about *whether* the pattern matches str // (as opposed to *how* it matches), there is no need to find a // greedy match. return true; } if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i])) return false; } return false; } // Returns true iff regex matches a prefix of str. regex must be a // valid simple regular expression and not start with "^", or the // result is undefined. bool MatchRegexAtHead(const char* regex, const char* str) { if (*regex == '\0') // An empty regex matches a prefix of anything. return true; // "$" only matches the end of a string. Note that regex being // valid guarantees that there's nothing after "$" in it. if (*regex == '$') return *str == '\0'; // Is the first thing in regex an escape sequence? const bool escaped = *regex == '\\'; if (escaped) ++regex; if (IsRepeat(regex[1])) { // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so // here's an indirect recursion. It terminates as the regex gets // shorter in each recursion. return MatchRepetitionAndRegexAtHead( escaped, regex[0], regex[1], regex + 2, str); } else { // regex isn't empty, isn't "$", and doesn't start with a // repetition. We match the first atom of regex with the first // character of str and recurse. return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) && MatchRegexAtHead(regex + 1, str + 1); } } // Returns true iff regex matches any substring of str. regex must be // a valid simple regular expression, or the result is undefined. // // The algorithm is recursive, but the recursion depth doesn't exceed // the regex length, so we won't need to worry about running out of // stack space normally. In rare cases the time complexity can be // exponential with respect to the regex length + the string length, // but usually it's must faster (often close to linear). bool MatchRegexAnywhere(const char* regex, const char* str) { if (regex == NULL || str == NULL) return false; if (*regex == '^') return MatchRegexAtHead(regex + 1, str); // A successful match can be anywhere in str. do { if (MatchRegexAtHead(regex, str)) return true; } while (*str++ != '\0'); return false; } // Implements the RE class. RE::~RE() { free(const_cast(pattern_)); free(const_cast(full_pattern_)); } // Returns true iff regular expression re matches the entire str. bool RE::FullMatch(const char* str, const RE& re) { return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str); } // Returns true iff regular expression re matches a substring of str // (including str itself). bool RE::PartialMatch(const char* str, const RE& re) { return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str); } // Initializes an RE from its string representation. void RE::Init(const char* regex) { pattern_ = full_pattern_ = NULL; if (regex != NULL) { pattern_ = posix::StrDup(regex); } is_valid_ = ValidateRegex(regex); if (!is_valid_) { // No need to calculate the full pattern when the regex is invalid. return; } const size_t len = strlen(regex); // Reserves enough bytes to hold the regular expression used for a // full match: we need space to prepend a '^', append a '$', and // terminate the string with '\0'. char* buffer = static_cast(malloc(len + 3)); full_pattern_ = buffer; if (*regex != '^') *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'. // We don't use snprintf or strncpy, as they trigger a warning when // compiled with VC++ 8.0. memcpy(buffer, regex, len); buffer += len; if (len == 0 || regex[len - 1] != '$') *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'. *buffer = '\0'; } #endif // GTEST_USES_POSIX_RE const char kUnknownFile[] = "unknown file"; // Formats a source file path and a line number as they would appear // in an error message from the compiler used to compile this code. GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) { const std::string file_name(file == NULL ? kUnknownFile : file); if (line < 0) { return file_name + ":"; } #ifdef _MSC_VER return file_name + "(" + StreamableToString(line) + "):"; #else return file_name + ":" + StreamableToString(line) + ":"; #endif // _MSC_VER } // Formats a file location for compiler-independent XML output. // Although this function is not platform dependent, we put it next to // FormatFileLocation in order to contrast the two functions. // Note that FormatCompilerIndependentFileLocation() does NOT append colon // to the file location it produces, unlike FormatFileLocation(). GTEST_API_ ::std::string FormatCompilerIndependentFileLocation( const char* file, int line) { const std::string file_name(file == NULL ? kUnknownFile : file); if (line < 0) return file_name; else return file_name + ":" + StreamableToString(line); } GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) : severity_(severity) { const char* const marker = severity == GTEST_INFO ? "[ INFO ]" : severity == GTEST_WARNING ? "[WARNING]" : severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]"; GetStream() << ::std::endl << marker << " " << FormatFileLocation(file, line).c_str() << ": "; } // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program. GTestLog::~GTestLog() { GetStream() << ::std::endl; if (severity_ == GTEST_FATAL) { fflush(stderr); posix::Abort(); } } // Disable Microsoft deprecation warnings for POSIX functions called from // this class (creat, dup, dup2, and close) #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4996) #endif // _MSC_VER #if GTEST_HAS_STREAM_REDIRECTION // Object that captures an output stream (stdout/stderr). class CapturedStream { public: // The ctor redirects the stream to a temporary file. explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) { # if GTEST_OS_WINDOWS char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path); const UINT success = ::GetTempFileNameA(temp_dir_path, "gtest_redir", 0, // Generate unique file name. temp_file_path); GTEST_CHECK_(success != 0) << "Unable to create a temporary file in " << temp_dir_path; const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE); GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file " << temp_file_path; filename_ = temp_file_path; # else // There's no guarantee that a test has write access to the current // directory, so we create the temporary file in the /tmp directory // instead. We use /tmp on most systems, and /sdcard on Android. // That's because Android doesn't have /tmp. # if GTEST_OS_LINUX_ANDROID // Note: Android applications are expected to call the framework's // Context.getExternalStorageDirectory() method through JNI to get // the location of the world-writable SD Card directory. However, // this requires a Context handle, which cannot be retrieved // globally from native code. Doing so also precludes running the // code as part of a regular standalone executable, which doesn't // run in a Dalvik process (e.g. when running it through 'adb shell'). // // The location /sdcard is directly accessible from native code // and is the only location (unofficially) supported by the Android // team. It's generally a symlink to the real SD Card mount point // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or // other OEM-customized locations. Never rely on these, and always // use /sdcard. char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX"; # else char name_template[] = "/tmp/captured_stream.XXXXXX"; # endif // GTEST_OS_LINUX_ANDROID const int captured_fd = mkstemp(name_template); filename_ = name_template; # endif // GTEST_OS_WINDOWS fflush(NULL); dup2(captured_fd, fd_); close(captured_fd); } ~CapturedStream() { remove(filename_.c_str()); } std::string GetCapturedString() { if (uncaptured_fd_ != -1) { // Restores the original stream. fflush(NULL); dup2(uncaptured_fd_, fd_); close(uncaptured_fd_); uncaptured_fd_ = -1; } FILE* const file = posix::FOpen(filename_.c_str(), "r"); const std::string content = ReadEntireFile(file); posix::FClose(file); return content; } private: // Reads the entire content of a file as an std::string. static std::string ReadEntireFile(FILE* file); // Returns the size (in bytes) of a file. static size_t GetFileSize(FILE* file); const int fd_; // A stream to capture. int uncaptured_fd_; // Name of the temporary file holding the stderr output. ::std::string filename_; GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); }; // Returns the size (in bytes) of a file. size_t CapturedStream::GetFileSize(FILE* file) { fseek(file, 0, SEEK_END); return static_cast(ftell(file)); } // Reads the entire content of a file as a string. std::string CapturedStream::ReadEntireFile(FILE* file) { const size_t file_size = GetFileSize(file); char* const buffer = new char[file_size]; size_t bytes_last_read = 0; // # of bytes read in the last fread() size_t bytes_read = 0; // # of bytes read so far fseek(file, 0, SEEK_SET); // Keeps reading the file until we cannot read further or the // pre-determined file size is reached. do { bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file); bytes_read += bytes_last_read; } while (bytes_last_read > 0 && bytes_read < file_size); const std::string content(buffer, bytes_read); delete[] buffer; return content; } # ifdef _MSC_VER # pragma warning(pop) # endif // _MSC_VER static CapturedStream* g_captured_stderr = NULL; static CapturedStream* g_captured_stdout = NULL; // Starts capturing an output stream (stdout/stderr). void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { if (*stream != NULL) { GTEST_LOG_(FATAL) << "Only one " << stream_name << " capturer can exist at a time."; } *stream = new CapturedStream(fd); } // Stops capturing the output stream and returns the captured string. std::string GetCapturedStream(CapturedStream** captured_stream) { const std::string content = (*captured_stream)->GetCapturedString(); delete *captured_stream; *captured_stream = NULL; return content; } // Starts capturing stdout. void CaptureStdout() { CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout); } // Starts capturing stderr. void CaptureStderr() { CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr); } // Stops capturing stdout and returns the captured string. std::string GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); } // Stops capturing stderr and returns the captured string. std::string GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); } #endif // GTEST_HAS_STREAM_REDIRECTION #if GTEST_HAS_DEATH_TEST // A copy of all command line arguments. Set by InitGoogleTest(). ::std::vector g_argvs; static const ::std::vector* g_injected_test_argvs = NULL; // Owned. void SetInjectableArgvs(const ::std::vector* argvs) { if (g_injected_test_argvs != argvs) delete g_injected_test_argvs; g_injected_test_argvs = argvs; } const ::std::vector& GetInjectableArgvs() { if (g_injected_test_argvs != NULL) { return *g_injected_test_argvs; } return g_argvs; } #endif // GTEST_HAS_DEATH_TEST #if GTEST_OS_WINDOWS_MOBILE namespace posix { void Abort() { DebugBreak(); TerminateProcess(GetCurrentProcess(), 1); } } // namespace posix #endif // GTEST_OS_WINDOWS_MOBILE // Returns the name of the environment variable corresponding to the // given flag. For example, FlagToEnvVar("foo") will return // "GTEST_FOO" in the open-source version. static std::string FlagToEnvVar(const char* flag) { const std::string full_flag = (Message() << GTEST_FLAG_PREFIX_ << flag).GetString(); Message env_var; for (size_t i = 0; i != full_flag.length(); i++) { env_var << ToUpper(full_flag.c_str()[i]); } return env_var.GetString(); } // Parses 'str' for a 32-bit signed integer. If successful, writes // the result to *value and returns true; otherwise leaves *value // unchanged and returns false. bool ParseInt32(const Message& src_text, const char* str, Int32* value) { // Parses the environment variable as a decimal integer. char* end = NULL; const long long_value = strtol(str, &end, 10); // NOLINT // Has strtol() consumed all characters in the string? if (*end != '\0') { // No - an invalid character was encountered. Message msg; msg << "WARNING: " << src_text << " is expected to be a 32-bit integer, but actually" << " has value \"" << str << "\".\n"; printf("%s", msg.GetString().c_str()); fflush(stdout); return false; } // Is the parsed value in the range of an Int32? const Int32 result = static_cast(long_value); if (long_value == LONG_MAX || long_value == LONG_MIN || // The parsed value overflows as a long. (strtol() returns // LONG_MAX or LONG_MIN when the input overflows.) result != long_value // The parsed value overflows as an Int32. ) { Message msg; msg << "WARNING: " << src_text << " is expected to be a 32-bit integer, but actually" << " has value " << str << ", which overflows.\n"; printf("%s", msg.GetString().c_str()); fflush(stdout); return false; } *value = result; return true; } // Reads and returns the Boolean environment variable corresponding to // the given flag; if it's not set, returns default_value. // // The value is considered true iff it's not "0". bool BoolFromGTestEnv(const char* flag, bool default_value) { const std::string env_var = FlagToEnvVar(flag); const char* const string_value = posix::GetEnv(env_var.c_str()); return string_value == NULL ? default_value : strcmp(string_value, "0") != 0; } // Reads and returns a 32-bit integer stored in the environment // variable corresponding to the given flag; if it isn't set or // doesn't represent a valid 32-bit integer, returns default_value. Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) { const std::string env_var = FlagToEnvVar(flag); const char* const string_value = posix::GetEnv(env_var.c_str()); if (string_value == NULL) { // The environment variable is not set. return default_value; } Int32 result = default_value; if (!ParseInt32(Message() << "Environment variable " << env_var, string_value, &result)) { printf("The default value %s is used.\n", (Message() << default_value).GetString().c_str()); fflush(stdout); return default_value; } return result; } // Reads and returns the string environment variable corresponding to // the given flag; if it's not set, returns default_value. const char* StringFromGTestEnv(const char* flag, const char* default_value) { const std::string env_var = FlagToEnvVar(flag); const char* const value = posix::GetEnv(env_var.c_str()); return value == NULL ? default_value : value; } } // namespace internal } // namespace testing // Copyright 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) // Google Test - The Google C++ Testing Framework // // This file implements a universal value printer that can print a // value of any type T: // // void ::testing::internal::UniversalPrinter::Print(value, ostream_ptr); // // It uses the << operator when possible, and prints the bytes in the // object otherwise. A user can override its behavior for a class // type Foo by defining either operator<<(::std::ostream&, const Foo&) // or void PrintTo(const Foo&, ::std::ostream*) in the namespace that // defines Foo. #include #include #include // NOLINT #include namespace testing { namespace { using ::std::ostream; // Prints a segment of bytes in the given object. void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, size_t count, ostream* os) { char text[5] = ""; for (size_t i = 0; i != count; i++) { const size_t j = start + i; if (i != 0) { // Organizes the bytes into groups of 2 for easy parsing by // human. if ((j % 2) == 0) *os << ' '; else *os << '-'; } GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); *os << text; } } // Prints the bytes in the given value to the given ostream. void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, ostream* os) { // Tells the user how big the object is. *os << count << "-byte object <"; const size_t kThreshold = 132; const size_t kChunkSize = 64; // If the object size is bigger than kThreshold, we'll have to omit // some details by printing only the first and the last kChunkSize // bytes. // TODO(wan): let the user control the threshold using a flag. if (count < kThreshold) { PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); } else { PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); *os << " ... "; // Rounds up to 2-byte boundary. const size_t resume_pos = (count - kChunkSize + 1)/2*2; PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); } *os << ">"; } } // namespace namespace internal2 { // Delegates to PrintBytesInObjectToImpl() to print the bytes in the // given object. The delegation simplifies the implementation, which // uses the << operator and thus is easier done outside of the // ::testing::internal namespace, which contains a << operator that // sometimes conflicts with the one in STL. void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, ostream* os) { PrintBytesInObjectToImpl(obj_bytes, count, os); } } // namespace internal2 namespace internal { // Depending on the value of a char (or wchar_t), we print it in one // of three formats: // - as is if it's a printable ASCII (e.g. 'a', '2', ' '), // - as a hexidecimal escape sequence (e.g. '\x7F'), or // - as a special escape sequence (e.g. '\r', '\n'). enum CharFormat { kAsIs, kHexEscape, kSpecialEscape }; // Returns true if c is a printable ASCII character. We test the // value of c directly instead of calling isprint(), which is buggy on // Windows Mobile. inline bool IsPrintableAscii(wchar_t c) { return 0x20 <= c && c <= 0x7E; } // Prints a wide or narrow char c as a character literal without the // quotes, escaping it when necessary; returns how c was formatted. // The template argument UnsignedChar is the unsigned version of Char, // which is the type of c. template static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { switch (static_cast(c)) { case L'\0': *os << "\\0"; break; case L'\'': *os << "\\'"; break; case L'\\': *os << "\\\\"; break; case L'\a': *os << "\\a"; break; case L'\b': *os << "\\b"; break; case L'\f': *os << "\\f"; break; case L'\n': *os << "\\n"; break; case L'\r': *os << "\\r"; break; case L'\t': *os << "\\t"; break; case L'\v': *os << "\\v"; break; default: if (IsPrintableAscii(c)) { *os << static_cast(c); return kAsIs; } else { *os << "\\x" + String::FormatHexInt(static_cast(c)); return kHexEscape; } } return kSpecialEscape; } // Prints a wchar_t c as if it's part of a string literal, escaping it when // necessary; returns how c was formatted. static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { switch (c) { case L'\'': *os << "'"; return kAsIs; case L'"': *os << "\\\""; return kSpecialEscape; default: return PrintAsCharLiteralTo(c, os); } } // Prints a char c as if it's part of a string literal, escaping it when // necessary; returns how c was formatted. static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { return PrintAsStringLiteralTo( static_cast(static_cast(c)), os); } // Prints a wide or narrow character c and its code. '\0' is printed // as "'\\0'", other unprintable characters are also properly escaped // using the standard C++ escape sequence. The template argument // UnsignedChar is the unsigned version of Char, which is the type of c. template void PrintCharAndCodeTo(Char c, ostream* os) { // First, print c as a literal in the most readable form we can find. *os << ((sizeof(c) > 1) ? "L'" : "'"); const CharFormat format = PrintAsCharLiteralTo(c, os); *os << "'"; // To aid user debugging, we also print c's code in decimal, unless // it's 0 (in which case c was printed as '\\0', making the code // obvious). if (c == 0) return; *os << " (" << static_cast(c); // For more convenience, we print c's code again in hexidecimal, // unless c was already printed in the form '\x##' or the code is in // [1, 9]. if (format == kHexEscape || (1 <= c && c <= 9)) { // Do nothing. } else { *os << ", 0x" << String::FormatHexInt(static_cast(c)); } *os << ")"; } void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); } void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); } // Prints a wchar_t as a symbol if it is printable or as its internal // code otherwise and also as its code. L'\0' is printed as "L'\\0'". void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); } // Prints the given array of characters to the ostream. CharType must be either // char or wchar_t. // The array starts at begin, the length is len, it may include '\0' characters // and may not be NUL-terminated. template static void PrintCharsAsStringTo( const CharType* begin, size_t len, ostream* os) { const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; *os << kQuoteBegin; bool is_previous_hex = false; for (size_t index = 0; index < len; ++index) { const CharType cur = begin[index]; if (is_previous_hex && IsXDigit(cur)) { // Previous character is of '\x..' form and this character can be // interpreted as another hexadecimal digit in its number. Break string to // disambiguate. *os << "\" " << kQuoteBegin; } is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; } *os << "\""; } // Prints a (const) char/wchar_t array of 'len' elements, starting at address // 'begin'. CharType must be either char or wchar_t. template static void UniversalPrintCharArray( const CharType* begin, size_t len, ostream* os) { // The code // const char kFoo[] = "foo"; // generates an array of 4, not 3, elements, with the last one being '\0'. // // Therefore when printing a char array, we don't print the last element if // it's '\0', such that the output matches the string literal as it's // written in the source code. if (len > 0 && begin[len - 1] == '\0') { PrintCharsAsStringTo(begin, len - 1, os); return; } // If, however, the last element in the array is not '\0', e.g. // const char kFoo[] = { 'f', 'o', 'o' }; // we must print the entire array. We also print a message to indicate // that the array is not NUL-terminated. PrintCharsAsStringTo(begin, len, os); *os << " (no terminating NUL)"; } // Prints a (const) char array of 'len' elements, starting at address 'begin'. void UniversalPrintArray(const char* begin, size_t len, ostream* os) { UniversalPrintCharArray(begin, len, os); } // Prints a (const) wchar_t array of 'len' elements, starting at address // 'begin'. void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { UniversalPrintCharArray(begin, len, os); } // Prints the given C string to the ostream. void PrintTo(const char* s, ostream* os) { if (s == NULL) { *os << "NULL"; } else { *os << ImplicitCast_(s) << " pointing to "; PrintCharsAsStringTo(s, strlen(s), os); } } // MSVC compiler can be configured to define whar_t as a typedef // of unsigned short. Defining an overload for const wchar_t* in that case // would cause pointers to unsigned shorts be printed as wide strings, // possibly accessing more memory than intended and causing invalid // memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when // wchar_t is implemented as a native type. #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) // Prints the given wide C string to the ostream. void PrintTo(const wchar_t* s, ostream* os) { if (s == NULL) { *os << "NULL"; } else { *os << ImplicitCast_(s) << " pointing to "; PrintCharsAsStringTo(s, wcslen(s), os); } } #endif // wchar_t is native // Prints a ::string object. #if GTEST_HAS_GLOBAL_STRING void PrintStringTo(const ::string& s, ostream* os) { PrintCharsAsStringTo(s.data(), s.size(), os); } #endif // GTEST_HAS_GLOBAL_STRING void PrintStringTo(const ::std::string& s, ostream* os) { PrintCharsAsStringTo(s.data(), s.size(), os); } // Prints a ::wstring object. #if GTEST_HAS_GLOBAL_WSTRING void PrintWideStringTo(const ::wstring& s, ostream* os) { PrintCharsAsStringTo(s.data(), s.size(), os); } #endif // GTEST_HAS_GLOBAL_WSTRING #if GTEST_HAS_STD_WSTRING void PrintWideStringTo(const ::std::wstring& s, ostream* os) { PrintCharsAsStringTo(s.data(), s.size(), os); } #endif // GTEST_HAS_STD_WSTRING } // namespace internal } // namespace testing // Copyright 2008, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: mheule@google.com (Markus Heule) // // The Google C++ Testing Framework (Google Test) // Indicates that this translation unit is part of Google Test's // implementation. It must come before gtest-internal-inl.h is // included, or there will be a compiler error. This trick is to // prevent a user from accidentally including gtest-internal-inl.h in // his code. #define GTEST_IMPLEMENTATION_ 1 #undef GTEST_IMPLEMENTATION_ namespace testing { using internal::GetUnitTestImpl; // Gets the summary of the failure message by omitting the stack trace // in it. std::string TestPartResult::ExtractSummary(const char* message) { const char* const stack_trace = strstr(message, internal::kStackTraceMarker); return stack_trace == NULL ? message : std::string(message, stack_trace); } // Prints a TestPartResult object. std::ostream& operator<<(std::ostream& os, const TestPartResult& result) { return os << result.file_name() << ":" << result.line_number() << ": " << (result.type() == TestPartResult::kSuccess ? "Success" : result.type() == TestPartResult::kFatalFailure ? "Fatal failure" : "Non-fatal failure") << ":\n" << result.message() << std::endl; } // Appends a TestPartResult to the array. void TestPartResultArray::Append(const TestPartResult& result) { array_.push_back(result); } // Returns the TestPartResult at the given index (0-based). const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const { if (index < 0 || index >= size()) { printf("\nInvalid index (%d) into TestPartResultArray.\n", index); internal::posix::Abort(); } return array_[index]; } // Returns the number of TestPartResult objects in the array. int TestPartResultArray::size() const { return static_cast(array_.size()); } namespace internal { HasNewFatalFailureHelper::HasNewFatalFailureHelper() : has_new_fatal_failure_(false), original_reporter_(GetUnitTestImpl()-> GetTestPartResultReporterForCurrentThread()) { GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this); } HasNewFatalFailureHelper::~HasNewFatalFailureHelper() { GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread( original_reporter_); } void HasNewFatalFailureHelper::ReportTestPartResult( const TestPartResult& result) { if (result.fatally_failed()) has_new_fatal_failure_ = true; original_reporter_->ReportTestPartResult(result); } } // namespace internal } // namespace testing // Copyright 2008 Google Inc. // All Rights Reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Author: wan@google.com (Zhanyong Wan) namespace testing { namespace internal { #if GTEST_HAS_TYPED_TEST_P // Skips to the first non-space char in str. Returns an empty string if str // contains only whitespace characters. static const char* SkipSpaces(const char* str) { while (IsSpace(*str)) str++; return str; } // Verifies that registered_tests match the test names in // defined_test_names_; returns registered_tests if successful, or // aborts the program otherwise. const char* TypedTestCasePState::VerifyRegisteredTestNames( const char* file, int line, const char* registered_tests) { typedef ::std::set::const_iterator DefinedTestIter; registered_ = true; // Skip initial whitespace in registered_tests since some // preprocessors prefix stringizied literals with whitespace. registered_tests = SkipSpaces(registered_tests); Message errors; ::std::set tests; for (const char* names = registered_tests; names != NULL; names = SkipComma(names)) { const std::string name = GetPrefixUntilComma(names); if (tests.count(name) != 0) { errors << "Test " << name << " is listed more than once.\n"; continue; } bool found = false; for (DefinedTestIter it = defined_test_names_.begin(); it != defined_test_names_.end(); ++it) { if (name == *it) { found = true; break; } } if (found) { tests.insert(name); } else { errors << "No test named " << name << " can be found in this test case.\n"; } } for (DefinedTestIter it = defined_test_names_.begin(); it != defined_test_names_.end(); ++it) { if (tests.count(*it) == 0) { errors << "You forgot to list test " << *it << ".\n"; } } const std::string& errors_str = errors.GetString(); if (errors_str != "") { fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), errors_str.c_str()); fflush(stderr); posix::Abort(); } return registered_tests; } #endif // GTEST_HAS_TYPED_TEST_P } // namespace internal } // namespace testing Jellyfish-2.2.8/unit_tests/gtest/src/gtest_main.cc000066400000000000000000000033451323712541700222450ustar00rootroot00000000000000// Copyright 2006, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "gtest/gtest.h" GTEST_API_ int main(int argc, char **argv) { printf("Running main() from gtest_main.cc\n"); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } Jellyfish-2.2.8/unit_tests/test_allocators_mmap.cc000066400000000000000000000005211323712541700224030ustar00rootroot00000000000000#include #include namespace { TEST(AllocMmap, Simple) { static const size_t size = 4096; allocators::mmap mem(size); EXPECT_EQ(size, mem.get_size()); EXPECT_NE((void*)0, mem.get_ptr()); char* ptr = (char*)mem.get_ptr(); // char c = ptr[size]; // EXPECT_EQ((char)0, c); } } Jellyfish-2.2.8/unit_tests/test_atomic_bits_array.cc000066400000000000000000000014211323712541700227210ustar00rootroot00000000000000#include #include #include #include namespace { TEST(AtomicBitsArray, Fill) { static const size_t size = 2066; static const int bits = 3; jellyfish::atomic_bits_array ary(bits, size); std::unique_ptr data(new unsigned char[size]); for(size_t i = 0; i < size; ++i) { data[i] = random_bits(bits); auto e = ary[i]; e.get(); EXPECT_TRUE(e.set(data[i])); } auto it = ary.begin(); auto it_end = ary.end(); for(size_t i = 0; i < size; ++i, ++it) { auto e = ary[i]; EXPECT_EQ(data[i], e.get()); EXPECT_EQ(data[i], (unsigned char)e); ASSERT_NE(it_end, it); EXPECT_EQ(data[i], *it); } EXPECT_EQ(it_end, it); } } Jellyfish-2.2.8/unit_tests/test_cond.cc000066400000000000000000000033051323712541700201540ustar00rootroot00000000000000#include #include using testing::Types; #define NB_THREADS 3 #define COUNT 1000000 template class CondTest : public ::testing::Test { int volatile count; int count_at_signal; cond count_cond; pthread_t threads[NB_THREADS+1]; pthread_attr_t attr; public: CondTest() : count(0), count_at_signal(0), count_cond() { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_create(&threads[0], &attr, master_fun, (void *)this); for(int i = 1; i < NB_THREADS+1; i++) pthread_create(&threads[i], &attr, thread_fun, (void *)this); for(int i = 0; i <= NB_THREADS; i++) pthread_join(threads[i], NULL); } static void *master_fun(void *t) { CondTest *self = (CondTest *)t; self->master_wait(); return NULL; } void master_wait() { count_cond.lock(); count_cond.wait(); count_at_signal = count; sleep(1); count *= 10; count_cond.unlock(); } static void *thread_fun(void *t) { CondTest *self = (CondTest *)t; self->inc(); return NULL; } void inc() { for(int i = 0; i < COUNT; i++) { count_cond.lock(); if(count < 1000000) { count++; if(count > 100000) count_cond.signal(); count_cond.unlock(); } else { count_cond.unlock(); return; } } } int get_count() { return count; } int get_count_at_signal() { return count_at_signal; } }; typedef Types Implementations; TYPED_TEST_CASE(CondTest, Implementations); TYPED_TEST(CondTest, SuccessfullLocking) { EXPECT_EQ(10 *this->get_count_at_signal(), this->get_count()); } Jellyfish-2.2.8/unit_tests/test_cooperative_pool2.cc000066400000000000000000000042771323712541700226750ustar00rootroot00000000000000#include #include #include namespace { // Generate all numbers in [0, producers * max) class sequence : public jellyfish::cooperative_pool2 { typedef jellyfish::cooperative_pool2 super; const uint32_t max_; std::vector cur_; const uint32_t producers_; public: std::vector check_; sequence(uint32_t producers, uint32_t threads, uint32_t max) : super(producers, 3 * threads), max_(max), cur_(producers, 0), producers_(producers), check_(max * producers, 0) { } bool produce(uint32_t i, int& e) { assert(i < producers_); int& cur = cur_[i]; if(cur < max_) { e = i * max_ + cur++; __sync_add_and_fetch(&check_[e], 1); return false; } return true; } }; class list_ints : public jellyfish::thread_exec { sequence seq_; std::vector check_; public: list_ints(uint32_t producers, uint32_t threads, uint32_t max) : seq_(producers, threads, max), check_(producers * max, 0) { } virtual void start(int i) { while(true) { sequence::job j(seq_); if(j.is_empty()) break; ++check_[*j]; } } bool check() const { for(auto it = check_.cbegin(); it != check_.cend(); ++it) if(*it != 1) return false; return true; } bool check_print() const { if(check()) return true; for(auto it = check_.cbegin(); it != check_.cend(); ++it) printf("%d", *it); printf("\n----------\n"); for(auto it = seq_.check_.cbegin(); it != seq_.check_.cend(); ++it) printf("%d", *it); printf("\n"); return false; } }; class CooperativePoolTest : public ::testing::TestWithParam { public: static const uint32_t nb_threads = 10; CooperativePoolTest() : workers(GetParam(), nb_threads, 1000) { } protected: list_ints workers; }; TEST_P(CooperativePoolTest, Ints) { workers.exec_join(nb_threads); EXPECT_TRUE(workers.check_print()); } INSTANTIATE_TEST_CASE_P(CooperativePool, CooperativePoolTest, ::testing::Range((uint32_t)1, CooperativePoolTest::nb_threads + 1)); } // namespace { Jellyfish-2.2.8/unit_tests/test_dumpers.cc000066400000000000000000000101161323712541700207060ustar00rootroot00000000000000#include #include #include #include #include #include #include #include namespace { using jellyfish::mer_dna; using jellyfish::file_header; typedef jellyfish::cooperative::hash_counter hash_counter; typedef hash_counter::array::eager_iterator iterator; struct binary { typedef jellyfish::binary_dumper dumper; typedef jellyfish::binary_reader reader; typedef jellyfish::binary_query_base query; }; struct text { typedef jellyfish::text_dumper dumper; typedef jellyfish::text_reader reader; }; TEST(Dumper, IO) { static const int mer_len = 50; static const int hash_size = 5000; static const int nb = hash_size; static const int hash_val_len = 5; static const int dump_counter_len = 1; static const char* file_binary = "./binary_dumper"; static const char* file_text = "./text_dumper"; file_unlink bf(file_binary); file_unlink tf(file_text); mer_dna::k(mer_len); hash_counter hash(hash_size, mer_len * 2, 5 /* val len */, 1 /* nb threads */); mer_dna m; for(int i = 0; i < nb; i++) { m.randomize(); const uint64_t rval = random_bits(9); hash.add(m, rval); uint64_t val; ASSERT_TRUE(hash.ary()->get_val_for_key(m, &val)); EXPECT_EQ(rval, val); } // Dump without zeroing to check dumped content against in memory hash { file_header bh; bh.fill_standard(); bh.update_from_ary(*hash.ary()); binary::dumper bd(dump_counter_len, mer_len * 2, 4, file_binary, &bh); bd.one_file(true); bd.zero_array(false); bd.dump(hash.ary()); file_header th; th.fill_standard(); th.update_from_ary(*hash.ary()); text::dumper td(4, file_text, &th); td.one_file(true); td.zero_array(false); td.dump(hash.ary()); } // Check dumped content { file_header bh; std::ifstream bis(file_binary); bh.read(bis); EXPECT_STREQ(binary::dumper::format, bh.format().c_str()); EXPECT_EQ(dump_counter_len, bh.counter_len()); binary::reader br(bis, &bh); jellyfish::mapped_file binary_map(file_binary); binary::query bq(binary_map.base() + bh.offset(), bh.key_len(), bh.counter_len(), bh.matrix(), bh.size() - 1, binary_map.length() - bh.offset()); file_header th; std::ifstream tis(file_text); th.read(tis); EXPECT_STREQ(binary::dumper::format, bh.format().c_str()); text::reader tr(tis, &th); const uint64_t max_val = ((uint64_t)1 << (8 * dump_counter_len)) - 1; int bcount = 0, tcount = 0, qcount = 0; mer_dna tmp_key; while(br.next()) { uint64_t val = 0; size_t id = 0; bool present = hash.ary()->get_val_for_key(br.key(), &val, tmp_key, &id); EXPECT_TRUE(present); if(present) { EXPECT_EQ(std::min(max_val, val), br.val()); ++bcount; } EXPECT_TRUE(tr.next()); present = hash.ary()->get_val_for_key(tr.key(), &val); EXPECT_TRUE(present); if(present) { EXPECT_EQ(val, tr.val()); ++tcount; } uint64_t query_val; uint64_t query_id; present = bq.val_id(br.key(), &query_val, &query_id); EXPECT_TRUE(present); if(present) { EXPECT_EQ(std::min(max_val, val), query_val); // EXPECT_EQ(id, query_id); ++qcount; } } EXPECT_EQ(nb, bcount); EXPECT_EQ(nb, tcount); EXPECT_EQ(nb, qcount); } // Dump with zeroing and check hash is empty { file_header bh; bh.fill_standard(); bh.update_from_ary(*hash.ary()); binary::dumper bd(dump_counter_len, mer_len * 2, 4, file_binary, &bh); bd.one_file(true); bd.zero_array(true); bd.dump(hash.ary()); } { iterator it = hash.ary()->eager_slice(0, 1); uint64_t count = 0; while(it.next()) ++count; EXPECT_EQ((uint64_t)0, count); } } } // namespace { Jellyfish-2.2.8/unit_tests/test_file_header.cc000066400000000000000000000046701323712541700214660ustar00rootroot00000000000000#include #include #include #include #include #include namespace { using jellyfish::file_header; using jellyfish::RectangularBinaryMatrix; using std::ostringstream; using std::istringstream; using std::string; TEST(FileHeader, Standard) { file_header h; EXPECT_EQ("", h["hostname"]); EXPECT_EQ("", h["pwd"]); EXPECT_EQ("", h["time"]); EXPECT_EQ("", h["exe_path"]); h.fill_standard(); EXPECT_NE("", h["hostname"]); EXPECT_NE("", h["pwd"]); EXPECT_NE("", h["time"]); EXPECT_NE("", h["exe_path"]); } TEST(FileHeader, WriteRead) { file_header hw; ostringstream os; os.fill('A'); os.width(20); os << std::hex; std::ios::fmtflags flags = os.flags(); const size_t random_size = random_bits(35); const unsigned int val_len = random_bits(4); const unsigned int max_reprobe = random_bits(7); const double fpr = (double)random_bits(10) / 1024.0; RectangularBinaryMatrix m1(random_bits(6) + 1, random_bits(8) + 1); m1.randomize(random_bits); RectangularBinaryMatrix m2 = RectangularBinaryMatrix::identity(random_bits(6) + 1); EXPECT_EQ(8, hw.alignment()); hw.fill_standard(); hw.size(random_size); hw.matrix(m1, 1); hw.matrix(m2, 2); hw.key_len(m1.r()); hw.val_len(val_len); hw.max_reprobe(max_reprobe); hw.set_reprobes(jellyfish::quadratic_reprobes); hw.fpr(fpr); hw.write(os); EXPECT_EQ(0, os.tellp() % 8); EXPECT_EQ('A', os.fill()); EXPECT_EQ(20, os.width()); EXPECT_EQ(flags, os.flags()); os.width(0); const string ah("After header"); os << ah; // std::cerr << os.str() << "\n"; istringstream is(os.str()); file_header hr; EXPECT_TRUE(hr.read(is)); EXPECT_EQ(is.tellg(), hr.offset()); EXPECT_EQ(0, is.tellg() % 8); EXPECT_EQ(8, hr.alignment()); EXPECT_EQ(random_size, hr.size()); EXPECT_EQ(m1, hr.matrix(1)); EXPECT_TRUE(hr.matrix(2).is_low_identity()); EXPECT_EQ(m2.r(), hr.matrix(2).r()); EXPECT_EQ(m1.r(), hr.key_len()); EXPECT_EQ(val_len, hr.val_len()); EXPECT_EQ(fpr, hr.fpr()); size_t reprobes[max_reprobe + 1]; hr.get_reprobes(reprobes); for(unsigned int i = 0; i <= max_reprobe; ++i) EXPECT_EQ(jellyfish::quadratic_reprobes[i], reprobes[i]); // Not sure why the following fails. But all the fields come out // equal so ignore for now // EXPECT_EQ(hw, hr); string line; getline(is, line); EXPECT_EQ(ah, line); } } // namespace { Jellyfish-2.2.8/unit_tests/test_generator_manager.cc000066400000000000000000000047011323712541700227120ustar00rootroot00000000000000#include #include #include #include #include #include #include #include namespace { static const int nb_pipes = 5; TEST(TmpPipes, CreateDestroy) { std::vector pipe_paths; { jellyfish::tmp_pipes pipes(nb_pipes); EXPECT_EQ(nb_pipes, pipes.size()); for(int i = 0; i < nb_pipes; ++i) { struct stat buf; ASSERT_EQ(0, stat(pipes[i], &buf)); EXPECT_TRUE(S_ISFIFO(buf.st_mode)); pipe_paths.push_back(pipes[i]); } } for(auto it = pipe_paths.begin(); it != pipe_paths.end(); ++it) { struct stat buf; EXPECT_EQ(-1, stat(it->c_str(), &buf)); } } TEST(TmpPipes, Discard) { jellyfish::tmp_pipes pipes(nb_pipes); for(int i = 0; i < nb_pipes; ++i) { ASSERT_STRNE("", pipes[i]); std::string path(pipes[i]); int fd = open(path.c_str(), O_RDONLY|O_NONBLOCK); ASSERT_NE(-1, fd); pipes.discard(i); EXPECT_STREQ("", pipes[i]); struct stat buf; EXPECT_EQ(-1, stat(path.c_str(), &buf)); char rbuf[1]; EXPECT_EQ((ssize_t)0, read(fd, rbuf, 1)); close(fd); } } TEST(GeneratorManager, OneLiners) { static const char* cmds_file = "./cmds_file"; file_unlink unlink_cmds(cmds_file); { std::ofstream cmds(cmds_file, std::ios::out|std::ios::trunc); ASSERT_TRUE(cmds.good()) << "Failed to open cmd file '" << cmds_file << "'"; cmds << "echo hello\n" << "date\n" << "whoami\n" << "uname\n"; ASSERT_TRUE(cmds.good()) << "Failed to write to cmd file"; } std::ifstream cmds(cmds_file); ASSERT_TRUE(cmds.good()) << "Failed top open cmd file '" << cmds_file << "'"; static const int nb_pipes = 2; int active_pipes = nb_pipes; bool active[nb_pipes]; jellyfish::generator_manager manager(cmds_file, nb_pipes); manager.start(); for(int i = 0; i < nb_pipes; ++i) active[i] = true; std::vector lines; while(active_pipes > 0) { for(int i = 0; i < nb_pipes; ++i) { if(!active[i]) continue; std::ifstream p(manager.pipes()[i]); if(!p.good()) { active[i] = false; --active_pipes; continue; } std::string line; while(std::getline(p, line)) lines.push_back(line); } } EXPECT_TRUE(manager.wait()); EXPECT_EQ((size_t)4, lines.size()); } } Jellyfish-2.2.8/unit_tests/test_hash_counter.cc000066400000000000000000000051441323712541700217160ustar00rootroot00000000000000#include #include #include #include #include #include #include namespace { using jellyfish::thread_exec; using jellyfish::mer_dna; typedef jellyfish::cooperative::hash_counter hash_counter; typedef hash_counter::array::lazy_iterator lazy_iterator; enum OPERATION { ADD, SET }; class hash_adder : public thread_exec { typedef std::map map; typedef std::vector maps; hash_counter& hash_; int nb_; maps check_; OPERATION op_; public: hash_adder(hash_counter& hash, int nb, int nb_threads, OPERATION op) : hash_(hash), nb_(nb), check_(nb_threads), op_(op) { } void start(int id) { mer_dna m; map& my_map = check_[id]; for(int i = 0; i < nb_; ++i) { m.randomize(); switch(op_) { case ADD: hash_.add(m, std::numeric_limits::max()); break; case SET: hash_.set(m); break; } my_map[m] = std::numeric_limits::max(); } hash_.done(); } uint64_t val(const mer_dna& m) { uint64_t res = 0; for(maps::const_iterator it = check_.begin(); it < check_.end(); ++it) { map::const_iterator vit = (*it).find(m); if(vit != it->end()) res += vit->second; } return res; } }; TEST(HashCounterCooperative, SizeDouble) { static const int mer_len = 35; static const int nb_threads = 1; static const int nb = 200; static const size_t init_size = 128; mer_dna::k(mer_len); { hash_counter hash(init_size, mer_len * 2, 5, nb_threads); EXPECT_TRUE(hash.do_size_doubling()); EXPECT_EQ(mer_len * 2, hash.key_len()); EXPECT_EQ(5, hash.val_len()); hash_adder adder(hash, nb, nb_threads, ADD); adder.exec_join(nb_threads); lazy_iterator it = hash.ary()->iterator_all(); while(it.next()) EXPECT_EQ(adder.val(it.key()), it.val()); EXPECT_LT((size_t)(nb_threads * nb), hash.size()); } { hash_counter hash(init_size, mer_len * 2, 0, nb_threads); EXPECT_TRUE(hash.do_size_doubling()); EXPECT_EQ(mer_len * 2, hash.key_len()); EXPECT_EQ(0, hash.val_len()); hash_adder adder(hash, nb, nb_threads, SET); adder.exec_join(nb_threads); lazy_iterator it = hash.ary()->iterator_all(); while(it.next()) { SCOPED_TRACE(::testing::Message() << "mer:" << it.key()); EXPECT_EQ(0, it.val()); } EXPECT_LT((size_t)(nb_threads * nb), hash.size()); } } } // namespace { Jellyfish-2.2.8/unit_tests/test_int128.cc000066400000000000000000000017431323712541700202620ustar00rootroot00000000000000#include #include #ifdef HAVE_INT128 #include #include namespace { TEST(Int128, Specialized) { // This is supposed to be true, whether it is specialized by gcc or // in int128.hpp above. EXPECT_TRUE(std::numeric_limits<__int128>::is_specialized); EXPECT_TRUE(std::numeric_limits::is_specialized); } TEST(Int128, Max) { static const __int128 sone = 1; static const unsigned __int128 uone = 1; __int128 sm = std::numeric_limits<__int128>::max(); unsigned __int128 um = std::numeric_limits::max(); for(int i = 0; i < 127; ++i, sm >>= 1, um >>= 1) { EXPECT_EQ(1, (int)(sm & sone)); EXPECT_EQ(1, (int)(um & uone)); EXPECT_EQ(1, (int)((std::numeric_limits<__int128>::max() >> i) & sone)); EXPECT_EQ(1, (int)((std::numeric_limits::max() >> i) & uone)); } EXPECT_EQ(0, (int)sm); EXPECT_EQ(1, (int)um); } } // namespace #endif // HAVE_INT128 Jellyfish-2.2.8/unit_tests/test_large_block.cc000066400000000000000000000016251323712541700215000ustar00rootroot00000000000000#include #include #include #include using testing::Types; #define SMALL_SIZE ((size_t)4096) template class LargeBlockTest : public ::testing::Test { public: large_block block; LargeBlockTest() : block(SMALL_SIZE) {} void *double_size() { return block.realloc(block.get_size() * 2); } }; typedef Types Implementations; TYPED_TEST_CASE(LargeBlockTest, Implementations); TYPED_TEST(LargeBlockTest, SuccessfulAllocation) { EXPECT_NE((void *)0, this->block.get_ptr()); EXPECT_EQ(SMALL_SIZE, this->block.get_size()); void *new_ptr = this->double_size(); EXPECT_NE((void *)0, new_ptr); EXPECT_NE((void *)0, this->block.get_ptr()); EXPECT_EQ(new_ptr, this->block.get_ptr()); EXPECT_EQ(SMALL_SIZE * 2, this->block.get_size()); } Jellyfish-2.2.8/unit_tests/test_large_hash_array.cc000066400000000000000000000262051323712541700225300ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include void PrintTo(jellyfish::mer_dna& m, ::std::ostream* os) { *os << m.to_str(); } namespace { typedef jellyfish::large_hash::unbounded_array large_array; typedef std::map mer_map; typedef std::set mer_set; using jellyfish::RectangularBinaryMatrix; using jellyfish::mer_dna; using std::numeric_limits; typedef large_array::iterator stl_iterator; typedef large_array::eager_iterator eager_iterator; typedef large_array::lazy_iterator lazy_iterator; typedef large_array::region_iterator region_iterator; // Tuple is {key_len, val_len, reprobe_len}. class HashArray : public ::testing::TestWithParam< ::std::tr1::tuple > { public: static const size_t ary_lsize = 10; static const size_t ary_size = (size_t)1 << ary_lsize; static const size_t ary_size_mask = ary_size - 1; const int key_len, val_len, reprobe_len, reprobe_limit; large_array ary; HashArray() : key_len(::std::tr1::get<0>(GetParam())), val_len(::std::tr1::get<1>(GetParam())), reprobe_len(::std::tr1::get<2>(GetParam())), reprobe_limit((1 << reprobe_len) - 2), ary(ary_size, key_len, val_len, reprobe_limit) { } void SetUp() { jellyfish::mer_dna::k(key_len / 2); } ~HashArray() { } }; TEST_P(HashArray, OneElement) { mer_dna m, m2, get_mer; SCOPED_TRACE(::testing::Message() << "key_len:" << key_len << " val_len:" << val_len << " reprobe:" << reprobe_limit); EXPECT_EQ((unsigned int)ary_lsize, ary.matrix().r()); EXPECT_EQ((unsigned int)key_len, ary.matrix().c()); size_t start_pos = random() % (ary_size - bsizeof(uint64_t)); size_t mask = (size_t)key_len >= bsizeof(size_t) ? (size_t)-1 : ((size_t)1 << key_len) - 1; for(uint64_t i = start_pos; i < start_pos + bsizeof(uint64_t); ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i); // Create mer m so that it will hash to position i m.randomize(); m2 = m; m2.set_bits(0, ary.matrix().r(), (uint64_t)i); m.set_bits(0, ary.matrix().r(), ary.inverse_matrix().times(m2)); // Add this one element to the hash ary.clear(); bool is_new = false; size_t id = (size_t)-1; unsigned int carry_shift = 0; EXPECT_TRUE(ary.add(m, i, &carry_shift, &is_new, &id)); EXPECT_TRUE(is_new); // Only expected to agree on the length of the key. Applies only // if key_len < lsize. The bits above key_len are pseudo-random EXPECT_EQ((size_t)i & mask, id & mask); // Every position but i in the hash should be empty uint64_t val; for(ssize_t j = -bsizeof(uint64_t); j <= (ssize_t)bsizeof(uint64_t); ++j) { SCOPED_TRACE(::testing::Message() << "j:" << j); val = (uint64_t)-1; size_t jd = (start_pos + j) & ary_size_mask; ASSERT_EQ(jd == id, ary.get_key_val_at_id(jd, get_mer, val) == large_array::FILLED); if(jd == id) { ASSERT_EQ(m2, get_mer); ASSERT_EQ((uint64_t)jd, val); } } } } TEST_P(HashArray, Collisions) { static const int nb_collisions = 4; std::vector mers(nb_collisions); std::vector mers2(nb_collisions); std::map map; ASSERT_EQ((unsigned int)key_len / 2, mer_dna::k()); SCOPED_TRACE(::testing::Message() << "key_len:" << key_len << " val_len:" << val_len << " reprobe:" << reprobe_limit); mers[0].polyA(); mers2[0].polyA(); mers[1].polyC(); mers2[1].polyC(); mers[2].polyG(); mers2[2].polyG(); mers[3].polyT(); mers2[3].polyT(); size_t start_pos = random() % (ary_size - bsizeof(uint64_t)); for(uint64_t i = start_pos; i < start_pos + bsizeof(uint64_t); ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i); ary.clear(); map.clear(); // Add mers that it will all hash to position i for(int j = 0; j < nb_collisions; ++j) { mers2[j].set_bits(0, ary.matrix().r(), (uint64_t)i); mers[j].set_bits(0, ary.matrix().r(), ary.inverse_matrix().times(mers2[j])); ary.add(mers[j], j); map[mers[j]] += j; } lazy_iterator it = ary.iterator_all(); size_t count = 0; while(it.next()) { SCOPED_TRACE(::testing::Message() << "it.key():" << it.key()); ASSERT_FALSE(map.end() == map.find(it.key())); EXPECT_EQ(map[it.key()], it.val()); ++count; } EXPECT_EQ(map.size(), count); } } struct arrays_type { large_array array; mer_map map; arrays_type(size_t size, uint16_t key_len, uint16_t val_len, uint16_t reprobe_limit) : array(size, key_len, val_len, reprobe_limit), map() { } }; typedef std::unique_ptr arrays_ptr; arrays_ptr fill_array(size_t nb_elts, size_t size, int key_len, int val_len, int reprobe_limit) { arrays_ptr arrays(new arrays_type(size, key_len, val_len, reprobe_limit)); large_array& ary = arrays->array; mer_map& map = arrays->map; mer_dna mer; for(int i = 0; i < nb_elts; ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i); mer.randomize(); map[mer] += i; // If get false, hash array filled up: double size bool res = ary.add(mer, i); if(!res) { // std::cerr << "Double size (" << size << " -> " << (2 * size) << ") nb_elts:" << nb_elts // << " key_len:" << key_len << " val_len:" << val_len // << " mer:" << mer << std::endl; // return std::make_pair(std::move(ary), std::move(map)); return fill_array(nb_elts, 2 * size, key_len, val_len, reprobe_limit); } } return arrays; } TEST_P(HashArray, Iterator) { static const int nb_elts = 1 << (ary_lsize - 1 - (val_len == 1)); SCOPED_TRACE(::testing::Message() << "key_len:" << key_len << " val_len:" << val_len << " reprobe:" << reprobe_limit); arrays_ptr res = fill_array(nb_elts, ary_size, key_len, val_len, reprobe_limit); large_array& ary = res->array; mer_map & map = res->map; eager_iterator it = ary.iterator_all(); lazy_iterator lit = ary.iterator_all(); stl_iterator stl_it = ary.iterator_all(); int count = 0; for( ; it.next(); ++stl_it) { ASSERT_TRUE(lit.next()); ASSERT_NE(ary.end(), stl_it); mer_map::const_iterator mit = map.find(it.key()); SCOPED_TRACE(::testing::Message() << "key:" << it.key()); ASSERT_NE(map.end(), mit); EXPECT_EQ(mit->first, it.key()); EXPECT_EQ(mit->second, it.val()); EXPECT_EQ(mit->first, lit.key()); EXPECT_EQ(mit->second, lit.val()); EXPECT_EQ(mit->first, stl_it->first); EXPECT_EQ(mit->second, stl_it->second); EXPECT_EQ(it.id(), lit.id()); EXPECT_EQ(it.id(), stl_it.id()); ++count; } EXPECT_FALSE(lit.next()); EXPECT_EQ(ary.end(), stl_it); EXPECT_EQ(map.size(), (size_t)count); count = 0; const int nb_slices = 1; for(int i = 0; i < nb_slices; ++i) { SCOPED_TRACE(::testing::Message() << "slice:" << i << " nb_slices:" << nb_slices); region_iterator rit = ary.iterator_slice(i, nb_slices); while(rit.next()) { ASSERT_GE(rit.oid(), rit.start()); ASSERT_LT(rit.oid(), rit.end()); mer_map::const_iterator mit = map.find(rit.key()); ASSERT_NE(map.end(), mit); EXPECT_EQ(mit->first, rit.key()); EXPECT_EQ(mit->second, rit.val()); ++count; } } EXPECT_EQ(map.size(), (size_t)count); int i = 0; for(mer_map::const_iterator it = map.begin(); it != map.end(); ++it, ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i << " key:" << it->first); uint64_t val; size_t id; EXPECT_TRUE(ary.get_key_id(it->first, &id)); ASSERT_TRUE(ary.get_val_for_key(it->first, &val)); EXPECT_EQ(it->second, val); } } TEST_P(HashArray, LargeValue) { mer_dna mer; mer.randomize(); ary.add(mer, numeric_limits::max()); uint64_t val = 0; ASSERT_TRUE(ary.get_val_for_key(mer, &val)); ASSERT_EQ(numeric_limits::max(), val); } INSTANTIATE_TEST_CASE_P(HashArrayTest, HashArray, ::testing::Combine(::testing::Range(8, 4 * 64, 2), // Key lengths ::testing::Range(1, 10), // Val lengths ::testing::Range(6, 8) // Reprobe lengths )); TEST(Hash, Set) { static const int lsize = 16; static const int size = 1 << lsize; static const int nb_elts = 2 * size / 3; large_array ary(size, 100, 0, 126); mer_set set; mer_dna::k(50); mer_dna mer; for(int i = 0; i < nb_elts; ++i) { mer.randomize(); bool is_new; size_t id; ASSERT_TRUE(ary.set(mer, &is_new, &id)); ASSERT_EQ(set.insert(mer).second, is_new); } mer_dna tmp_mer; for(mer_set::const_iterator it = set.begin(); it != set.end(); ++it) { SCOPED_TRACE(::testing::Message() << "key:" << *it); size_t id; EXPECT_TRUE(ary.get_key_id(*it, &id, tmp_mer)); } for(int i = 0; i < nb_elts; ++i) { mer.randomize(); size_t id; EXPECT_EQ(set.find(mer) != set.end(), ary.get_key_id(mer, &id)); } } TEST(Hash, Update) { static const int lsize = 16; static const int size = 1 << lsize; static const int nb_elts = 2 * size / 3; large_array ary(size, 100, 4, 126); mer_map in_ary; mer_dna::k(50); mer_dna mer; for(int i = 0; i < nb_elts; ++i) { mer.randomize(); bool is_new; size_t id; ASSERT_TRUE(ary.set(mer, &is_new, &id)); auto res = in_ary.insert(std::make_pair(mer, (uint64_t)0)); ASSERT_EQ(res.second, is_new); } for(auto it = in_ary.begin(); it != in_ary.end(); ++it) { uint64_t val = random_bits(4); EXPECT_TRUE(ary.update_add(it->first, val)); it->second = val; } for(int i = 0; i < nb_elts; ++i) { mer.randomize(); uint64_t val = random_bits(4); auto it = in_ary.find(mer); if(it == in_ary.end()) { EXPECT_FALSE(ary.update_add(mer, val)); } else { it->second += val; EXPECT_TRUE(ary.update_add(mer, val)); } } lazy_iterator it = ary.iterator_all(); size_t count = 0; while(it.next()) { ASSERT_NE(in_ary.end(), in_ary.find(it.key())); EXPECT_EQ(in_ary[it.key()], it.val()); ++count; } EXPECT_EQ(in_ary.size(), count); } TEST(Hash, Info) { for(int iteration = 0; iteration < 100; ++iteration) { size_t mem = random_bits(48); uint16_t key_len = random_bits(7) + 1; uint16_t val_len = random_bits(4) + 1; large_array::usage_info info(key_len, val_len, 126); SCOPED_TRACE(::testing::Message() << "iteration:" << iteration << " mem:" << mem << " key_len:" << key_len << " val_len:" << val_len); uint16_t size_bits = info.size_bits(mem); uint16_t size2_bits = info.size_bits_linear(mem); ASSERT_EQ(size2_bits, size_bits); ASSERT_LE(info.mem((size_t)1 << size_bits), mem); ASSERT_GT(info.mem((size_t)1 << (size_bits + 1)), mem); } } } Jellyfish-2.2.8/unit_tests/test_main.cc000066400000000000000000000035511323712541700201600ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include template struct floorLog2 { static const int val = floorLog2::val + 1; }; template<> struct floorLog2<1> { static const int val = 0; }; // Return length random bits. 1 <= length <= 64 uint64_t random_bits(int length) { uint64_t res = 0; for(int i = 0; i < length; i += floorLog2::val) res ^= (uint64_t)random() << i; return res & ((uint64_t)-1 >> (64 - length)); } int main(int argc, char *argv[]) { ::testing::InitGoogleTest(&argc, argv); cmdline_parse args(argc, argv); unsigned int seed; if(args.seed_given) { seed = args.seed_arg; } else { std::ifstream urandom("/dev/urandom"); urandom.read((char*)&seed, sizeof(seed)); if(!urandom.good()) { std::cerr << "Failed to read random seed" << std::endl; return 1; } } if(args.backtrace_flag) { show_backtrace(); setenv("GTEST_CATCH_EXCEPTIONS", "0", 1); } std::cout << "Using random seed " << seed << std::endl; srandom(seed); return RUN_ALL_TESTS(); } Jellyfish-2.2.8/unit_tests/test_main.hpp000066400000000000000000000010601323712541700203530ustar00rootroot00000000000000#ifndef __TEST_MAIN_HPP__ #define __TEST_MAIN_HPP__ #include #include #include #include uint64_t random_bits(int length); inline uint64_t random_bits() { return random_bits(64); } struct file_unlink { std::string path; bool do_unlink; explicit file_unlink(const char* s, bool d = true) : path(s), do_unlink(d) { } explicit file_unlink(const std::string& s, bool d = true) : path(s), do_unlink(d) { } ~file_unlink() { if(do_unlink) unlink(path.c_str()); } }; #endif /* __TEST_MAIN_HPP__ */ Jellyfish-2.2.8/unit_tests/test_main_cmdline.yaggo000066400000000000000000000003041323712541700223650ustar00rootroot00000000000000purpose "Unit tests" name "cmdline_parse" option("s", "seed") { description "Random seed" uint32 } option("b", "backtrace") { description "Do not catch errors and show backtrace" flag } Jellyfish-2.2.8/unit_tests/test_mapped_file.cc000066400000000000000000000031261323712541700214770ustar00rootroot00000000000000#include #include #include #include #include namespace { using jellyfish::mapped_file; TEST(MappedFile, CreateMove) { const char* mpt = "mapped_file_test"; file_unlink file(mpt); std::string text = "Hello\nThis is a test\n"; { std::ofstream fd(mpt); fd << text; } mapped_file mf(mpt); EXPECT_STREQ(mpt, mf.path().c_str()); ASSERT_NE((char*)0, mf.base()); ASSERT_EQ(text.size(), mf.length()); EXPECT_EQ(text, std::string(mf.base(), mf.length())); mapped_file mf2 = std::move(mf); EXPECT_STREQ(mpt, mf2.path().c_str()); ASSERT_NE((char*)0, mf2.base()); ASSERT_EQ(text.size(), mf2.length()); EXPECT_EQ(text, std::string(mf2.base(), mf2.length())); ASSERT_EQ((char*)0, mf.base()); mapped_file mf3(mpt); mf2 = std::move(mf3); EXPECT_STREQ(mpt, mf2.path().c_str()); ASSERT_NE((char*)0, mf2.base()); ASSERT_EQ(text.size(), mf2.length()); EXPECT_EQ(text, std::string(mf2.base(), mf2.length())); ASSERT_EQ((char*)0, mf.base()); } // Gtest and newer compilers seem to have a problem with EXPECT_THROW #if !defined(__clang__) && (!defined(GTEST_GCC_VER_) || GTEST_GCC_VER_ < 40800) TEST(MappedFile, Fail) { const char* bad_file = "/doesntexistsforsure/thatwouldbecrazy!"; EXPECT_THROW(mapped_file mf(bad_file), jellyfish::mapped_file::ErrorMMap); mapped_file mf; EXPECT_THROW(mf.map(bad_file), jellyfish::mapped_file::ErrorMMap); EXPECT_EQ((char*)0, mf.base()); EXPECT_THROW(mf.map(-1), jellyfish::mapped_file::ErrorMMap); EXPECT_EQ((char*)0, mf.base()); } #endif } Jellyfish-2.2.8/unit_tests/test_mer_dna.cc000066400000000000000000000414241323712541700206420ustar00rootroot00000000000000/* SuperRead pipeline * Copyright (C) 2012 Genome group at University of Maryland. * * 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 . */ #include #include #include #include #include #include #include namespace { using namespace jellyfish; const std::string short_mer("ACGTTGGCCAA"); const std::string mid_mer("AAGACTTAGAATCAGCTAAGGTAACTTACGTAGAATATAGA"); const std::string long_mer("AAGACTTAGAATCAGCTAAGGTAACTTACGTAGAATATAG" "AAGACGGCGCCTATCCCAACCTCCATTTGCTGACGCCCTC" "GTAACCGTGCTGCGAGGTTACTCTATACTGA"); const std::string huge_mer("CAGGACACAATACGTCGATCCAATCCCCGACGTGAGAGTT" "TAACGCTAATCTTGATCCATTACAAGTATAGATATTTCGG" "GCGCCACGGGGAAACTTGCCCTATGTTCGAGTCCGCCACC" "GCGGCACCAGCCTTTGTGTGACGGCCACAAAGGGTAAAAG" "ATGTTGTCTCGCGCCGGCGTGCGGTCTTTACCAGATCCTT" "GAGCGGCCTAGAAAGTTCGTACCAGTTCGACTGAAACAAG" "ACAACGGATCGCCCACGGTCATCACACGCCCACGCACGGG" "GTCGGGTTGGTATATTCAACCTCGAGTTAAACGT"); const std::string* test_mers[4] = { &short_mer, &mid_mer, &long_mer, &huge_mer }; TEST(MerDNASimple, InitSize64) { struct sinfo { unsigned int k; unsigned int nb_words; unsigned int nb_msb; uint64_t msw; unsigned int lshift; }; sinfo ary[5] = { { 5, 1, 10, (uint64_t)0x3ff, 8 }, { 32, 1, 64, (uint64_t)-1, 62 }, { 33, 2, 2, (uint64_t)0x3, 0 }, { 64, 2, 64, (uint64_t)-1, 62 }, { 65, 3, 2, (uint64_t)0x3, 0 } }; typedef mer_dna_ns::mer_base_dynamic mer64; for(size_t i = 0; i < sizeof(ary) / sizeof(sinfo); ++i) { mer64 m(ary[i].k); EXPECT_EQ(ary[i].k, m.k()); EXPECT_EQ(ary[i].nb_words, m.nb_words()); EXPECT_EQ(ary[i].nb_msb, m.nb_msb()); EXPECT_EQ(ary[i].lshift, m.lshift()); } } #ifdef HAVE_INT128 TEST(MerDNASimple, InitSize128) { struct sinfo { unsigned int k; unsigned int nb_words; unsigned int nb_msb; unsigned __int128 msw; unsigned int lshift; }; sinfo ary[5] = { { 5, 1, 10, (unsigned __int128)0x3ff, 8 }, { 32, 1, 64, (unsigned __int128)0xffffffffffffffffUL, 62 }, { 33, 1, 66, (unsigned __int128)0xffffffffffffffffUL | ((unsigned __int128)0x3 << 64), 64 }, { 64, 1, 128, (unsigned __int128)-1, 126 }, { 65, 2, 2, (unsigned __int128)0x3, 0 } }; typedef mer_dna_ns::mer_base_dynamic mer128; for(size_t i = 0; i < sizeof(ary) / sizeof(sinfo); ++i) { mer128 m(ary[i].k); EXPECT_EQ(ary[i].k, m.k()); EXPECT_EQ(ary[i].nb_words, m.nb_words()); EXPECT_EQ(ary[i].nb_msb, m.nb_msb()); EXPECT_EQ(ary[i].lshift, m.lshift()); } } #endif TEST(MerDNASimple, Codes) { EXPECT_EQ(mer_dna::CODE_A, mer_dna::code('A')); EXPECT_EQ(mer_dna::CODE_A, mer_dna::code('a')); EXPECT_EQ(mer_dna::CODE_C, mer_dna::code('C')); EXPECT_EQ(mer_dna::CODE_C, mer_dna::code('c')); EXPECT_EQ(mer_dna::CODE_G, mer_dna::code('G')); EXPECT_EQ(mer_dna::CODE_G, mer_dna::code('g')); EXPECT_EQ(mer_dna::CODE_T, mer_dna::code('T')); EXPECT_EQ(mer_dna::CODE_T, mer_dna::code('t')); EXPECT_FALSE(mer_dna::not_dna(mer_dna::CODE_A)); EXPECT_FALSE(mer_dna::not_dna(mer_dna::CODE_C)); EXPECT_FALSE(mer_dna::not_dna(mer_dna::CODE_G)); EXPECT_FALSE(mer_dna::not_dna(mer_dna::CODE_T)); for(int c = 0; c < 256; ++c) { switch((char)c) { case 'A': case 'a': case 'C': case 'c': case 'G': case 'g': case 'T': case 't': EXPECT_FALSE(mer_dna::not_dna(mer_dna::code(c))); break; default: EXPECT_TRUE(mer_dna::not_dna(mer_dna::code(c))); break; } } } TEST(MerDNASimple, SetBits) { mer_dna::k(100); static const int pattern_len = 10; uint64_t pattern = ::random_bits(pattern_len); // Create a random pattern mer_dna even_pattern, odd_pattern; // And the corresponding mers for(int i = pattern_len - 2; i >= 0; i -= 2) { even_pattern.shift_left((int)((pattern >> i) & 0x3)); odd_pattern.shift_left((int)((pattern >> (i + 1)) & 0x3)); } odd_pattern.shift_left((int)((pattern << 1) & 0x3)); mer_dna mer; for(int i = 0; i <= (int)(mer_dna::k() - pattern_len / 2); ++i, even_pattern.shift_left('A'), odd_pattern.shift_left('A')) { // Even mer.polyA(); EXPECT_EQ(std::string(mer_dna::k(), 'A'), mer.to_str()); mer.set_bits(2 * i, pattern_len, pattern); EXPECT_EQ(pattern, mer.get_bits(2 * i, pattern_len)); EXPECT_EQ(even_pattern, mer); EXPECT_EQ(even_pattern.to_str(), mer.to_str()); // Odd mer.polyA(); mer.set_bits(2 * i + 1, pattern_len, pattern); if(i < (int)(mer_dna::k() - pattern_len / 2)) EXPECT_EQ(pattern, mer.get_bits(2 * i + 1, pattern_len)); else // On the largest value of i, one bit may have fallen off the end of the mer EXPECT_EQ(pattern & (((uint64_t)1 << (pattern_len - 1)) - 1), mer.get_bits(2 * i + 1, pattern_len)); EXPECT_EQ(odd_pattern, mer); EXPECT_EQ(odd_pattern.to_str(), mer.to_str()); } } TEST(MerDNASimple, Shifts) { for(int i = 1; i < 100; ++i) { mer_dna::k(i); mer_dna m; m.randomize(); const int c = ::random_bits(2); mer_dna rm(m); rm.shift_right(c); mer_dna lm(m); lm.shift_left(c); EXPECT_EQ(c, rm.base(mer_dna::k() - 1).code()); EXPECT_EQ(c, lm.base(0).code()); for(unsigned int j = 0; j < mer_dna::k() - 1; ++j) { EXPECT_EQ(m.base(j + 1).code(), rm.base(j).code()); EXPECT_EQ(m.base(j).code(), lm.base(j + 1).code()); } } } // MerDNASimple.Shifts bool simple_homolymer_test(const mer_dna& m) { mer_dna cm(m); cm.shift_right(m.base(0).code()); return cm == m; } TEST(MerDNASimple, Homopolymer) { for(int i = 1; i < 256; ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i); mer_dna::k(i); mer_dna m; for(int j = 0; j < 10; ++j) { m.randomize(); EXPECT_EQ(simple_homolymer_test(m), m.is_homopolymer()); } m.polyA(); EXPECT_TRUE(simple_homolymer_test(m)); EXPECT_TRUE(m.is_homopolymer()); if(i > 1) { // i == 1 all mers are homopolymers by definition m.base(::random_bits(5) % i) = 'T'; if(simple_homolymer_test(m) || m.is_homopolymer()) std::cerr << m << "\n"; EXPECT_FALSE(simple_homolymer_test(m)); EXPECT_FALSE(m.is_homopolymer()); } m.polyC(); EXPECT_TRUE(simple_homolymer_test(m)); EXPECT_TRUE(m.is_homopolymer()); m.polyG(); EXPECT_TRUE(simple_homolymer_test(m)); EXPECT_TRUE(m.is_homopolymer()); m.polyT(); EXPECT_TRUE(simple_homolymer_test(m)); EXPECT_TRUE(m.is_homopolymer()); } } // MerDNASimple.Homopolymer TEST(MerDNASimple, Comparators) { mer_dna::k(151); mer_dna ma, mc, mg, mt; ma.polyA(); mc.polyC(); mg.polyG(); mt.polyT(); mer_dna cma(ma), cmc(mc), cmg(mg), cmt(mt); ASSERT_TRUE(ma < mc); ASSERT_FALSE(mc < ma); ASSERT_TRUE(ma < mg); ASSERT_FALSE(mg < ma); ASSERT_TRUE(ma < mt); ASSERT_FALSE(mt < ma); ASSERT_TRUE(mc < mg); ASSERT_FALSE(mg < mc); ASSERT_TRUE(mc < mt); ASSERT_FALSE(mt < mc); ASSERT_TRUE(mg < mt); ASSERT_FALSE(mt < mg); ASSERT_FALSE(ma < ma); ASSERT_FALSE(mc < mc); ASSERT_FALSE(mg < mg); ASSERT_FALSE(mt < mt); std::map map; EXPECT_EQ(1, ++map[ma]); EXPECT_EQ(1, ++map[mc]); EXPECT_EQ(1, ++map[mg]); EXPECT_EQ(1, ++map[mt]); EXPECT_EQ(2, ++map[cma]); EXPECT_EQ(2, ++map[cmc]); EXPECT_EQ(2, ++map[cmg]); EXPECT_EQ(2, ++map[cmt]); mer_dna m1, m2; for(int i = 0; i < 1000; ++i) { m1.randomize(); m2.randomize(); SCOPED_TRACE(::testing::Message() << "m1:" << m1 << " m2:" << m2); ASSERT_FALSE(m1 == m2); // Very small probability to fail (k == 151) EXPECT_TRUE(m1 == m1); EXPECT_FALSE(m1 < m1); EXPECT_FALSE(m1 > m1); EXPECT_TRUE(m1 <= m1); EXPECT_TRUE(m1 >= m1); EXPECT_TRUE(m2 == m2); EXPECT_FALSE(m2 < m2); EXPECT_FALSE(m2 > m2); EXPECT_TRUE(m2 <= m2); EXPECT_TRUE(m2 >= m2); EXPECT_EQ(m1.to_str().compare(m2.to_str()) < 0, m1 < m2); // Comparison is lexicographic EXPECT_TRUE(m1 < m2 || m2 < m1); EXPECT_TRUE(m1 <= m2 || m2 <= m1); EXPECT_FALSE(m1 <= m2 && m2 <= m1); EXPECT_TRUE(m1 > m2 || m2 > m1); EXPECT_TRUE(m1 >= m2 || m2 >= m1); EXPECT_FALSE(m1 >= m2 && m2 >= m1); EXPECT_NE(m1 < m2, m1 >= m2); EXPECT_NE(m1 < m2, m1 > m2); } } TEST(MerDNASimple, IO) { std::stringstream buffer; for(int i = 0; i < 10000; ++i) { buffer.clear(); SCOPED_TRACE(::testing::Message() << "i:" << i); mer_dna::k(::random_bits(9) + 1); mer_dna m1, m2; m1.randomize(); buffer << m1; buffer >> m2; EXPECT_EQ(m1, m2); } } TEST(MerDNASimple, MultipleSize) { typedef jellyfish::mer_dna_ns::mer_base_static mer_dna1; typedef jellyfish::mer_dna_ns::mer_base_static mer_dna2; mer_dna::k(10); mer_dna1::k(50); mer_dna2::k(100); EXPECT_EQ(10, mer_dna::k()); EXPECT_EQ(0, mer_dna::class_index); EXPECT_EQ(50, mer_dna1::k()); EXPECT_EQ(1, mer_dna1::class_index); EXPECT_EQ(100, mer_dna2::k()); EXPECT_EQ(2, mer_dna2::class_index); } // Value Type Container class template class VTC { public: typedef T Type; static const int test_id = N; }; template const int VTC::test_id; template class MerDNA : public ::testing::Test { public: typedef typename VT::Type Type; void SetUp() { Type::k(GetParam().size()); } const std::string& GetParam() const { return *test_mers[VT::test_id]; } }; typedef ::testing::Types, 0>, VTC, 1>, VTC, 2>, VTC, 3>, #ifdef HAVE_INT128 VTC, 0>, VTC, 1>, VTC, 2>, VTC, 3>, #endif VTC, 0>, VTC, 1>, VTC, 2>, VTC, 3>, #ifdef HAVE_INT128 VTC, 0>, VTC, 1>, VTC, 2>, VTC, 3>, #endif VTC, 3> > MerDNATypes; TYPED_TEST_CASE(MerDNA, MerDNATypes); TYPED_TEST(MerDNA, InitFromStr) { typename TypeParam::Type m(this->GetParam()); EXPECT_EQ(this->GetParam().size(), m.k()); EXPECT_EQ(this->GetParam(), m.to_str()); } TYPED_TEST(MerDNA, ShiftLeft) { typename TypeParam::Type m(this->GetParam().size()); m.polyA(); int inserted = 0; for(std::string::const_iterator it = this->GetParam().begin(); it != this->GetParam().end(); ++it, ++inserted) { m.shift_left(*it); int check = inserted; for(std::string::const_iterator cit = this->GetParam().begin(); check >= 0; ++cit, --check) EXPECT_EQ(*cit, (char)m.base(check)); } EXPECT_EQ(this->GetParam(), m.to_str()); } TYPED_TEST(MerDNA, ShiftRight) { typename TypeParam::Type m(this->GetParam().size()); m.polyA(); int inserted = 0; for(std::string::const_reverse_iterator it = this->GetParam().rbegin(); it != this->GetParam().rend(); ++it, ++inserted) { m.shift_right(*it); int check = inserted; for(std::string::const_reverse_iterator cit = this->GetParam().rbegin(); check >= 0; ++cit, --check) EXPECT_EQ(*cit, (char)m.base(m.k() - 1 - check)); } EXPECT_EQ(this->GetParam(), m.to_str()); } TYPED_TEST(MerDNA, Equality) { typename TypeParam::Type m1(this->GetParam()); typename TypeParam::Type m2(this->GetParam().size()); char str[this->GetParam().size() + 1]; str[this->GetParam().size()] = '\0'; memset(str, 'A', this->GetParam().size()); m2.polyA(); EXPECT_STREQ(str, m2.to_str().c_str()); memset(str, 'C', this->GetParam().size()); m2.polyC(); EXPECT_STREQ(str, m2.to_str().c_str()); memset(str, 'G', this->GetParam().size()); m2.polyG(); EXPECT_STREQ(str, m2.to_str().c_str()); memset(str, 'T', this->GetParam().size()); m2.polyT(); EXPECT_STREQ(str, m2.to_str().c_str()); int i = 1; for(std::string::const_iterator it = this->GetParam().begin(); it < this->GetParam().end(); ++it, ++i) { sprintf(str + this->GetParam().size() - i, "%.*s", i, this->GetParam().c_str()); typename TypeParam::Type m(str); EXPECT_STREQ(str, m.to_str().c_str()); m2.shift_left(*it); EXPECT_EQ(m, m2); } EXPECT_TRUE(m1 == m2); EXPECT_FALSE(m1 != m2); EXPECT_EQ(m1.to_str(), m2.to_str()); // typename TypeParam::Type m3(this->GetParam()); // m3[0] = 0; // EXPECT_FALSE(m1 == m3); // typename TypeParam::Type m4(this->GetParam().size() + 1); // EXPECT_FALSE(m1 == m4); // typename TypeParam::Type m5(this->GetParam().size() - 1); // EXPECT_FALSE(m1 == m5); } TYPED_TEST(MerDNA, Copy) { typename TypeParam::Type m1(this->GetParam()); typename TypeParam::Type m2(m1); typename TypeParam::Type m3(this->GetParam().size()); m3 = m1; EXPECT_TRUE(m1 == m2); EXPECT_TRUE(m2 == m3); EXPECT_TRUE(m3 == m1); m1.shift_left('A'); EXPECT_TRUE(!(m1 == m2)); EXPECT_TRUE(!(m1 == m3)); } TYPED_TEST(MerDNA, OperatorShift) { typename TypeParam::Type m(this->GetParam()); std::ostringstream os; os << m; EXPECT_EQ(this->GetParam(), os.str()); } TYPED_TEST(MerDNA, GetBits) { typename TypeParam::Type m(this->GetParam()); for(unsigned int i = 0; i < 20; ++i) { long int start = random() % (this->GetParam().size() - 1); long int max_len = std::min((long int)(this->GetParam().size() - start), (long int)(8 * sizeof(typename TypeParam::Type::base_type))); long int len = (random() % (max_len - 1)) + 1; // Get bits by right-shifting typename TypeParam::Type cm(m); for(unsigned int j = 1; j < start; j += 2) cm.shift_right(0); // Shift by 2 bits typename TypeParam::Type::base_type y = cm.word(0); if(start & 0x1) y >>= 1; y &= ((typename TypeParam::Type::base_type)1 << len) - 1; EXPECT_EQ(y, m.get_bits(start, len)); } } TYPED_TEST(MerDNA, GetBases) { typename TypeParam::Type m(this->GetParam()); for(std::string::const_reverse_iterator it = this->GetParam().rbegin(); it != this->GetParam().rend(); ++it) EXPECT_EQ(*it, (char)m.base(it - this->GetParam().rbegin())); const char bases[4] = { 'A', 'C', 'G', 'T' }; for(const char* it = bases; it != bases + 4; ++it) { typename TypeParam::Type n(m); for(size_t j = 0; j < this->GetParam().size(); ++j) n.base(j) = *it; typename TypeParam::Type m_expected(std::string(this->GetParam().size(), *it)); EXPECT_EQ(m_expected, n); } } char rc_base(char c) { switch(c) { case 'A': case 'a': return 'T'; case 'C': case 'c': return 'G'; case 'G': case 'g': return 'C'; case 'T': case 't': return 'A'; } return 'A'; // Should never be reached } TYPED_TEST(MerDNA, ReverseComplement) { typename TypeParam::Type m(this->GetParam()); std::string rc(this->GetParam().size(), 'A'); for(size_t i = 0; i < rc.size(); ++i) rc[i] = rc_base(this->GetParam()[this->GetParam().size() - 1 - i]); EXPECT_EQ(this->GetParam().size(), m.k()); m.reverse_complement(); EXPECT_EQ(rc, m.to_str()); typename TypeParam::Type rm(rc); EXPECT_EQ(rm, m); EXPECT_EQ(m, m.get_reverse_complement().get_reverse_complement()); } TYPED_TEST(MerDNA, Canonical) { typename TypeParam::Type m(this->GetParam()); typename TypeParam::Type canonical = m.get_canonical(); EXPECT_FALSE(m < canonical); EXPECT_TRUE(canonical <= m); EXPECT_TRUE(canonical == m || canonical == m.get_reverse_complement()); m.canonicalize(); EXPECT_EQ(canonical, m.get_canonical()); } } // namespace { Jellyfish-2.2.8/unit_tests/test_mer_dna_bloom_counter.cc000066400000000000000000000122341323712541700235660ustar00rootroot00000000000000/* This file is part of Jellyfish. Jellyfish 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. Jellyfish 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 Jellyfish. If not, see . */ #include #include #include #include #include #include #include #include #include namespace { using jellyfish::mer_dna; static const size_t nb_inserts = 10000; static const double error_rate = 0.001; template class MerDnaBloomTest : public ::testing::Test { }; struct TestBloomCounter { typedef jellyfish::mer_dna_bloom_counter bloom_type; typedef jellyfish::mer_dna_bloom_counter_file file_type; static const unsigned int threshold_twice = 2; // Bloom counter counts up to 2. }; struct TestBloomFilter { typedef jellyfish::mer_dna_bloom_filter bloom_type; typedef jellyfish::mer_dna_bloom_filter_file file_type; static const unsigned int threshold_twice = 1; // Bloom filter counts up to 1. }; typedef ::testing::Types TestBloomCounterTypes; TYPED_TEST_CASE(MerDnaBloomTest, TestBloomCounterTypes); TYPED_TEST(MerDnaBloomTest, FalsePositive) { mer_dna::k(50); std::set mer_set; typename TypeParam::bloom_type bc(error_rate, nb_inserts); size_t collisions2 = 0; size_t collisions3 = 0; // Insert once nb_inserts. Insert twice the first half { // First insertion size_t nb_collisions = 0; mer_dna m; for(size_t i = 0; i < nb_inserts; ++i) { m.randomize(); mer_set.insert(m); nb_collisions += bc.insert(m) > 0; } // EXPECT_GT(error_rate * nb_inserts, nb_collisions); if(error_rate * nb_inserts < nb_collisions) std::cerr << "First insertion high error rate: " << nb_collisions << " > " << (error_rate * nb_inserts) << '\n'; } // Second insertion { size_t nb_collisions = 0; size_t nb_errors = 0; auto it = mer_set.cbegin(); for(size_t i =0; i < nb_inserts / 2; ++i, ++it) { unsigned int oc = bc.insert(*it); nb_collisions += oc > 1; nb_errors += oc < 1; } EXPECT_EQ((size_t)0, nb_errors); // EXPECT_GT(2 * error_rate * nb_inserts, nb_collisions); if(2 * error_rate * nb_inserts < nb_collisions) std::cerr << "Second insertion high error rate: " << nb_collisions << " > " << (2 * error_rate * nb_inserts) << '\n'; } // Write to file and reload two different ways file_unlink f("bloom_file"); { std::ofstream out(f.path.c_str()); bc.write_bits(out); EXPECT_TRUE(out.good()); EXPECT_EQ(bc.nb_bytes(), out.tellp()); } std::ifstream in(f.path.c_str()); typename TypeParam::bloom_type bc_read(bc.m(), bc.k(), in, bc.hash_functions()); EXPECT_EQ(bc.nb_bytes(), in.tellg()); in.close(); typename TypeParam::file_type bc_map(bc.m(), bc.k(), f.path.c_str(), bc.hash_functions()); EXPECT_EQ(bc.m(), bc_read.m()); EXPECT_EQ(bc.k(), bc_read.k()); EXPECT_EQ(bc.m(), bc_map.m()); EXPECT_EQ(bc.k(), bc_map.k()); // Check known mers { size_t nb_collisions = 0; size_t nb_errors = 0; auto it = mer_set.cbegin(); for(size_t i = 0; i < nb_inserts; ++i, ++it) { unsigned int check = bc.check(*it); EXPECT_EQ(check, bc_read.check(*it)); EXPECT_EQ(check, bc_map.check(*it)); if(i < nb_inserts / 2) { nb_errors += check < TypeParam::threshold_twice; } else { nb_errors += check < 1; nb_collisions += check > 1; } } EXPECT_EQ((size_t)0, nb_errors); // EXPECT_GT(2 * error_rate * nb_inserts, nb_collisions); if(2 * error_rate * nb_inserts < nb_collisions) std::cerr << "Check known mers high error rate: " << nb_collisions << " > " << (2 * error_rate * nb_inserts) << '\n'; } // Check unknown mers { size_t nb_collisions = 0; mer_dna m; for(size_t i = 0; i < nb_inserts; ++i) { m.randomize(); unsigned int check = bc.check(m); EXPECT_EQ(check, bc_read.check(m)); EXPECT_EQ(check, bc_map.check(m)); nb_collisions += check > 0; } // EXPECT_GT(2 * error_rate * nb_inserts, nb_collisions); if(2 * error_rate * nb_inserts < nb_collisions) std::cerr << "Check unknown mers high error rate: " << nb_collisions << " > " << (2 * error_rate * nb_inserts) << '\n'; } } TYPED_TEST(MerDnaBloomTest, Move) { mer_dna::k(100); typename TypeParam::bloom_type bc(error_rate, nb_inserts); const unsigned long k = bc.k(); const size_t m = bc.m(); typename TypeParam::bloom_type bc2(std::move(bc)); EXPECT_EQ(k, bc2.k()); EXPECT_EQ(m, bc.m()); } } Jellyfish-2.2.8/unit_tests/test_mer_heap.cc000066400000000000000000000036111323712541700210110ustar00rootroot00000000000000#include #include #include #include namespace { using jellyfish::mer_dna; typedef jellyfish::large_hash::array large_array; typedef large_array::region_iterator region_iterator; typedef jellyfish::mer_heap::heap mer_heap; static const size_t ary_size = 10000; static const uint16_t mer_len = 50; static const size_t nb_mers = ary_size / 2; class MerHeapTest : public ::testing::TestWithParam { public: static void SetUpTestCase() { mer_dna::k(mer_len); shared_ary = new large_array(ary_size, mer_len * 2, 0, 63); mer_dna m; for(size_t i = 0; i < nb_mers; ++i) { m.randomize(); bool is_new; size_t id; shared_ary->set(m, &is_new, &id); EXPECT_TRUE(is_new); // Very small probability to fail } } static void TearDownTestCase() { delete shared_ary; } static large_array* shared_ary; }; large_array* MerHeapTest::shared_ary = 0; TEST_P(MerHeapTest, Order) { uint64_t hash = 0; int count = 0; const large_array& ary = *shared_ary; mer_dna m; m.polyA(); for(size_t slice = 0; slice < GetParam(); ++slice) { region_iterator rit = ary.iterator_slice(slice, GetParam()); mer_heap heap(ary.max_reprobe_offset()); heap.fill(rit); while(!heap.is_empty()) { uint64_t nhash = ary.matrix().times(heap.head()->key_); EXPECT_LE(hash, nhash); if(nhash == hash) EXPECT_LT(m, heap.head()->key_); hash = nhash; m = heap.head()->key_; heap.pop(); ++count; if(rit.next()) heap.push(rit); } } EXPECT_EQ(nb_mers, count); } INSTANTIATE_TEST_CASE_P(MerHeap, MerHeapTest, ::testing::Range((size_t)1, (size_t)11)); } // namespace { Jellyfish-2.2.8/unit_tests/test_mer_iterator.cc000066400000000000000000000135311323712541700217270ustar00rootroot00000000000000#include #include #include #include #include #include #include #include namespace { using std::string; using jellyfish::mer_dna; typedef std::vector string_vector; template struct opened_streams { Iterator begin_, end_; opened_streams(Iterator begin, Iterator end) : begin_(begin), end_(end) { } jellyfish::stream_type next() { jellyfish::stream_type res; if(begin_ != end_) { res.standard.reset(*begin_); ++begin_; } return res; } }; typedef jellyfish::mer_overlap_sequence_parser > parser_type; typedef jellyfish::mer_iterator mer_iterator_type; typedef jellyfish::whole_sequence_parser > parser_qual_type; typedef jellyfish::mer_qual_iterator mer_qual_iterator_type; static string generate_sequence(int len) { static const char bases[4] = { 'A', 'C', 'G', 'T' }; string res; res.reserve(len); for(int i = 0; i < len; ++i) res += bases[random() & 0x3]; return res; } static string generate_quals(int len) { string res; res.reserve(len); for(int i = 0; i < len; ++i) res += static_cast('!' + (random() % 94)); return res; } TEST(MerIterator, Sequence) { static const int nb_sequences = 100; const char* file_name = "Sequence.fa"; file_unlink fu(file_name); string_vector sequences; mer_dna::k(35); { std::ofstream input_fasta(file_name); for(int i = 0; i < nb_sequences; ++i) { sequences.push_back(generate_sequence(20 + random() % 200)); input_fasta << ">" << i << "\n" << sequences.back() << "\n"; } } // Check that every mer of the iterator matches the sequence auto input_fasta = new std::ifstream(file_name); { opened_streams streams(&input_fasta, &input_fasta + 1); parser_type parser(mer_dna::k(), 1, 10, 100, streams); mer_iterator_type mit(parser); for(string_vector::const_iterator it = sequences.begin(); it != sequences.end(); ++it) { if(it->size() >= mer_dna::k()) { for(int i = 0; i < it->size() - (mer_dna::k() - 1); ++i, ++mit) { ASSERT_NE(mer_iterator_type(), mit); EXPECT_EQ(it->substr(i, mer_dna::k()), mit->to_str()); } } } EXPECT_EQ(mer_iterator_type(), mit); } } // Same but with canonical mers TEST(MerIterator, SequenceCanonical) { const char* file_name = "SequenceCanonical.fa"; file_unlink fu(file_name); string_vector sequences; static const int nb_sequences = 100; mer_dna::k(35); { std::ofstream input_fasta(file_name); for(int i = 0; i < nb_sequences; ++i) { sequences.push_back(generate_sequence(20 + random() % 200)); input_fasta << ">" << i << "\n" << sequences.back() << "\n"; } } auto input_fasta = new std::ifstream(file_name); { opened_streams streams(&input_fasta, &input_fasta + 1); parser_type parser(mer_dna::k(), 1, 10, 100, streams); mer_iterator_type mit(parser, true); for(string_vector::const_iterator it = sequences.begin(); it != sequences.end(); ++it) { if(it->size() >= mer_dna::k()) { for(int i = 0; i < it->size() - (mer_dna::k() - 1); ++i, ++mit) { ASSERT_NE(mer_iterator_type(), mit); ASSERT_EQ(*mit, mit->get_canonical()); EXPECT_TRUE((it->substr(i, mer_dna::k()) == mit->to_str()) || (it->substr(i, mer_dna::k()) == mit->get_reverse_complement().to_str())); } } } EXPECT_EQ(mer_iterator_type(), mit); } } TEST(MerQualIterator, Sequence) { const char* file_name = "Sequence.fq"; file_unlink fu(file_name); string_vector sequences; string_vector quals; static const int nb_sequences = 100; mer_dna::k(35); for(int i = 0; i < nb_sequences; ++i) { const int len = 20 + (random() % 200); sequences.push_back(generate_sequence(len)); quals.push_back(generate_quals(len)); } { std::ofstream input_fasta(file_name); for(size_t i = 0; i < sequences.size(); ++i) input_fasta << "@" << i << "\n" << sequences[i] << "\n" << "+\n" << quals[i] << "\n"; } auto input1_fastq = new std::ifstream(file_name); auto input2_fastq = new std::ifstream(file_name); { opened_streams streams1(&input1_fastq, &input1_fastq + 1); parser_qual_type parser1(10, 10, 1, streams1); mer_qual_iterator_type mit(parser1, '#', false); opened_streams streams2(&input2_fastq, &input2_fastq + 1); parser_qual_type parser2(10, 10, 1, streams2); mer_qual_iterator_type mit_canonical(parser2, '#', true); for(string_vector::const_iterator it = sequences.begin(), qit = quals.begin(); it != sequences.end(); ++it, ++qit) { if(it->size() >= mer_dna::k()) { for(int i = 0; i < it->size() - (mer_dna::k() - 1); ++i) { const size_t next_N = qit->find_first_of("!\"", i); SCOPED_TRACE(::testing::Message() << "i:" << i << " next_N:" << next_N); if(next_N != std::string::npos && next_N >= i && next_N < i + mer_dna::k()) continue; ASSERT_NE(mer_iterator_type(), mit); EXPECT_EQ(it->substr(i, mer_dna::k()), mit->to_str()); ASSERT_NE(mer_iterator_type(), mit_canonical); ASSERT_EQ(*mit_canonical, mit_canonical->get_canonical()); EXPECT_TRUE((it->substr(i, mer_dna::k()) == mit_canonical->to_str()) || (it->substr(i, mer_dna::k()) == mit_canonical->get_reverse_complement().to_str())); ++mit; ++mit_canonical; } } } EXPECT_EQ(mer_iterator_type(), mit); } } } // namespace { Jellyfish-2.2.8/unit_tests/test_mer_overlap_sequence_parser.cc000066400000000000000000000132721323712541700250140ustar00rootroot00000000000000#include #include #include #include #include #include namespace { using std::string; using std::istringstream; template struct opened_streams { Iterator begin_, end_; opened_streams(Iterator begin, Iterator end) : begin_(begin), end_(end) { } jellyfish::stream_type next() { jellyfish::stream_type res; if(begin_ != end_) { res.standard.reset(*begin_); ++begin_; } return res; } }; typedef jellyfish::mer_overlap_sequence_parser > parser_type; TEST(MerOverlapSequenceParser, OneSmallSequence) { static const char* seq = "ATTACCTTGTACCTTCAGAGC"; const char* file_name = "OneSmallSequence.fa"; file_unlink fu(file_name); { std::ofstream sequence(file_name); sequence << ">header\n" << seq; } auto sequence = new std::ifstream(file_name); opened_streams streams(&sequence, &sequence + 1); parser_type parser(10, 1, 10, 100, streams); parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); EXPECT_EQ(strlen(seq), j->end - j->start); EXPECT_STREQ(seq, j->start); j.release(); parser_type::job j2(parser); EXPECT_TRUE(j2.is_empty()); EXPECT_EQ((size_t)1, parser.nb_files()); EXPECT_EQ((size_t)1, parser.nb_reads()); } string generate_sequences(std::ostream& os, int a, int b, int nb, bool fastq = false) { static const char bases[4] = {'A', 'C', 'G', 'T' }; string res; for(int i = 0; i < nb; ++i) { int len = a + random() % b; os << (fastq ? "@" : ">") << "r" << i << " " << len << "\n"; for(int j = 0; j < len; ++j) { char b = bases[random() & 0x3]; os << b; res += b; if(random() % 16 == 0) os << "\n"; } if(i != nb - 1) res += 'N'; os << "\n"; if(fastq) { os << "+\n"; for(int j = 0; j < len; ++j) { if(random() % 16 == 0) os << "\n"; os << "#"; } os << "\n"; } } return res; } TEST(MerOverlapSequenceParser, ManySmallSequences) { const char* file_name = "ManySmallSequences.fa"; file_unlink fu(file_name); static const int nb_reads = 20; static const int mer_len = 10; std::ofstream o_sequence(file_name); string res = generate_sequences(o_sequence, 20, 64, nb_reads); o_sequence.close(); auto sequence = new std::ifstream(file_name); opened_streams streams(&sequence, &sequence + 1); parser_type parser(mer_len, 1, 10, 100, streams); size_t offset = 0; while(true) { parser_type::job j(parser); if(j.is_empty()) break; SCOPED_TRACE(::testing::Message() << offset << ": " << res.substr(offset, j->end - j->start)); EXPECT_EQ(res.substr(offset, j->end - j->start).c_str(), string(j->start, j->end - j->start)); offset += j->end - j->start - (mer_len - 1); } EXPECT_EQ(res.size(), offset + mer_len - 1); EXPECT_EQ((size_t)1, parser.nb_files()); EXPECT_EQ((size_t)nb_reads, parser.nb_reads()); } TEST(MerOverlapSequenceParser, BigSequences) { const char* file_name1 = "BigSequences1.fa"; const char* file_name2 = "BigSequences2.fa"; file_unlink fu1(file_name1); file_unlink fu2(file_name2); std::ofstream o_sequence(file_name1); const string res0 = generate_sequences(o_sequence, 200, 100, 3); o_sequence.close(); o_sequence.open(file_name2); const string res1 = generate_sequences(o_sequence, 200, 100, 3); o_sequence.close(); std::ifstream* tmps[2]; tmps[0] = new std::ifstream(file_name1); tmps[1] = new std::ifstream(file_name2); opened_streams streams(tmps, tmps + 2); static const int mer_len = 10; parser_type parser(mer_len, 1, 10, 100, streams); size_t offset = 0; while(offset < res0.size() - mer_len + 1) { parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); SCOPED_TRACE(::testing::Message() << offset << ": " << res0.substr(offset, j->end - j->start)); EXPECT_EQ(res0.substr(offset, j->end - j->start).c_str(), string(j->start, j->end - j->start)); offset += j->end - j->start - (mer_len - 1); } EXPECT_EQ(res0.size(), offset + mer_len - 1); offset = 0; while(offset < res1.size() - mer_len + 1) { parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); SCOPED_TRACE(::testing::Message() << offset << ": " << res1.substr(offset, j->end - j->start)); EXPECT_EQ(res1.substr(offset, j->end - j->start).c_str(), string(j->start, j->end - j->start)); offset += j->end - j->start - (mer_len - 1); } EXPECT_EQ(res1.size(), offset + mer_len - 1); parser_type::job j2(parser); EXPECT_TRUE(j2.is_empty()); EXPECT_EQ((size_t)2, parser.nb_files()); EXPECT_EQ((size_t)6, parser.nb_reads()); } TEST(MerOverlapSequenceParser, Fastq) { const char* file_name = "Fastq.fa"; file_unlink fu(file_name); static const int nb_reads = 100; static const int mer_len = 20; std::ofstream o_sequence(file_name); string res = generate_sequences(o_sequence, 10, 50, nb_reads, true); o_sequence.close(); auto sequence = new std::ifstream(file_name); opened_streams streams(&sequence, &sequence + 1); parser_type parser(mer_len, 1, 10, 100, streams); size_t offset = 0; while(true) { parser_type::job j(parser); if(j.is_empty()) break; // SCOPED_TRACE(::testing::Message() << offset << ": " << res.substr(offset, j->end - j->start)); EXPECT_EQ(res.substr(offset, j->end - j->start).c_str(), string(j->start, j->end - j->start)); offset += j->end - j->start - (mer_len - 1); } EXPECT_EQ(res.size(), offset + mer_len - 1); EXPECT_EQ((size_t)1, parser.nb_files()); EXPECT_EQ((size_t)nb_reads, parser.nb_reads()); } } // namespace { Jellyfish-2.2.8/unit_tests/test_misc.cc000066400000000000000000000061141323712541700201650ustar00rootroot00000000000000#include #include #include #include #include #include namespace { using testing::Types; template class FloorLog2Test : public ::testing::Test { public: T x; FloorLog2Test() : x(1) {} }; typedef Types Implementations; TYPED_TEST_CASE(FloorLog2Test, Implementations); TYPED_TEST(FloorLog2Test, FloorLog2) { unsigned int i = 0; for(i = 0; i < 8 * sizeof(this->x); i++) { ASSERT_EQ(i, jellyfish::floorLog2(this->x << i)); ASSERT_EQ(i, jellyfish::floorLog2((this->x << i) | ((this->x << i) - 1))); } } using jellyfish::bitsize; TEST(BitSize, Small) { for(int i = 1; i < 4098; ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i); EXPECT_GE((1 << bitsize(i)) - 1, i); EXPECT_LE(1 << (bitsize(i) - 1), i); } } template int generic_popcount(T x) { static int counts[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; int res = 0; for( ; x; x >>= 4) res += counts[x & 0xf]; return res; } TEST(Random, Bits) { uint64_t m = 0; uint64_t m2 = 0; int not_zero = 0; int bits = 0; for(int i = 0; i < 1024; ++i) { m += jellyfish::random_bits(41); m2 += random_bits(41); not_zero += random_bits() > 0; bits += generic_popcount(m); } std::cout << bits << "\n"; EXPECT_LT((uint64_t)1 << 49, m); // Should be false with very low probability EXPECT_LT((uint64_t)1 << 49, m2); // Should be false with very low probability EXPECT_LT((int)(20.5 * 1024) / 2, bits); EXPECT_LT(512, not_zero); } TEST(BinarySearchFirst, Int) { static int size = 1024; for(int i = 0; i < size; ++i) EXPECT_EQ(i, *jellyfish::binary_search_first_false(jellyfish::pointer_integer(0), jellyfish::pointer_integer(size), std::bind2nd(std::less(), i))); } TEST(Slices, NonOverlapAll) { for(int iteration = 0; iteration < 100; ++iteration) { unsigned int nb_slices = random_bits(4) + 1; unsigned int size = std::max(nb_slices, (unsigned int)random_bits(20)); SCOPED_TRACE(::testing::Message() << "iteration:" << iteration << " size:" << size << " nb_slices:" << nb_slices); unsigned int total = 0; unsigned int prev = 0; for(unsigned int i = 0; i < nb_slices; ++i) { SCOPED_TRACE(::testing::Message() << "i:" << i); std::pair b = jellyfish::slice(i, nb_slices, size); ASSERT_EQ(prev, b.first); ASSERT_GT(b.second, b.first); total += b.second - b.first; prev = b.second; } ASSERT_EQ(size, total); } } TEST(QuoteArg, Nothing) { const std::string arg = "hello_world.1234_coucou/voila-bouh"; EXPECT_EQ(arg, jellyfish::quote_arg(arg)); } TEST(QuoteArg, Quote) { const std::string arg = "coucou voila"; EXPECT_EQ("'" + arg + "'", jellyfish::quote_arg(arg)); } TEST(QuoteArg, QuoteSlash) { const std::string arg = "coucou_'voila"; EXPECT_EQ("'coucou_'\\''voila'", jellyfish::quote_arg(arg)); } } Jellyfish-2.2.8/unit_tests/test_mutex.cc000066400000000000000000000021751323712541700203770ustar00rootroot00000000000000#include #include using testing::Types; #define NB_THREADS 3 #define COUNT 1000000 template class MutexTest : public ::testing::Test { int volatile count; mutex count_mutex; pthread_t threads[NB_THREADS]; pthread_attr_t attr; public: MutexTest() : count(0), count_mutex() { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for(int i = 0; i < NB_THREADS; i++) pthread_create(&threads[i], &attr, thread_fun, (void *)this); for(int i = 0; i < NB_THREADS; i++) pthread_join(threads[i], NULL); } static void *thread_fun(void *t) { MutexTest *self = (MutexTest *)t; self->inc(); return NULL; } void inc() { for(int i = 0; i < COUNT; i++) { count_mutex.lock(); count++; count_mutex.unlock(); } } int get_count() { return count; } }; typedef Types Implementations; TYPED_TEST_CASE(MutexTest, Implementations); TYPED_TEST(MutexTest, SuccessfullLocking) { EXPECT_EQ(NB_THREADS * COUNT, this->get_count()); } Jellyfish-2.2.8/unit_tests/test_offsets_key_value.cc000066400000000000000000000157331323712541700227560ustar00rootroot00000000000000#include #include #include #include #include #include #include #include namespace { #ifndef UINT64_C #define UINT64_C(x) ((uint64_t)x) #endif using namespace jellyfish; // Tuple is {key_len, val_len, reprobe_len}. Actual reprobe value is computed from the reprobe_len. class ComputeOffsetsTest : public ::testing::TestWithParam< ::std::tr1::tuple > { public: Offsets offsets; ComputeOffsetsTest() : offsets(::std::tr1::get<0>(GetParam()), ::std::tr1::get<1>(GetParam()), (1 << ::std::tr1::get<2>(GetParam())) - 2) { } ~ComputeOffsetsTest() { } }; void test_key_offsets(const Offsets::offset_t* it, unsigned int k_len, const char* message) { SCOPED_TRACE(message); unsigned int val_boff = (it->key.boff + k_len + 1 + (k_len - (bsizeof(uint64_t) - it->key.boff - 1)) / (bsizeof(uint64_t) - 1)) % bsizeof(uint64_t); if(it->key.sb_mask1) { // key between two words EXPECT_LT(sizeof(uint64_t), it->key.boff + k_len) << ": Key not between words, should not have mask2"; EXPECT_EQ(val_boff + (val_boff > 0), it->val.boff) << ": Invalid value offset"; if(it->val.boff == 0) EXPECT_EQ((uint64_t)0, it->key.sb_mask2); } else { if(bsizeof(uint64_t) >= it->key.boff + k_len) { EXPECT_EQ((it->key.boff + k_len) % bsizeof(uint64_t), it->val.boff) << ": Invalid value offset"; } else { EXPECT_TRUE(val_boff % bsizeof(uint64_t) == 0) << ": Key between words, should have mask2"; } } EXPECT_EQ((uint64_t)1 << (it->key.boff - 1), it->key.lb_mask) << ": Invalid lb_mask"; if(it->key.sb_mask1) { EXPECT_EQ(bsizeof(uint64_t) - it->key.boff - 1, it->key.shift) << ": invalid key shift"; EXPECT_EQ(it->key.boff == 1 ? 0 : (uint64_t)1 << (bsizeof(uint64_t) - it->key.boff + 1), 1 + (it->key.mask1 >> (it->key.boff - 1))) << ": invalid key mask"; EXPECT_EQ((uint64_t)1 << it->val.boff, 1 + it->key.mask2) << ": invalid key mask2"; EXPECT_EQ(bsizeof(uint64_t) - it->key.boff - 1, it->key.shift) << ": invalid key shift"; EXPECT_EQ((unsigned int)0, (k_len - (it->key.shift + it->key.cshift)) % (bsizeof(uint64_t) - 1)) << ": invalid sum of shift and cshift"; if(it->key.sb_mask2) EXPECT_EQ(1 + it->key.mask2, (uint64_t)1 << (it->key.cshift + 1)) << ": invalid key cshift"; else EXPECT_EQ((unsigned int)0, it->key.cshift); EXPECT_EQ((uint64_t)1 << 63, it->key.sb_mask1) << ": invalid key key sb_mask1"; EXPECT_EQ(k_len - (bsizeof(uint64_t) - 1 - it->key.boff) >= bsizeof(uint64_t) - 1, it->key.full_words); } else { EXPECT_EQ(0u, it->key.shift) << ": key shift should be zero, no sb_mask"; EXPECT_EQ((uint64_t)1 << (k_len + 1), 1 + (it->key.mask1 >> (it->key.boff - 1))) << ": invalid key mask, no sb_mask"; EXPECT_EQ(0u, it->key.cshift) << ": key cshift should be zero, no sb_mask"; EXPECT_EQ(0u, it->key.sb_mask1 | it->key.sb_mask2) << ": set bit masks should be 0"; } } void test_val_offsets(const Offsets::offset_t* it, unsigned int v_len, const char* message) { SCOPED_TRACE(message); if(it->val.mask2) { EXPECT_TRUE(bsizeof(uint64_t) <= it->val.boff + v_len && (it->val.boff + v_len) % bsizeof(uint64_t) != 0) << ": val not between words, should not have mask2"; EXPECT_EQ(bsizeof(uint64_t) - it->val.boff, it->val.shift) << ": invalid val shift"; EXPECT_EQ((uint64_t)1 << (bsizeof(uint64_t) - it->val.boff), 1 + (it->val.mask1 >> it->val.boff)) << ": invalid val mask1"; EXPECT_EQ((uint64_t)1 << (it->val.boff + v_len - bsizeof(uint64_t)), 1 + it->val.mask2) << ": invalid val mask2"; } else { EXPECT_TRUE(bsizeof(uint64_t) > it->val.boff + v_len || (bsizeof(uint64_t) <= it->val.boff + v_len && (it->val.boff + v_len) % bsizeof(uint64_t) == 0)) << ": val between words, should have mask2"; EXPECT_EQ(v_len, it->val.shift) << ": invalid val shift"; EXPECT_EQ(v_len == bsizeof(uint64_t) ? (uint64_t)0 : (uint64_t)1 << v_len, 1 + (it->val.mask1 >> it->val.boff)) << ": invalid val mask1"; } EXPECT_EQ(v_len, it->val.shift + it->val.cshift); } TEST_P(ComputeOffsetsTest, CheckCoherency) { const Offsets::offset_t *it = NULL, *pit = NULL; const Offsets::offset_t *lit = NULL, *lpit = NULL; unsigned int k_len = ::std::tr1::get<0>(GetParam()); unsigned int v_len = ::std::tr1::get<1>(GetParam()); unsigned int kv_len = k_len + v_len; unsigned int lk_len = ::std::tr1::get<2>(GetParam()); unsigned int lv_len = std::min(kv_len - lk_len, (unsigned int)bsizeof(uint64_t)); unsigned int i = 0; EXPECT_EQ(lk_len, this->offsets.reprobe_len()); EXPECT_EQ((uint64_t)1 << lk_len, this->offsets.reprobe_mask() + 1); EXPECT_EQ(lv_len, this->offsets.lval_len()); for(i = 0; i < bsizeof(uint64_t); i++) { SCOPED_TRACE(::testing::Message() << "key:" << k_len << " val:" << v_len << " i:" << i << " lkey:" << lk_len << " lval:" << lv_len); this->offsets.word_offset(i, &it, &lit, NULL); if(i > 0) { this->offsets.word_offset(i-1, &pit, &lpit, NULL); EXPECT_GE(it->key.woff, pit->key.woff) << "Current key offset larger than previous"; EXPECT_GE(it->key.woff, pit->val.woff) << "Current key offset larger than previous val offset"; EXPECT_TRUE(it->key.woff != pit->key.woff || it->key.boff > pit->key.boff) << "Key bit offset did not increase within a word"; EXPECT_EQ((pit->val.boff + v_len) % 64 + 1, it->key.boff) << ": Invalid jump of bit offset"; } // if(i > 0) EXPECT_GE(it->val.woff, it->key.woff) << "Val offset larger than key offset"; EXPECT_TRUE(it->key.woff != it->val.woff || it->val.boff > it->key.boff) << "Val bit offset did not increase within a word"; EXPECT_EQ(it->key.woff, lit->key.woff); EXPECT_EQ(it->key.boff, lit->key.boff); EXPECT_EQ(it->key.lb_mask, lit->key.lb_mask); test_key_offsets(it, k_len, "Key offsets"); test_key_offsets(lit, lk_len, "Large key offsets"); test_val_offsets(it, v_len, "Val offsets"); test_val_offsets(lit, lv_len, "Large val offsets"); size_t next_bit = (it->val.boff + v_len) % bsizeof(uint64_t); if(next_bit >= 62 || next_bit == 0) break; } EXPECT_EQ(i + 1, this->offsets.block_len()); } INSTANTIATE_TEST_CASE_P(OffsetsTest, ComputeOffsetsTest, ::testing::Combine(::testing::Range(8, 192, 2), // Key lengths ::testing::Range(0, 64), // Val lengths ::testing::Range(4, 9) // Reprobe lengths )); } // namespace { Jellyfish-2.2.8/unit_tests/test_packed_key_value_array.cc000066400000000000000000000155501323712541700237270ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace jellyfish; typedef struct { size_t size, entries, iterations; uint_t key_len, val_len, reprobe_limit; } packed_counting_param; class PackedCountingTest : public ::testing::TestWithParam { public: typedef packed_key_value::array,allocators::malloc> pary_t; typedef hash< uint64_t,uint64_t,pary_t,atomic::gcc > pch_t; typedef std::pair kv_t; pary_t ary; pch_t pch; kv_t *kv_pairs; std::map key_entry_map; PackedCountingTest() : ary(GetParam().size, GetParam().key_len, GetParam().val_len, GetParam().reprobe_limit, quadratic_reprobes), pch(&ary) { } void random_keys_fill() { uint64_t nkey; uint64_t key_mask = (1 << GetParam().key_len) - 1; kv_pairs = new kv_t[GetParam().entries]; for(size_t i = 0; i < GetParam().entries; i++) { do { nkey = rand() & key_mask; } while(nkey == 0 || key_entry_map.find(nkey) != key_entry_map.end()); kv_pairs[i] = kv_t(nkey, 0); key_entry_map[kv_pairs[i].first] = i; } for(size_t i = 0; i < GetParam().iterations; i++) { size_t k = exp_rand(0.5, GetParam().entries); if(ary.add_rec(kv_pairs[k].first % GetParam().size, kv_pairs[k].first, (uint64_t)1, false)) { kv_pairs[k].second++; } } } void large_fields_fill() { std::vector keys; uint64_t key_mask = (1 << GetParam().key_len) - 1; uint64_t fval = (((uint64_t)1) << GetParam().val_len) - 1; uint64_t nkey, nval; kv_pairs = new kv_t[GetParam().entries]; keys.reserve(GetParam().entries); for(size_t i = 0; i < GetParam().entries; i++) { do { nkey = rand() & key_mask; } while(nkey == 0 || key_entry_map.find(nkey) != key_entry_map.end()); keys.push_back(nkey); key_entry_map[nkey] = i; } std::vector shuff_keys = keys; random_shuffle(shuff_keys.begin(), shuff_keys.end()); for(std::vector::const_iterator it = shuff_keys.begin(); it != shuff_keys.end(); it++) { ary.add_rec(*it % GetParam().size, *it, fval, false); ASSERT_TRUE(ary.get_val(*it % GetParam().size, *it, nval)) << std::hex << "Key not set " << (it - shuff_keys.begin()) << " key " << *it; ASSERT_EQ(fval, nval) << "Val not set properly " << (it - shuff_keys.begin()) << " key " << *it; } for(std::vector::const_iterator it = keys.begin(); it != keys.end(); it++) { uint64_t aval = rand() & 7; bool res = ary.add_rec(*it % GetParam().size, *it, aval, false); kv_pairs[it - keys.begin()] = kv_t(*it, fval + (res ? aval : 0)); ASSERT_TRUE(ary.get_val(*it % GetParam().size, *it, nval, true)) << std::hex << "Key not set " << (it - keys.begin()) << " key " << *it; ASSERT_EQ(fval + (res ? aval : 0), nval) << std::hex << "Val not set properly " << (it - keys.begin()) << " key " << *it; } } ~PackedCountingTest() {} // Exponantial distribution with parameter p, truncated into [0, max-1] size_t exp_rand(double p, size_t max) { size_t k; do { k = (size_t)ceil(log(1 - (((double)rand()) / RAND_MAX)) / log(p)) - 1; } while(k >= max); return k; } }; TEST_P(PackedCountingTest, RandomIncrementsIterator) { this->random_keys_fill(); ASSERT_EQ(GetParam().size, this->ary.get_size()); pch_t::iterator it = this->pch.iterator_all(); std::map::iterator key_id; kv_t kv_pair; while(it.next()) { key_id = this->key_entry_map.find(it.key); ASSERT_FALSE(key_entry_map.end() == key_id) << "Unknown key in hash: " << std::hex << it.key << " id " << it.id; kv_pair = kv_pairs[key_id->second]; ASSERT_EQ(kv_pair.first, it.key) << "Bad initialization"; ASSERT_EQ(kv_pairs[key_id->second].second, it.val) << "Error in count for key: " << it.key; } // for(size_t i = 0; i < GetParam().entries; i++) { // ASSERT_EQ((uint64_t)0, kv_pairs[i].second) << // "Error in count for key: " << i << " " << std::hex << kv_pairs[i].first; // } } // Not neede anymore. Only one type of iterator already tested in previous TEST_P // TEST_P(PackedCountingTest, RandomIncrementsFullIterator) { // this->random_keys_fill(); // ASSERT_EQ(GetParam().size, this->pch.size()); // pch_t::full_iterator it = this->pch.full_all(); // std::map::iterator key_id; // kv_t kv_pair; // while(it.next()) { // key_id = this->key_entry_map.find(it.key); // ASSERT_FALSE(key_entry_map.end() == key_id) << // "Unknown key in hash: " << std::hex << it.key << " id " << it.id; // kv_pair = kv_pairs[key_id->second]; // ASSERT_EQ(kv_pair.first, it.key) << // "Bad initialization"; // ASSERT_EQ(kv_pairs[key_id->second].second, it.val) << // "Error in count for key: " << std::hex << it.key; // } // } TEST_P(PackedCountingTest, FullKeyIncrements) { uint64_t fkey = (((uint64_t)1) << GetParam().key_len) - 1; uint64_t key, val; // uint_t overflows; for(size_t i = 0; i < GetParam().size; i++) { this->ary.add_rec(i, fkey, (uint64_t)1, false); ASSERT_TRUE(this->ary.get_key_val(i, key, val)); ASSERT_EQ(fkey, key); // ASSERT_EQ(0u, overflows); ASSERT_EQ(1u, val); } for(size_t i = 0; i < GetParam().size; i++) { this->ary.add_rec(i, fkey, (uint64_t)1, false); ASSERT_TRUE(this->ary.get_key_val(i, key, val)); ASSERT_EQ(fkey, key); // ASSERT_EQ(0u, overflows); ASSERT_EQ(2u, val); } } TEST_P(PackedCountingTest, LargeFields) { this->large_fields_fill(); ASSERT_EQ(GetParam().size, this->pch.get_size()); pch_t::iterator it = this->pch.iterator_all(); std::map::iterator key_id; kv_t kv_pair; while(it.next()) { key_id = this->key_entry_map.find(it.key); ASSERT_FALSE(key_entry_map.end() == key_id) << "Unknown key in hash: " << std::hex << it.key << " id " << it.id; kv_pair = kv_pairs[key_id->second]; ASSERT_EQ(kv_pair.first, it.key) << "Bad initialization"; ASSERT_EQ(kv_pairs[key_id->second].second, it.val) << "Error in count for key: " << std::hex << it.key; } } packed_counting_param pc_params[] = { { 32, 16, 32, 20, 3, 15}, // size, entries, iterations, key_len, val_len, reprobe-limit { 32, 16, 1024, 20, 3, 15}, { 64, 40, 2048, 22, 3, 7} }; INSTANTIATE_TEST_CASE_P(SingleThreadTest, PackedCountingTest, ::testing::ValuesIn(pc_params)); Jellyfish-2.2.8/unit_tests/test_rectangular_binary_matrix.cc000066400000000000000000000217621323712541700244770ustar00rootroot00000000000000#include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_INT128 #include #endif namespace { using jellyfish::RectangularBinaryMatrix; using jellyfish::mer_dna; static bool allocate_matrix(unsigned int r, unsigned c) { RectangularBinaryMatrix m(r, c); return m.is_zero(); } TEST(RectangularBinaryMatrix, InitSizes) { RectangularBinaryMatrix m(5, 60); EXPECT_EQ(5u, m.r()); EXPECT_EQ(60u, m.c()); EXPECT_TRUE(m.is_zero()); EXPECT_THROW(allocate_matrix(100, 100), std::out_of_range); EXPECT_THROW(allocate_matrix(0, 100), std::out_of_range); EXPECT_THROW(allocate_matrix(10, 0), std::out_of_range); } TEST(RectangularBinaryMatrix, Copy) { RectangularBinaryMatrix m1(5, 55); m1.randomize(random_bits); RectangularBinaryMatrix m2(m1); RectangularBinaryMatrix m3(6, 66); RectangularBinaryMatrix m4(5, 55); EXPECT_TRUE(!m1.is_zero()); EXPECT_TRUE(m1 == m2); EXPECT_TRUE(!(m1 == m3)); EXPECT_TRUE(!(m1 == m4)); m4 = m1; EXPECT_TRUE(m1 == m4); } TEST(RectangularBinaryMatrix, InitRaw) { const unsigned int nb_col = 80; uint64_t raw[nb_col]; for(unsigned int i = 0; i < nb_col; ++i) raw[i] = random_bits(); const RectangularBinaryMatrix m(raw, 19, nb_col); EXPECT_EQ(19u, m.r()); EXPECT_EQ(80u, m.c()); const uint64_t mask = ((uint64_t)1 << 19) - 1; for(unsigned int i = 0; i < nb_col; ++i) EXPECT_EQ(raw[i] & mask, m[i]); } TEST(RectangularBinaryMatrix, LowIdentity) { for(int r = 2; r < 64; r += 2) { for(int c = 2; c < 100; c += 2) { SCOPED_TRACE(::testing::Message() << "matrix " << r << "x" << c); RectangularBinaryMatrix m(r, c); // Matrix should be zeroed out mer_dna::k(c); mer_dna v; v.randomize(); EXPECT_FALSE(m.is_low_identity()); m.init_low_identity(); EXPECT_TRUE(m.is_low_identity()); uint64_t res = m.times(v); EXPECT_EQ(v.get_bits(0, std::min(r, c)), res); RectangularBinaryMatrix m2 = RectangularBinaryMatrix::identity(r); uint64_t res2 = m2.times(v); EXPECT_EQ(v.get_bits(0, r), res2); } } } /****************************** * Matrix Vector product ******************************/ class MatrixVectorProd : public ::testing::TestWithParam< ::std::tr1::tuple > { public: unsigned int row, col; RectangularBinaryMatrix m; MatrixVectorProd() : row(::std::tr1::get<0>(GetParam())), col(::std::tr1::get<1>(GetParam())), m(row, col) { m.randomize(random_bits); } }; TEST_P(MatrixVectorProd, Checks) { EXPECT_EQ(row, m.r()); EXPECT_EQ(col, m.c()); } TEST_P(MatrixVectorProd, AllOnes) { uint64_t v[2], res = 0; v[0] = v[1] = (uint64_t)-1; for(unsigned int i = 0; i < m.c(); ++i) res ^= m[i]; EXPECT_EQ(res, m.times_loop(v)); #ifdef HAVE_INT128 EXPECT_EQ(res, m.times_128(v)); #endif #ifdef HAVE_SSE EXPECT_EQ(res, m.times_sse(v)); #endif } TEST_P(MatrixVectorProd, EveryOtherOnes) { uint64_t v[2], res = 0; v[0] = 0xaaaaaaaaaaaaaaaaUL; v[1] = 0xaaaaaaaaaaaaaaaaUL; for(unsigned int i = 0; i < m.c(); i += 2) res ^= m[i]; EXPECT_EQ(res, m.times_loop(v)); #ifdef HAVE_INT128 EXPECT_EQ(res, m.times_128(v)); #endif #ifdef HAVE_SSE EXPECT_EQ(res, m.times_sse(v)); #endif v[0] >>= 1; v[1] >>= 1; res = 0; for(unsigned int i = 1; i < m.c(); i += 2) res ^= m[i]; EXPECT_EQ(res, m.times_loop(v)); #ifdef HAVE_INT128 EXPECT_EQ(res, m.times_128(v)); #endif #ifdef HAVE_SSE EXPECT_EQ(res, m.times_sse(v)); #endif } #if HAVE_SSE || HAVE_INT128 TEST_P(MatrixVectorProd, Optimizations) { static const int nb_tests = 100; const unsigned int nb_words = col / 64 + (col % 64 != 0); uint64_t v[nb_words]; for(int i = 0; i < nb_tests; ++i) { // unsigned int r = 2 * (random() % 31 + 1); // unsigned int c = 2 * (random() % 100) + r; // RectangularBinaryMatrix m(r, c); // m.randomize(random_bits); for(unsigned int j = 0; j < nb_words; ++j) v[j] = random_bits(); uint64_t res = m.times_loop((uint64_t*)v); #ifdef HAVE_SSE EXPECT_EQ(res, m.times_sse((uint64_t*)v)); #endif #ifdef HAVE_INT128 EXPECT_EQ(res, m.times_128((uint64_t*)v)); #endif } } #endif // HAVE_SSE || HAVE_INT128 INSTANTIATE_TEST_CASE_P(MatrixVectorProdTest, MatrixVectorProd, ::testing::Combine(::testing::Range(1, 65, 1), // rows ::testing::Range(2, 100, 2))); // cols /****************************** * Matrix product and inverse ******************************/ TEST(PseudoProduct, Dimensions) { RectangularBinaryMatrix m(30, 100), m1(32, 100), m2(30, 98); EXPECT_THROW(m.pseudo_multiplication(m1), std::domain_error); EXPECT_THROW(m.pseudo_multiplication(m2), std::domain_error); } TEST(PseudoProduct, Identity) { RectangularBinaryMatrix m(30, 100), i(30, 100); i.init_low_identity(); m.randomize(random_bits); EXPECT_TRUE(i.pseudo_multiplication(m) == m); } TEST(PseudoProduct, Parity) { const unsigned int col_sizes[6] = { 50, 70, 126, 130, 64, 128 }; const unsigned int nb_rows = 30; for(unsigned int k = 0; k < sizeof(col_sizes) / sizeof(unsigned int); ++k) { const unsigned int nb_cols = col_sizes[k]; uint64_t *cols = new uint64_t[nb_cols]; RectangularBinaryMatrix p(nb_rows, nb_cols); for(unsigned int j = 18; j < 19; ++j) { const uint64_t bits = ((uint64_t)1 << j) - 1; unsigned int i; for(i = 0; i < nb_cols; ++i) cols[i] = bits; RectangularBinaryMatrix m(cols, nb_rows, nb_cols); p = m.pseudo_multiplication(m); for(i = 0; i < nb_cols - nb_rows; ++i) EXPECT_EQ(__builtin_parity(bits) ? (uint64_t)0 : bits, p[i]); for( ; i < nb_cols; ++i) EXPECT_EQ(__builtin_parity(bits) ? bits : (uint64_t)0, p[i]); } delete [] cols; } } TEST(PseudoProduct, Inverse) { int full_rank = 0, singular = 0; for(unsigned int i = 0; i < 500; ++i) { unsigned int r = random() % 63 + 1; unsigned int c = 2 * ((random() % 100) + 1); SCOPED_TRACE(::testing::Message() << "Dimension " << r << "x" << c); RectangularBinaryMatrix m(r, c); m.randomize(random_bits); RectangularBinaryMatrix s(m); unsigned int rank = m.pseudo_rank(); if(rank != c) { ++singular; EXPECT_THROW(m.pseudo_inverse(), std::domain_error); } else { ++full_rank; RectangularBinaryMatrix inv(m); EXPECT_NO_THROW(inv = m.pseudo_inverse()); RectangularBinaryMatrix i = inv.pseudo_multiplication(m); EXPECT_TRUE(i.is_low_identity()); } EXPECT_TRUE(s == m); } EXPECT_EQ(500, full_rank + singular); EXPECT_NE(0, full_rank); } TEST(PseudoProduct, Rank) { RectangularBinaryMatrix m(50, 100); for(unsigned int i = 0; i < 10; ++i) { m.randomize(random_bits); RectangularBinaryMatrix s(m); unsigned int rank = m.pseudo_rank(); EXPECT_TRUE(rank <= m.c()); EXPECT_TRUE(s == m); } } TEST(PseudoProduct, InitRandom) { RectangularBinaryMatrix m(50, 100); for(unsigned int i = 0; i < 10; ++i) { RectangularBinaryMatrix im(m.randomize_pseudo_inverse(random_bits)); EXPECT_EQ((unsigned int)m.c(), m.pseudo_rank()); EXPECT_EQ((unsigned int)m.c(), im.pseudo_rank()); EXPECT_TRUE((m.pseudo_multiplication(im)).is_low_identity()); } } TEST(PseudoProduct, VectorInverseMultiplication) { RectangularBinaryMatrix m(50, 132); RectangularBinaryMatrix im(m.randomize_pseudo_inverse()); RectangularBinaryMatrix cim(im); EXPECT_TRUE(cim.pseudo_multiplication(m).is_low_identity()); mer_dna::k(66); mer_dna v, iv, iv2; EXPECT_EQ(m.nb_words(), v.nb_words()); for(int i = 0; i < 100; ++i) { SCOPED_TRACE(::testing::Message() << "i=" << i); v.randomize(); uint64_t hash = m.times(v); iv = v; iv.set_bits(0, 50, hash); uint64_t lower = im.times(iv); EXPECT_EQ(v.get_bits(0, 50), lower); } } static const int speed_loop = 100000000; TEST(MatrixProductSpeed, Loop) { RectangularBinaryMatrix m(50, 100); const unsigned int nb_words = m.c() / 64 + (m.c() % 64 != 0); uint64_t v[nb_words]; for(unsigned int j = 0; j < nb_words; ++j) v[j] = random_bits(); volatile uint64_t res = 0; for(int i = 0; i < speed_loop; ++i) res ^= m.times_loop((uint64_t*)v); } #ifdef HAVE_SSE TEST(MatrixProductSpeed, SSE) { RectangularBinaryMatrix m(50, 100); const unsigned int nb_words = m.c() / 64 + (m.c() % 64 != 0); uint64_t v[nb_words]; for(unsigned int j = 0; j < nb_words; ++j) v[j] = random_bits(); volatile uint64_t res = 0; for(int i = 0; i < speed_loop; ++i) res ^= m.times_sse((uint64_t*)v); } #endif #ifdef HAVE_INT128 TEST(MatrixProductSpeed, U128) { RectangularBinaryMatrix m(50, 100); const unsigned int nb_words = m.c() / 64 + (m.c() % 64 != 0); uint64_t v[nb_words]; for(unsigned int j = 0; j < nb_words; ++j) v[j] = random_bits(); volatile uint64_t res = 0; for(int i = 0; i < speed_loop; ++i) res ^= m.times_128((uint64_t*)v); } #endif } Jellyfish-2.2.8/unit_tests/test_simple_circular_buffer.cc000066400000000000000000000027021323712541700237370ustar00rootroot00000000000000#include #include namespace { static const int capa = 16; typedef jellyfish::simple_circular_buffer::pre_alloc test_simple_circular_buffer; TEST(SimpleCircularBufferTest, FillEmpty) { int ary[capa]; test_simple_circular_buffer buffer(ary); EXPECT_EQ(capa, buffer.capacity()); EXPECT_TRUE(buffer.empty()); for(int i = 0; i < buffer.capacity(); ++i) { SCOPED_TRACE(::testing::Message() << "i=" << i); EXPECT_FALSE(buffer.full()); EXPECT_EQ(i, buffer.size()); buffer.push_back(i); EXPECT_EQ(i, buffer.back()); EXPECT_FALSE(buffer.empty()); } EXPECT_TRUE(buffer.full()); for(int i = 0; i < buffer.capacity(); ++i) { SCOPED_TRACE(::testing::Message() << "i=" << i); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(i, buffer.front()); EXPECT_EQ(buffer.capacity() - i, buffer.size()); buffer.pop_front(); EXPECT_FALSE(buffer.full()); } EXPECT_TRUE(buffer.empty()); EXPECT_EQ(0, buffer.size()); } TEST(SimpleCircularBufferTest, Usefull) { int ary[capa]; test_simple_circular_buffer buffer(ary); EXPECT_EQ(capa, buffer.capacity()); int i = 0; for( ; i < buffer.capacity(); ++i) { EXPECT_TRUE(buffer.push_back()); buffer.back() = i; } for( ; i < 10 * buffer.capacity(); ++i) { EXPECT_EQ(i - capa, buffer.front()); buffer.pop_front(); EXPECT_TRUE(buffer.push_back()); buffer.back() = i; } } } // namespace { Jellyfish-2.2.8/unit_tests/test_square_binary_matrix.cc000066400000000000000000000073301323712541700234630ustar00rootroot00000000000000#include #include #include #include #include class RandomEnvironment : public ::testing::Environment { public: virtual void SetUp() { std::ifstream dev_rand("/dev/urandom"); unsigned int seed; dev_rand.read((char *)&seed, sizeof(seed)); std::cout << "Seed: " << seed << std::endl; dev_rand.close(); srandom(seed); } }; //::testing::Environment* const foo_env = ::testing::AddGlobalTestEnvironment(new RandomEnvironment); #define VECLEN 44 TEST(SquareBinaryMatrix, Initialization) { SquareBinaryMatrix small_id_m(8); small_id_m.init_identity(); ASSERT_STREQ("8x8\n10000000\n01000000\n00100000\n00010000\n00001000\n00000100\n00000010\n00000001\n", small_id_m.str().c_str()); SquareBinaryMatrix id_m(VECLEN); SquareBinaryMatrix rand_m(VECLEN); id_m.init_identity(); ASSERT_TRUE(id_m.is_identity()); ASSERT_EQ(VECLEN, id_m.get_size()); rand_m.init_random(); ASSERT_EQ(VECLEN, rand_m.get_size()); SquareBinaryMatrix rand2_m(5); rand2_m = rand_m; ASSERT_TRUE(rand_m == rand2_m); ASSERT_FALSE(rand_m != rand2_m); SquareBinaryMatrix rand3_m = rand_m; ASSERT_TRUE(rand_m == rand3_m); ASSERT_FALSE(rand_m != rand3_m); uint64_t v = random_vector(VECLEN); ASSERT_EQ(v, id_m.times(v)); ASSERT_TRUE(rand_m == rand_m.transpose().transpose()); ASSERT_TRUE(id_m == id_m.transpose()); SquareBinaryMatrix sym_m = rand_m.transpose() * rand_m; ASSERT_TRUE(sym_m == sym_m.transpose()); ASSERT_FALSE(rand_m[0] == v); // Could fail with probability 2**-64!! rand_m[0] = v; ASSERT_TRUE(rand_m[0] == v); ASSERT_TRUE(rand_m == (id_m * rand_m)); int i, regular = 0, singular = 0; for(i = 0; i < 10; i++) { SquareBinaryMatrix tmp_m(32); tmp_m.init_random(); try { SquareBinaryMatrix inv_m = tmp_m.inverse(); SquareBinaryMatrix sbi_m = inv_m * tmp_m; regular++; ASSERT_TRUE(sbi_m.is_identity()) << "Not identity\n" << sbi_m.str() << std::endl; } catch(SquareBinaryMatrix::SingularMatrix e) { singular++; } } ASSERT_EQ(10, regular + singular); for(i = 0; i < 100; i++) { v = random_vector(VECLEN); ASSERT_EQ(rand_m.times_loop(v), rand_m.times_unrolled(v)); #ifdef SSE ASSERT_EQ(rand_m.times_loop(v), rand_m.times_sse(v)); #endif } // speed tests uint64_t v1 = random_vector(VECLEN); uint64_t v2 = random_vector(VECLEN); uint64_t v3 = random_vector(VECLEN); uint64_t v4 = random_vector(VECLEN); uint64_t v5 = random_vector(VECLEN); uint64_t v6 = random_vector(VECLEN); uint64_t v7 = random_vector(VECLEN); uint64_t v8 = random_vector(VECLEN); uint64_t res_unrolled = 0, res_sse = 0; Time time1; const int nb_loops = 2560000; for(i = 0; i < nb_loops; i++) { res_unrolled ^= rand_m.times_unrolled(v1); res_unrolled ^= rand_m.times_unrolled(v2); res_unrolled ^= rand_m.times_unrolled(v3); res_unrolled ^= rand_m.times_unrolled(v4); res_unrolled ^= rand_m.times_unrolled(v5); res_unrolled ^= rand_m.times_unrolled(v6); res_unrolled ^= rand_m.times_unrolled(v7); res_unrolled ^= rand_m.times_unrolled(v8); } Time time2; for(i = 0; i < nb_loops; i++) { res_sse ^= rand_m.times_sse(v1); res_sse ^= rand_m.times_sse(v2); res_sse ^= rand_m.times_sse(v3); res_sse ^= rand_m.times_sse(v4); res_sse ^= rand_m.times_sse(v5); res_sse ^= rand_m.times_sse(v6); res_sse ^= rand_m.times_sse(v7); res_sse ^= rand_m.times_sse(v8); } Time time3; ASSERT_LT(time3 - time2, time2 - time1); // std::cout << "unrolled timing " << (time2 - time1).str() << // " sse timing " << (time3 - time2).str() << std::endl; ASSERT_EQ(res_unrolled, res_sse); } Jellyfish-2.2.8/unit_tests/test_stdio_filebuf.cc000066400000000000000000000032421323712541700220470ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include namespace { typedef jellyfish::stdio_filebuf stdio_filebuf; TEST(StdioFileBuf, Read) { const char* file_name = "test_stdio_file_buf_read"; file_unlink fu(file_name); std::vector buffer(8192); for(size_t i = 0; i < buffer.size(); ++i) buffer[i] = '@' + (i % 64); { std::ofstream out(file_name); out.write(buffer.data(), buffer.size()); } int fd = open(file_name, O_RDONLY); EXPECT_GT(fd, -1); FILE* file = fopen(file_name, "r"); EXPECT_NE((FILE*)0, file); std::unique_ptr fd_buf(new stdio_filebuf(fd, std::ios::in)); std::istream fd_stream(fd_buf.get()); std::unique_ptr file_buf(new stdio_filebuf(file, std::ios::in)); std::istream file_stream(file_buf.get()); size_t have_read = 0; char read_buffer[256]; while(have_read < buffer.size()) { const size_t to_read = random_bits(8); const size_t expect_read = std::min(buffer.size() - have_read, to_read); fd_stream.read(read_buffer, to_read); EXPECT_EQ(expect_read, fd_stream.gcount()); EXPECT_EQ(0, std::strncmp(&buffer[have_read], read_buffer, expect_read)); file_stream.read(read_buffer, to_read); EXPECT_EQ(expect_read, fd_stream.gcount()); EXPECT_EQ(0, std::strncmp(&buffer[have_read], read_buffer, expect_read)); have_read += expect_read; } EXPECT_TRUE(fd_stream.eof() || fd_stream.peek() == EOF); EXPECT_TRUE(file_stream.eof() || file_stream.peek() == EOF); } } Jellyfish-2.2.8/unit_tests/test_stream_iterator.cc000066400000000000000000000052671323712541700224460ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include namespace { namespace err = jellyfish::err; typedef std::vector path_vector; typedef path_vector::const_iterator path_iterator; typedef jellyfish::stream_iterator stream_iterator; class StreamIterator : public ::testing::Test { protected: static path_vector paths; static int total_lines; static char* tmpdir; static void SetUpTestCase() { tmpdir = strdup("/tmp/stream_iterator_XXXXXX"); if(!mkdtemp(tmpdir)) throw std::runtime_error(err::msg() << "Failed to create tmp directory: " << err::no); int nb_files = jellyfish::random_bits(5); for(int i = 0; i < nb_files; ++i) { std::ostringstream path; path << tmpdir << "/" << i; paths.push_back(strdup(path.str().c_str())); std::ofstream tmp_file(path.str().c_str()); if(tmp_file.fail()) throw std::runtime_error(err::msg() << "Failed to open file '" << path.str() << "' for writing"); int nb_lines = jellyfish::random_bits(6); total_lines += nb_lines; for(int j = 0; j < nb_lines; ++j) tmp_file << "line " << j << "\n"; } } static void TearDownTestCase() { for(path_iterator it = paths.begin(); it != paths.end(); ++it) { if(unlink(*it) == -1) throw std::runtime_error(err::msg() << "Failed to unlink file '" << *it << ": " << err::no); free((void*)*it); } if(rmdir(tmpdir) == -1) throw std::runtime_error(err::msg() << "Failed to rmdir '" << tmpdir << ": " << err::no); free(tmpdir); } }; path_vector StreamIterator::paths; int StreamIterator::total_lines = 0; char* StreamIterator::tmpdir; TEST_F(StreamIterator, Empty) { stream_iterator sit(paths.begin(), paths.begin()); stream_iterator send; int nb_files = 0; int nb_lines = 0; for( ; sit != send; ++sit, ++nb_files) for(std::string line; std::getline(*sit, line); ++nb_lines) ; EXPECT_EQ(0, nb_files); EXPECT_EQ(0, nb_lines); } TEST_F(StreamIterator, RandomFiles) { SCOPED_TRACE(::testing::Message() << "nb_files:" << paths.size() << " nb_lines:" << total_lines); stream_iterator sit(paths.begin(), paths.end()); stream_iterator send; int nb_files = 0; int nb_lines = 0; for( ; sit != send; ++sit, ++nb_files) { for(std::string line; std::getline(*sit, line); ++nb_lines) ; EXPECT_TRUE(sit->eof()); } EXPECT_EQ(paths.size(), (size_t)nb_files); EXPECT_EQ(total_lines, nb_lines); } } Jellyfish-2.2.8/unit_tests/test_text_dumper.cc000066400000000000000000000055761323712541700216050ustar00rootroot00000000000000#include #include #include #include #include #include #include namespace { using jellyfish::mer_dna; typedef jellyfish::cooperative::hash_counter hash_counter; typedef hash_counter::array::lazy_iterator lazy_iterator; typedef hash_counter::array::eager_iterator eager_iterator; typedef hash_counter::array::region_iterator region_iterator; typedef jellyfish::text_dumper dumper; class hash_adder : public jellyfish::thread_exec { typedef std::map map; typedef std::vector maps; hash_counter& hash_; int nb_; maps check_; public: hash_adder(hash_counter& hash, int nb, int nb_threads) : hash_(hash), nb_(nb), check_(nb_threads) { } void start(int id) { mer_dna m; map& my_map = check_[id]; for(int i = 0; i < nb_; ++i) { m.randomize(); hash_.add(m, 1); ++my_map[m]; } hash_.done(); } void maps_consolidate() { maps::iterator first = check_.begin(); maps::const_iterator it = first; for(++it; it < check_.end(); ++it) for(map::const_iterator vit = it->begin(); vit != it->end(); ++vit) (*first)[vit->first] += vit->second; } void hash_check() { map& m = check_.front(); size_t id; for(map::const_iterator vit = m.begin(); vit != m.end(); ++vit) EXPECT_TRUE(hash_.ary()->get_key_id(vit->first, &id)); } uint64_t operator[](const mer_dna& m) const { map::const_iterator it = check_.front().find(m); if(it == check_.front().end()) return 0; else return it->second; } size_t size() const { return check_.front().size(); } }; template struct inc_on_destructor { T* const x; inc_on_destructor(T* nb) : x(nb) { } ~inc_on_destructor() { ++*x; } operator T() const { return *x; } }; TEST(TextDumper, Random) { static int iteration_count_ = 0; ++iteration_count_; static const int mer_len = 35; static const int nb_threads = 5; static const int nb = 5000; static const size_t init_size = 5000; static const char* file = "./text_dumper"; file_unlink f(file); mer_dna::k(mer_len); hash_counter hash(init_size, mer_len * 2, 5, nb_threads, 15); hash_adder adder(hash, nb, nb_threads); adder.exec_join(nb_threads); adder.maps_consolidate(); adder.hash_check(); { dumper d(nb_threads, file); d.one_file(true); d.dump(hash.ary()); } std::ifstream fd(file); std::string line; mer_dna m; uint64_t count = 0; while(std::getline(fd, line)) { m = line.substr(0, mer_dna::k()); EXPECT_EQ(adder[m], (uint64_t)atol(line.substr(mer_dna::k() + 1).c_str())); ++count; } EXPECT_EQ(adder.size(), count); // unlink(file); } } // namespace { Jellyfish-2.2.8/unit_tests/test_token_ring.cc000066400000000000000000000017531323712541700213750ustar00rootroot00000000000000#include #include #include #include #include namespace { using jellyfish::thread_exec; struct write_number : public thread_exec { typedef jellyfish::token_ring token_ring; std::ostream *os_; int nb_threads_; token_ring ring; public: write_number(std::ostream* os, int nb_threads) : os_(os), nb_threads_(nb_threads), ring(nb_threads) { } virtual void start(int i) { token_ring::token& token = ring[i]; for(int j = 0; j < 10; ++j) { token.wait(); *os_ << (nb_threads_ * j + i) << "\n"; token.pass(); } } }; TEST(TokenRing, Count) { static const int nb_threads = 5; std::ostringstream out; write_number write(&out, nb_threads); write.exec_join(nb_threads); std::ostringstream res; for(int i = 0; i < nb_threads * 10; ++i) res << i << "\n"; EXPECT_EQ(res.str(), out.str()); } } // namespace { Jellyfish-2.2.8/unit_tests/test_whole_sequence_parser.cc000066400000000000000000000115551323712541700236210ustar00rootroot00000000000000#include #include #include #include namespace { using std::string; using std::istringstream; template struct opened_streams { Iterator begin_, end_; opened_streams(Iterator begin, Iterator end) : begin_(begin), end_(end) { } jellyfish::stream_type next() { jellyfish::stream_type res; if(begin_ != end_) { res.standard.reset(*begin_); ++begin_; } return res; } }; typedef jellyfish::whole_sequence_parser > parser_type; TEST(SequenceParser, Fasta) { static const char* seq1 = "ATTACCTTGTACCTTCAGAGC"; static const char* seq2 = "TTCGATCCCTTGATAATTAGTCACGTTAGCT"; const char* file_name = "Fasta.fa"; file_unlink fu(file_name); { std::ofstream sequence(file_name); sequence << ">header1\n" << seq1 << "\n\n" << ">header2\n" << seq2 << "\n\n\n" << seq1; } auto sequence = new std::ifstream(file_name); opened_streams streams(&sequence, &sequence + 1); parser_type parser(10, 1, 1, streams); { parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); ASSERT_EQ((size_t)1, j->nb_filled); EXPECT_STREQ("header1", j->data[0].header.c_str()); EXPECT_STREQ(seq1, j->data[0].seq.c_str()); } { parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); ASSERT_EQ((size_t)1, j->nb_filled); EXPECT_STREQ("header2", j->data[0].header.c_str()); EXPECT_EQ(strlen(seq2) + strlen(seq1), j->data[0].seq.size()); EXPECT_STREQ(seq2, j->data[0].seq.substr(0, strlen(seq2)).c_str()); EXPECT_STREQ(seq1, j->data[0].seq.substr(strlen(seq2)).c_str()); } { parser_type::job j(parser); EXPECT_TRUE(j.is_empty()); } EXPECT_EQ((size_t)1, parser.nb_files()); EXPECT_EQ((size_t)2, parser.nb_reads()); } TEST(SequenceParser, Fastq) { static const char* seq1 = "ATTACCTTGTACCTTCAGAGC"; static const char* seq2 = "TTCGATCCCTTGATAATTAGTCACGTTAGCT"; const char* file_name = "Fasta.fq"; file_unlink fu(file_name); { std::ofstream sequence(file_name); sequence << "@header1\n" << seq1 << "\n\n" << "+and some stuff\n" << seq1 << "\n" << "@header2\n" << seq2 << "\n\n\n" << seq1 << "\n" << "+\n" << seq1 << "\n" << seq2 << "\n"; } auto sequence = new std::ifstream(file_name); opened_streams streams(&sequence, &sequence + 1); parser_type parser(10, 1, 1, streams); { parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); ASSERT_EQ((size_t)1, j->nb_filled); EXPECT_STREQ("header1", j->data[0].header.c_str()); EXPECT_STREQ(seq1, j->data[0].seq.c_str()); EXPECT_STREQ(seq1, j->data[0].qual.c_str()); } { parser_type::job j(parser); ASSERT_FALSE(j.is_empty()); ASSERT_EQ((size_t)1, j->nb_filled); EXPECT_STREQ("header2", j->data[0].header.c_str()); EXPECT_EQ(strlen(seq2) + strlen(seq1), j->data[0].seq.size()); EXPECT_EQ(strlen(seq2) + strlen(seq1), j->data[0].qual.size()); EXPECT_STREQ(seq2, j->data[0].seq.substr(0, strlen(seq2)).c_str()); EXPECT_STREQ(seq1, j->data[0].seq.substr(strlen(seq2)).c_str()); EXPECT_STREQ(seq1, j->data[0].qual.substr(0, strlen(seq1)).c_str()); EXPECT_STREQ(seq2, j->data[0].qual.substr(strlen(seq1)).c_str()); } { parser_type::job j(parser); EXPECT_TRUE(j.is_empty()); } EXPECT_EQ((size_t)1, parser.nb_files()); EXPECT_EQ((size_t)2, parser.nb_reads()); } TEST(SequenceParser, FastaMany) { const char* file_name = "FastaMany.fa"; file_unlink fu(file_name); static const int nb_sequences = 1000; { std::ofstream sequence(file_name); ASSERT_TRUE(sequence.good()); for(int i = 0; i < nb_sequences; ++i) { const int seq_len = random_bits(8) + 10; sequence << ">" << i << " " << seq_len << "\n"; for(int j = 0; j < seq_len; ++j) { sequence << (char)('A' + j % 26); if(random_bits(6) == 0) sequence << '\n'; } sequence << '\n'; } } auto sequence = new std::ifstream(file_name); opened_streams streams(&sequence, &sequence + 1); parser_type parser(10, 13, 1, streams); int got_sequences = 0; while(true) { parser_type::job job(parser); if(job.is_empty()) break; for(size_t i = 0; i < job->nb_filled; ++i) { ++got_sequences; const size_t len_pos = job->data[i].header.find_first_of(" "); const int seq_len = atoi(job->data[i].header.c_str() + len_pos + 1); ASSERT_LE(10, seq_len); for(int j = 0; j < seq_len; ++j) EXPECT_EQ('A' + (j % 26), job->data[i].seq[j]); } } EXPECT_EQ(nb_sequences, got_sequences); EXPECT_EQ((size_t)1, parser.nb_files()); EXPECT_EQ((size_t)nb_sequences, parser.nb_reads()); } } Jellyfish-2.2.8/unit_tests/unit_tests.sh000066400000000000000000000002031323712541700204120ustar00rootroot00000000000000#! /bin/sh cd tests . ./compat.sh if [ -n "$VALGRIND" ]; then exec valgrind ${DIR}/test_all else exec ${DIR}/test_all fi