diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..2cc6c23 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,20 @@ +Authors +======= + +Georg Nebehay + +Contributors +============ + +Clemens Korner +Bernd Lukatschek +João Silva +Lucas Doyle +Lukas Oberhuber +Michael Rennie +Sebastian Borggrewe +Jonathan Senecal +Huang Xin +Jason Catchpole +Victor Daropoulos +Klaus Haag diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4f3d6e9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,95 @@ +# Open The CMake GUI +# specify the source directory and the binary directory +# press configure. +# +# UNIX Makefile: +# 1) go to the binary folder and type "make" to build the project +# +# Microsoft Visual C++: +# 1) open the .sln file +# 2) build the project "ALL_BUILD" to build the opentld project + + +project(CF_TLD) +cmake_minimum_required(VERSION 2.6) + +# add c++11 support +if(CMAKE_COMPILER_IS_GNUCC) + ADD_DEFINITIONS ( -std=c++11 ) +endif(CMAKE_COMPILER_IS_GNUCC) + +set(OpenCV_DIR "/usr/local/AID/opencv3.3.0") +#set(OpenCV_DIR "/home/firefly/opencv-3.3.0/build") + +#find_package(OpenCV REQUIRED highgui video videoio imgproc imgcodecs) + +# find_package(OpenCV) does not account for proper path setup +# on windows; proper path setup requires path "OPENCV_DIR" +# pointing to ie. \build_opencv_3\install\x64\vc12 +set(OPENCV_DIR_HINT "/usr/local/AID/opencv3.3.0") + +if(WIN32) + get_filename_component(OPENCV_DIR_PLATFORM $ENV{OPENCV_DIR} DIRECTORY) + get_filename_component(OPENCV_DIR_HINT ${OPENCV_DIR_PLATFORM} DIRECTORY) +endif(WIN32) + +set(OpenCV_STATIC OFF) +find_package(OpenCV REQUIRED HINTS ${OPENCV_DIR_HINT}) +# OpenCV 3.0 does currently not include its' includes correctly +include_directories(${OpenCV_DIR}/include) + + +#------------------------------------------------------------------------------- +#version +set(TLD_VERSION_MAJOR 1) +set(TLD_VERSION_MINOR 4) +set(TLD_VERSION_PATCH 0) +set(TLD_VERSION ${TLD_VERSION_MAJOR}.${TLD_VERSION_MINOR}.${TLD_VERSION_PATCH}) + +#------------------------------------------------------------------------------ +#build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING + "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." + FORCE) +endif(NOT CMAKE_BUILD_TYPE) + +option(USE_SYSTEM_LIBS "Use the installed version of libconfig++." OFF) +option(WITH_OPENMP "Use OpenMP." OFF) + +if(WITH_OPENMP) + find_package(OpenMP REQUIRED) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") +endif(WITH_OPENMP) + +if(WIN32) + add_definitions(-DLIBCONFIGXX_STATIC -DLIBCONFIG_STATIC) #Needed when linking libconfig statically +endif(WIN32) + +if(APPLE) + add_definitions(-DHAVE_XLOCALE_H) +endif(APPLE) + +if(NOT MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +endif(NOT MSVC) + +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) + +#------------------------------------------------------------------------------- +#add subdirectories +add_subdirectory(src/3rdparty/cf_tracking) + +if(NOT USE_SYSTEM_LIBS) + add_subdirectory(src/3rdparty/libconfig) +endif(NOT USE_SYSTEM_LIBS) + +add_subdirectory(src/libopentld) +add_subdirectory(src/opentld) + +configure_file("${PROJECT_SOURCE_DIR}/OpenTLDConfig.cmake.in" "${PROJECT_BINARY_DIR}/OpenTLDConfig.cmake" @ONLY) diff --git a/LICENSE b/LICENSE index 261eeb9..20d40b6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,674 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + 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 +. \ No newline at end of file diff --git a/OpenTLDConfig.cmake.in b/OpenTLDConfig.cmake.in new file mode 100644 index 0000000..0d941c2 --- /dev/null +++ b/OpenTLDConfig.cmake.in @@ -0,0 +1,21 @@ +find_package(OpenCV) + +set(bin_dir "@PROJECT_BINARY_DIR@") +set(src_dir "@PROJECT_SOURCE_DIR@") + +set(OPENTLD_INCLUDE_DIRS + ${src_dir}/src/3rdparty/cvblobs + ${src_dir}/src/3rdparty/libconfig + ${src_dir}/src/libopentld/tld + ${src_dir}/src/libopentld/mftracker + ${src_dir}/src/libopentld/imacq + ${src_dir}/src/opentld/main) +INCLUDE_DIRECTORIES(${OPENTLD_INCLUDE_DIRS}) + +SET(OPENTLD_LIB_DIRS ${LIBRARY_OUTPUT_PATH}) +LINK_DIRECTORIES(${OPENTLD_LIB_DIRS}) + +set(OPENTLD_LIBS cvblobs libconfig libopentld) + + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..05b10ac --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +# Introduction + +This is a fork of the [C++ implementation of OpenTLD](https://github.com/gnebehay/OpenTLD) called CFtld. +OpenTLD was originally proposed in [1] and implemented by Georg Nebehay in C++. + +This fork uses C++ implementations of correlation filter based trackers as short-term trackers. Both short-term trackers are modified variants of the visual trackers proposed in [2,3]. +The short-term trackers are extended with target loss detection capabilities as in [4] and use the C++ implementation [5] of the FHOG features proposed in [6]. More implementation details of the short-term trackers can be found [here](src/3rdparty/cf_tracking/README.md). The detection cascade is only used to suggest possible target locations to the short-term trackers for redetection purposes. It cannot reinitialize the short-term trackers. The short-term trackers decide whether a suggested patch actually contains the target. + +The system starts with the KCFcpp as default short-term tracker. + +# Usage +If you have a webcam attached to your PC, you can simply execute cftld (on Linux) or cftld.exe (on Windows) in order to +try it out. +### Keyboard shortcuts +* `r` select a target +* `q` quit +* `l` toggle learning +* `a` toggle alternating mode (if true, detector is switched off when tracker is available) + +### Command line options +#### Synopsis +`cftld [option arguments] [arguments]` + +#### option arguments +* `-x Use DSSTcpp instead of KCFcpp as short-term tracker. KCFcpp is the default short-term tracker.` +* `[-a ]` video starts at the frameNumber _startFrameNumber_ +* `[-b ]` Initial bounding box +* `[-d ]` select input device: _device_=(IMGS|CAM|VID|STREAM) + _IMGS_: capture from images + _CAM_: capture from connected camera + _VID_: capture from a video + _STREAM_: capture from RTSP stream +* `[-f]` shows foreground +* `[-i ]` _path_ to the images or to the video. +* `[-j ]` show trajectory for the last _number_ frames +* `[-h]` shows help +* `[-n ]` Specifies the video device to use (defaults to 0). Useful to select a different camera when multiple cameras are connected. +* `[-p path]` prints results into the file _path_ +* `[-s]` if set, user can select initial bounding box +* `[-t ]` threshold for determining positive results +* `[-z ]` video ends at the frameNumber _lastFrameNumber_. + If _lastFrameNumber_ is 0 or the option argument isn't specified means + all frames are taken. + +#### Arguments +`[CONFIG_FILE]` path to config file + +### Config files +Refer to the sample folder to see usage and config file examples. + +# Build +### Dependencies +* C++11 +* OpenCV 3.0 +* CMake +* libconfig++ (provided) +* SSE2-capable CPU + +### Windows 7 +* Set environment variables according to http://docs.opencv.org/doc/tutorials/introduction/windows_install/windows_install.html +* Launch cmake-gui, create a build folder and configure. +* Open CF_TLD.sln in Visual Studio and compile the project `opentld`. + +### Ubuntu 14.04 +* Install OpenCV 3.0 and CMake. +* Configure and compile: +``` +mkdir /build +cd /build +cmake ../ +make -j 8 +``` + +# Commercial Use (US) +The code using linear correlation filters may be affected by a US patent. If you want to use this code commercially in the US please refer to http://www.cs.colostate.edu/~vision/ocof_toolset_2012/index.php for possible patent claims. + +# References +If you reuse this code for a scientific publication, please cite the related publications (dependent on what parts of the code you reuse): + +[1] +``` +@article{kalal2012TLD, +title={Tracking-Learning-Detection}, +author={Kalal, Zdenek and Mikolajczyk, Krystian and Matas, Jiri}, +journal={Pattern Analysis and Machine Intelligence, IEEE Transactions on}, +year={2012}} +``` + +[2] +``` +@article{henriques2015tracking, +title = {High-Speed Tracking with Kernelized Correlation Filters}, +author = {Henriques, J. F. and Caseiro, R. and Martins, P. and Batista, J.}, +journal = {Pattern Analysis and Machine Intelligence, IEEE Transactions on}, +year = {2015} +``` + + +[3] +``` +@inproceedings{danelljan2014dsst, +title={Accurate Scale Estimation for Robust Visual Tracking}, +author={Danelljan, Martin and H{\"a}ger, Gustav and Khan, Fahad Shahbaz and Felsberg, Michael}, +booktitle={Proceedings of the British Machine Vision Conference BMVC}, +year={2014}} +``` + +[4] +``` +@inproceedings{bolme2010mosse, +author={Bolme, David S. and Beveridge, J. Ross and Draper, Bruce A. and Yui Man Lui}, +title={Visual Object Tracking using Adaptive Correlation Filters}, +booktitle={Conference on Computer Vision and Pattern Recognition (CVPR)}, +year={2010}} +``` + +[5] +``` +@misc{PMT, +author = {Piotr Doll\'ar}, +title = {{P}iotr's {C}omputer {V}ision {M}atlab {T}oolbox ({PMT})}, +howpublished = {\url{http://vision.ucsd.edu/~pdollar/toolbox/doc/index.html}}} +``` + +[6] +``` +@article{lsvm-pami, +title = "Object Detection with Discriminatively Trained Part Based Models", +author = "Felzenszwalb, P. F. and Girshick, R. B. and McAllester, D. and Ramanan, D.", +journal = "IEEE Transactions on Pattern Analysis and Machine Intelligence", +year = "2010", volume = "32", number = "9", pages = "1627--1645"} +``` diff --git a/performance_report.pdf b/performance_report.pdf new file mode 100644 index 0000000..233e4b5 Binary files /dev/null and b/performance_report.pdf differ diff --git a/src/3rdparty/cf_tracking/.gitignore b/src/3rdparty/cf_tracking/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/src/3rdparty/cf_tracking/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/src/3rdparty/cf_tracking/CMakeLists.txt b/src/3rdparty/cf_tracking/CMakeLists.txt new file mode 100644 index 0000000..7d97ed9 --- /dev/null +++ b/src/3rdparty/cf_tracking/CMakeLists.txt @@ -0,0 +1,56 @@ +set(CF_CV_EXT "src/3rdparty/cv_ext") +set(CF_PIOTR_DIR "src/3rdparty/piotr/") + +set(CF_HEADER_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/${CF_CV_EXT} + ${CMAKE_CURRENT_SOURCE_DIR}/${CF_PIOTR_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/${CF_PIOTR_DIR}/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/cf_libs/kcf + ${CMAKE_CURRENT_SOURCE_DIR}/src/cf_libs/dsst + ${CMAKE_CURRENT_SOURCE_DIR}/src/cf_libs/common + PARENT_SCOPE) + +set(CF_PIOTR_SOURCES + ${CF_PIOTR_DIR}/src/gradientMex.cpp + ${CF_PIOTR_DIR}/gradientMex.hpp + ${CF_PIOTR_DIR}/src/sse.hpp + ${CF_PIOTR_DIR}/src/wrappers.hpp) + +set(CF_LIB_COMMON_SOURCES + src/cf_libs/common/feature_channels.hpp + src/cf_libs/common/mat_consts.hpp + src/cf_libs/common/math_helper.hpp + src/cf_libs/common/math_helper.cpp + src/cf_libs/common/cf_tracker.hpp + src/cf_libs/common/tracker_debug.hpp + src/cf_libs/common/scale_estimator.hpp + src/cf_libs/common/cv_ext.hpp + ${CF_CV_EXT}/shift.cpp + ${CF_CV_EXT}/shift.hpp + ${CF_CV_EXT}/math_spectrums.cpp + ${CF_CV_EXT}/math_spectrums.hpp + ${CF_PIOTR_SOURCES}) + +set(CF_SOURCES_ + src/cf_libs/dsst/dsst_debug.hpp + src/cf_libs/dsst/dsst_tracker.hpp + src/cf_libs/kcf/kcf_debug.hpp + src/cf_libs/kcf/kcf_tracker.hpp + ${CF_LIB_COMMON_SOURCES} + ) + +function(PREFIX prefix list_) + SET(tmp_list) + + foreach(SOURCE_FILE ${${list_}}) + list(APPEND tmp_list "${prefix}${SOURCE_FILE}") + endforeach(SOURCE_FILE) + + set(${list_} ${tmp_list} PARENT_SCOPE) +endfunction(PREFIX) + +PREFIX("${CMAKE_CURRENT_SOURCE_DIR}/" "CF_SOURCES_") +set(CF_SOURCES ${CF_SOURCES_} PARENT_SCOPE) +# message(STATUS ${CF_SOURCES_}) + + diff --git a/src/3rdparty/cf_tracking/README.md b/src/3rdparty/cf_tracking/README.md new file mode 100644 index 0000000..787c427 --- /dev/null +++ b/src/3rdparty/cf_tracking/README.md @@ -0,0 +1,128 @@ +# Introduction + +This repository provides C++ implementations for two correlation filter-based trackers. The code implements modified versions of the +visual trackers proposed in [1] and [2]: +* KCFcpp: This tracker is a C++ port of the Matlab implementation of the kernelized correlation filter (KCF) tracker proposed in [1]. Project webpage: http://home.isr.uc.pt/~henriques/circulant/ KCFcpp uses as default scale adaption the 1D scale filter proposed in [2]. In addition, a fixed template size, +the subpixel/subcell response peak estimation, and the model update from [3] is used as in the KCF version used by Henriques et al. in the VOT challenge 2014 (http://votchallenge.net/vot2014/). The scale adaption used by Henriques et al. in the VOT challenge 2014 is available as option. +* DSSTcpp: This tracker is a C++ port of the Matlab implementation of the discriminative scale space tracker (DSST) proposed in [2]. The default settings +use a fixed template size and the subpixel/cell response peak estimation as in +the KCF version. Project webpage: http://www.cvl.isy.liu.se/en/research/objrec/visualtracking/scalvistrack/index.html + +Both implementations use the FHOG features proposed in [4]. +More specifically, the FHOG implementation from [5] is used. +Both trackers offer the option to use the target +loss detection proposed in [6]. + + + + +# Build +### Dependencies +* C++11 +* OpenCV 3.0 +* CMake +* SSE2-capable CPU + +Compilation has been tested on Windows 7 with Visual Studio 2013 Ultimate, +on Windows 8.1 with Visual Studio 2013 Community and on Ubuntu 14.04 with g++. + +### Windows 7 +* Set environment variables according to [OpenCV Setup - Environment Variables](http://docs.opencv.org/doc/tutorials/introduction/windows_install/windows_install.html#windowssetpathandenviromentvariable) +* Launch cmake-gui, create a build folder and configure. +* Open CfTracking.sln in Visual Studio and compile the projects DSSTcpp and KCFcpp. + +### Ubuntu 14.04 +* Install OpenCV 3.0 and CMake. +* Configure and compile: +``` +mkdir /build +cd /build +cmake ../ +make -j 8 +``` + +# Usage +* To track images from a webcam, simply launch DSSTcpp(.exe) or KCFcpp(.exe) and +mark an object with a rectangle. +* To pass a predefined bounding box, use the `-b x,y,w,h` command line switch. Boxes +are expected to use images starting at position 0,0. +* To track an image sequence or video, copy the contents of `/sample/*` to your build/release folder and run the batch/sh file. +The example launch scripts are brief and explain the trackers' usage. If you run the tracker from Windows cmd, use only one +% sign to specify the naming convention of the image sequence. +* To enable target loss detection, run the tracker with the `--para_enable_tracking_loss` command line switch. +* To achieve tracking performance as close to the original Matlab implementations as possible, run the trackers with the `--original_version` command line switch. +While the trackers are implemented closely to their original Matlab implementations, +implementation differences do still exist (even with the `--original_version` switch) and the tracking performance of the C++ implementations +may deviate from their original Matlab implementations. +* To see a full list of available options, run the trackers with `--help` command line switch. + + +# Commercial Use (US) +The code using linear correlation filters may be affected by a US patent. If you want to use this code commercially in the US please refer to http://www.cs.colostate.edu/~vision/ocof_toolset_2012/index.php for possible patent claims. + + +# Contributors +Luka Cehovin: Equalize FHOG performance on AMD and Intel CPUs + + +## 3rdparty libraries used: +* Piotr's Matlab Toolbox http://vision.ucsd.edu/~pdollar/toolbox/doc/ +* OpenCV http://opencv.org/ +* tclap http://tclap.sourceforge.net/ + +## References +If you reuse this code for a scientific publication, please cite the related publications (dependent on what parts of the code you reuse): + +[1] +``` +@article{henriques2015tracking, +title = {High-Speed Tracking with Kernelized Correlation Filters}, +author = {Henriques, J. F. and Caseiro, R. and Martins, P. and Batista, J.}, +journal = {Pattern Analysis and Machine Intelligence, IEEE Transactions on}, +year = {2015} +``` + + +[2] +``` +@inproceedings{danelljan2014dsst, +title={Accurate Scale Estimation for Robust Visual Tracking}, +author={Danelljan, Martin and H{\"a}ger, Gustav and Khan, Fahad Shahbaz and Felsberg, Michael}, +booktitle={Proceedings of the British Machine Vision Conference BMVC}, +year={2014}} +``` + +[3] +``` +@inproceedings{danelljan2014colorattributes, +title={Adaptive Color Attributes for Real-Time Visual Tracking}, +author={Danelljan, Martin and Khan, Fahad Shahbaz and Felsberg, Michael and Weijer, Joost van de}, +booktitle={Conference on Computer Vision and Pattern Recognition (CVPR)}, +year={2014}} +``` + +[4] +``` +@article{lsvm-pami, +title = "Object Detection with Discriminatively Trained Part Based Models", +author = "Felzenszwalb, P. F. and Girshick, R. B. and McAllester, D. and Ramanan, D.", +journal = "IEEE Transactions on Pattern Analysis and Machine Intelligence", +year = "2010", volume = "32", number = "9", pages = "1627--1645"} +``` + +[5] +``` +@misc{PMT, +author = {Piotr Doll\'ar}, +title = {{P}iotr's {C}omputer {V}ision {M}atlab {T}oolbox ({PMT})}, +howpublished = {\url{http://vision.ucsd.edu/~pdollar/toolbox/doc/index.html}}} +``` + +[6] +``` +@inproceedings{bolme2010mosse, +author={Bolme, David S. and Beveridge, J. Ross and Draper, Bruce A. and Yui Man Lui}, +title={Visual Object Tracking using Adaptive Correlation Filters}, +booktitle={Conference on Computer Vision and Pattern Recognition (CVPR)}, +year={2010}} +``` diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.cpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.cpp new file mode 100644 index 0000000..17d24e5 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.cpp @@ -0,0 +1,114 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +//M*/ + +/* +// Original file: https://github.com/Itseez/opencv_contrib/blob/292b8fa6aa403fb7ad6d2afadf4484e39d8ca2f1/modules/tracking/samples/tracker.cpp +// + Author: Klaus Haag +// * Refactor file: Move target selection to separate class/file +*/ + +#include "init_box_selector.hpp" + +void InitBoxSelector::onMouse(int event, int x, int y, int, void*) +{ + if (!selectObject) + { + switch (event) + { + case cv::EVENT_LBUTTONDOWN: + //set origin of the bounding box + startSelection = true; + initBox.x = x; + initBox.y = y; + break; + case cv::EVENT_LBUTTONUP: + //set width and height of the bounding box + initBox.width = std::abs(x - initBox.x); + initBox.height = std::abs(y - initBox.y); + startSelection = false; + selectObject = true; + break; + case cv::EVENT_MOUSEMOVE: + if (startSelection && !selectObject) + { + //draw the bounding box + cv::Mat currentFrame; + image.copyTo(currentFrame); + cv::rectangle(currentFrame, cv::Point((int)initBox.x, (int)initBox.y), cv::Point(x, y), cv::Scalar(255, 0, 0), 2, 1); + cv::imshow(windowTitle.c_str(), currentFrame); + } + break; + } + } +} + +bool InitBoxSelector::selectBox(cv::Mat& frame, cv::Rect& initBox) +{ + frame.copyTo(image); + startSelection = false; + selectObject = false; + cv::imshow(windowTitle.c_str(), image); + cv::setMouseCallback(windowTitle.c_str(), onMouse, 0); + + while (selectObject == false) + { + char c = (char)cv::waitKey(10); + + if (c == 27) + return false; + } + + initBox = InitBoxSelector::initBox; + cv::setMouseCallback(windowTitle.c_str(), 0, 0); + cv::destroyWindow(windowTitle.c_str()); + return true; +} + +const std::string InitBoxSelector::windowTitle = "Draw Bounding Box"; +bool InitBoxSelector::startSelection = false; +bool InitBoxSelector::selectObject = false; +cv::Mat InitBoxSelector::image; +cv::Rect InitBoxSelector::initBox; diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.hpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.hpp new file mode 100644 index 0000000..7b9a515 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.hpp @@ -0,0 +1,73 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +//M*/ + +/* +// Original file: https://github.com/Itseez/opencv_contrib/blob/292b8fa6aa403fb7ad6d2afadf4484e39d8ca2f1/modules/tracking/samples/tracker.cpp +// + Author: Klaus Haag +// * Refactor file: Move target selection to separate class/file +*/ + +#ifndef INIT_BOX_SELECTOR_HPP_ +#define INIT_BOX_SELECTOR_HPP_ + +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/opencv.hpp" + +class InitBoxSelector +{ +public: + static bool selectBox(cv::Mat& frame, cv::Rect& initBox); + +private: + static void onMouse(int event, int x, int y, int, void*); + static bool startSelection; + static bool selectObject; + static cv::Rect initBox; + static cv::Mat image; + static const std::string windowTitle; +}; + +#endif /* INIT_BOX_SELECTOR_H_ */ diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.cpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.cpp new file mode 100644 index 0000000..e6cae7d --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.cpp @@ -0,0 +1,278 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of Intel Corporation may not 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 Intel Corporation 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. +//M*/ + +// Author: Intel +// Original file: https://github.com/Itseez/opencv/blob/46a6f70d88bf816525a3ded80e69237d1960152f/modules/core/src/dxt.cpp +// + Klaus Haag (converted mulSpectrums to divSpectrums) + +// TODO: +// * vectorize +// * check precision errors for float (casting to double +// may not be necessary) +// * check inconsistency for float for real parts only +// (not casted to double) +// * needs more testing (conjB == true) is untested + +#include "math_spectrums.hpp" + +void divSpectrums(cv::InputArray _numeratorA, cv::InputArray _denominatorB, + cv::OutputArray _dst, int flags, bool conjB) +{ + cv::Mat srcA = _numeratorA.getMat(), srcB = _denominatorB.getMat(); + int depth = srcA.depth(), cn = srcA.channels(), type = srcA.type(); + int rows = srcA.rows, cols = srcA.cols; + int j, k; + + CV_Assert(type == srcB.type() && srcA.size() == srcB.size()); + CV_Assert(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2); + + _dst.create(srcA.rows, srcA.cols, type); + cv::Mat dst = _dst.getMat(); + + bool is_1d = (flags & cv::DFT_ROWS) || (rows == 1 || (cols == 1 && + srcA.isContinuous() && srcB.isContinuous() && dst.isContinuous())); + + if (is_1d && !(flags & cv::DFT_ROWS)) + cols = cols + rows - 1, rows = 1; + + // complex number representation + // http://mathworld.wolfram.com/ComplexDivision.html + // (a,b) / (c,d) = ((ac+bd)/v , (bc-ad)/v) + // with v = (c^2 + d^2) + double a = 0.0, b = 0.0, c = 0.0, d = 0.0, v = 0.0; + + int ncols = cols*cn; + int j0 = cn == 1; + int j1 = ncols - (cols % 2 == 0 && cn == 1); + + if (depth == CV_32F) + { + const float* dataA = srcA.ptr(); + const float* dataB = srcB.ptr(); + float* dataC = dst.ptr(); + + size_t stepA = srcA.step / sizeof(dataA[0]); + size_t stepB = srcB.step / sizeof(dataB[0]); + size_t stepC = dst.step / sizeof(dataC[0]); + + if (!is_1d && cn == 1) + { + // even: one loop execution + // odd: two loop executions + for (k = 0; k < (cols % 2 ? 1 : 2); k++) + { + if (k == 1) + dataA += cols - 1, dataB += cols - 1, dataC += cols - 1; + + // the following 2 elements do not have an imaginary part + // TODO: check precision + dataC[0] = dataA[0] / dataB[0]; + + if (rows % 2 == 0) + dataC[(rows - 1)*stepC] = dataA[(rows - 1)*stepA] / dataB[(rows - 1)*stepB]; + + if (!conjB) + { + for (j = 1; j <= rows - 2; j += 2) + { + a = (double)dataA[j*stepA]; + b = (double)dataA[(j + 1)*stepA]; + c = (double)dataB[j*stepB]; + d = (double)dataB[(j + 1)*stepB]; + v = (c*c) + (d*d); + + dataC[j*stepC] = (float)((a * c + b * d) / v); + dataC[(j + 1)*stepC] = (float)((b * c - a * d) / v); + } + } + else + { + for (j = 1; j <= rows - 2; j += 2) + { + a = (double)dataA[j*stepA]; + b = -(double)dataA[(j + 1)*stepA]; + c = (double)dataB[j*stepB]; + d = -(double)dataB[(j + 1)*stepB]; + v = (c*c) + (d*d); + + dataC[j*stepC] = (float)((a * c + b * d) / v); + dataC[(j + 1)*stepC] = (float)((b * c - a * d) / v); + } + } + + if (k == 1) + dataA -= cols - 1, dataB -= cols - 1, dataC -= cols - 1; + } + } + + for (; rows--; dataA += stepA, dataB += stepB, dataC += stepC) + { + if (is_1d && cn == 1) + { + // first and last element in row -> no imaginary part + dataC[0] = dataA[0] / dataB[0]; + + if (cols % 2 == 0) + dataC[j1] = dataA[j1] / dataB[j1]; + } + + if (!conjB) + { + for (j = j0; j < j1; j += 2) + { + a = (double)dataA[j]; + b = (double)dataA[j + 1]; + c = (double)dataB[j]; + d = (double)dataB[j + 1]; + v = (c*c) + (d*d); + dataC[j] = (float)((a * c + b * d) / v); + dataC[j + 1] = (float)((b * c - a * d) / v); + } + } + else + { + for (j = j0; j < j1; j += 2) + { + a = (double)dataA[j]; + b = -(double)dataA[j + 1]; + c = (double)dataB[j]; + d = -(double)dataB[j + 1]; + v = (c*c) + (d*d); + dataC[j] = (float)((a * c + b * d) / v); + dataC[j + 1] = (float)((b * c - a * d) / v); + } + } + } + } + else + { + const double* dataA = srcA.ptr(); + const double* dataB = srcB.ptr(); + double* dataC = dst.ptr(); + + size_t stepA = srcA.step / sizeof(dataA[0]); + size_t stepB = srcB.step / sizeof(dataB[0]); + size_t stepC = dst.step / sizeof(dataC[0]); + + if (!is_1d && cn == 1) + { + for (k = 0; k < (cols % 2 ? 1 : 2); k++) + { + if (k == 1) + dataA += cols - 1, dataB += cols - 1, dataC += cols - 1; + + dataC[0] = dataA[0] / dataB[0]; + + if (rows % 2 == 0) + dataC[(rows - 1)*stepC] = dataA[(rows - 1)*stepA] / dataB[(rows - 1)*stepB]; + + if (!conjB) + { + for (j = 1; j <= rows - 2; j += 2) + { + a = dataA[j*stepA]; + b = dataA[(j + 1)*stepA]; + c = dataB[j*stepB]; + d = dataB[(j + 1)*stepB]; + v = (c*c) + (d*d); + + dataC[j*stepC] = (a * c + b * d) / v; + dataC[(j + 1)*stepC] = (b * c - a * d) / v; + } + } + else + { + for (j = 1; j <= rows - 2; j += 2) + { + a = dataA[j*stepA]; + b = -dataA[(j + 1)*stepA]; + c = dataB[j*stepB]; + d = -dataB[(j + 1)*stepB]; + v = (c*c) + (d*d); + + dataC[j*stepC] = (a * c + b * d) / v; + dataC[(j + 1)*stepC] = (b * c - a * d) / v; + } + } + + if (k == 1) + dataA -= cols - 1, dataB -= cols - 1, dataC -= cols - 1; + } + } + + for (; rows--; dataA += stepA, dataB += stepB, dataC += stepC) + { + if (is_1d && cn == 1) + { + dataC[0] = dataA[0] / dataB[0]; + + if (cols % 2 == 0) + dataC[j1] = dataA[j1] / dataB[j1]; + } + + if (!conjB) + { + for (j = j0; j < j1; j += 2) + { + a = dataA[j]; + b = dataA[j + 1]; + c = dataB[j]; + d = dataB[j + 1]; + v = (c*c) + (d*d); + dataC[j] = (a * c + b * d) / v; + dataC[j + 1] = (b * c - a * d) / v; + } + } + else + { + for (j = j0; j < j1; j += 2) + { + a = dataA[j]; + b = -dataA[j + 1]; + c = dataB[j]; + d = -dataB[j + 1]; + v = (c*c) + (d*d); + dataC[j] = (a * c + b * d) / v; + dataC[j + 1] = (b * c - a * d) / v; + } + } + } + } +} diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.hpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.hpp new file mode 100644 index 0000000..16bb879 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.hpp @@ -0,0 +1,198 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of Intel Corporation may not 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 Intel Corporation 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. +//M*/ + +// Author: Intel +// Original file: https://github.com/Itseez/opencv/blob/46a6f70d88bf816525a3ded80e69237d1960152f/modules/core/src/dxt.cpp +// + Klaus Haag: +// * Converted mulSpectrums to divSpectrums +// * Converted mulSpectrums to addRealToSpectrum +// * Converted mulSpectrums to sumRealOfSpectrum +// + +#ifndef MATH_SPECTRUMS_HPP_ +#define MATH_SPECTRUMS_HPP_ + +#include + +void divSpectrums(cv::InputArray _numeratorA, cv::InputArray _denominatorB, + cv::OutputArray _dst, int flags = 0, bool conjB = false); + +template +cv::Mat addRealToSpectrum(T summand, cv::InputArray _numeratorA, int flags = 0) +{ + cv::Mat srcA = _numeratorA.getMat(); + int cn = srcA.channels(), type = srcA.type(); + int rows = srcA.rows, cols = srcA.cols; + int j, k; + + CV_Assert(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2); + + cv::Mat dst; + dst.create(srcA.rows, srcA.cols, type); + + bool is_1d = (flags & cv::DFT_ROWS) || (rows == 1 || (cols == 1 && + srcA.isContinuous() && dst.isContinuous())); + + if (is_1d && !(flags & cv::DFT_ROWS)) + cols = cols + rows - 1, rows = 1; + + int ncols = cols*cn; + int j0 = cn == 1; + int j1 = ncols - (cols % 2 == 0 && cn == 1); + + const T* dataA = srcA.ptr(); + T* dataC = dst.ptr(); + + size_t stepA = srcA.step / sizeof(dataA[0]); + size_t stepC = dst.step / sizeof(dataC[0]); + + if (!is_1d && cn == 1) + { + for (k = 0; k < (cols % 2 ? 1 : 2); k++) + { + if (k == 1) + dataA += cols - 1, dataC += cols - 1; + + dataC[0] = dataA[0] + summand; + + if (rows % 2 == 0) + dataC[(rows - 1)*stepC] = dataA[(rows - 1)*stepA] + summand; + + for (j = 1; j <= rows - 2; j += 2) + { + dataC[j*stepC] = dataA[j*stepA] + summand; + dataC[(j + 1)*stepC] = dataA[(j + 1)*stepA]; + } + + if (k == 1) + dataA -= cols - 1, dataC -= cols - 1; + } + } + + for (; rows--; dataA += stepA, dataC += stepC) + { + if (is_1d && cn == 1) + { + dataC[0] = dataA[0] + summand; + + if (cols % 2 == 0) + dataC[j1] = dataA[j1] + summand; + } + + for (j = j0; j < j1; j += 2) + { + dataC[j] = dataA[j] + summand; + dataC[j + 1] = dataA[j + 1]; + } + } + + return dst; +} + +template +T sumRealOfSpectrum(cv::InputArray _numeratorA, int flags = 0) +{ + cv::Mat srcA = _numeratorA.getMat(); + T sum_ = 0; + int cn = srcA.channels(), type = srcA.type(); + int rows = srcA.rows, cols = srcA.cols; + int j, k; + CV_Assert(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2); + + bool is_1d = (flags & cv::DFT_ROWS) || (rows == 1 || (cols == 1 && + srcA.isContinuous())); + + if (is_1d && !(flags & cv::DFT_ROWS)) + cols = cols + rows - 1, rows = 1; + + T multiplier = 1; + + if (cn == 1) + multiplier = 2; + + int ncols = cols*cn; + int j0 = cn == 1; + int j1 = ncols - (cols % 2 == 0 && cn == 1); + + const T* dataA = srcA.ptr(); + size_t stepA = srcA.step / sizeof(dataA[0]); + + if (!is_1d && cn == 1) + { + for (k = 0; k < (cols % 2 ? 1 : 2); k++) + { + if (k == 1) + dataA += cols - 1; + + sum_ += dataA[0]; + + if (rows % 2 == 0) + sum_ += dataA[(rows - 1)*stepA]; + + for (j = 1; j <= rows - 2; j += 2) + { + sum_ += multiplier * dataA[j*stepA]; + } + + if (k == 1) + dataA -= cols - 1; + } + } + + for (; rows--; dataA += stepA) + { + if (is_1d && cn == 1) + { + sum_ += dataA[0]; + + if (cols % 2 == 0) + sum_ += dataA[j1]; + } + + for (j = j0; j < j1; j += 2) + { + sum_ += multiplier * dataA[j]; + } + } + + return sum_; +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/psr.hpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/psr.hpp new file mode 100644 index 0000000..898699f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/psr.hpp @@ -0,0 +1,85 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +//M*/ + +/* +// + Author: Klaus Haag +// * The PSR was proposed in [1]. This file is based on PSR calculation calculation from: +// * https://github.com/Itseez/opencv/blob/d279f127c1a0e28951bfdbba5516edc1bf0a0965/samples/python2/mosse.py +// * Set values below 0 to 0 in the response for the sidelobe calculation + +// References: +// [1] D. Bolme, et al., +// “Visual Object Tracking using Adaptive Correlation Filters,” +// in Proc. CVPR, 2010. +*/ + +#ifndef PSR_HPP_ +#define PSR_HPP_ + +#include + +template inline +T calcPsr(const cv::Mat &response, const cv::Point2i &maxResponseIdx, const int deletionRange, T& peakValue) +{ + peakValue = response.at(maxResponseIdx); + double psrClamped = 0; + + cv::Mat sideLobe = response.clone(); + sideLobe.setTo(0, sideLobe < 0); + + cv::rectangle(sideLobe, + cv::Point2i(maxResponseIdx.x - deletionRange, maxResponseIdx.y - deletionRange), + cv::Point2i(maxResponseIdx.x + deletionRange, maxResponseIdx.y + deletionRange), + cv::Scalar(0), cv::FILLED); + + cv::Scalar mean_; + cv::Scalar std_; + cv::meanStdDev(sideLobe, mean_, std_); + psrClamped = (peakValue - mean_[0]) / (std_[0] + std::numeric_limits::epsilon()); + return static_cast(psrClamped); +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.cpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.cpp new file mode 100644 index 0000000..d1784a0 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.cpp @@ -0,0 +1,148 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2012, Willow Garage, 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 Willow Garage, 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. + * + * File: shift.cpp + * Author: Hilton Bristow + * Created: Aug 23, 2012 + * + Author: Klaus Haag (split into header/source file) + */ + +//#ifndef SHIFT_HPP_ +//#define SHIFT_HPP_ + +#include +#include +#include +#include "shift.hpp" + +/*! @brief shift the values in a matrix by an (x,y) offset + * + * Given a matrix and an integer (x,y) offset, the matrix will be shifted + * such that: + * + * src(a,b) ---> dst(a+y,b+x) + * + * In the case of a non-integer offset, (e.g. cv::Point2f(-2.1, 3.7)), + * the shift will be calculated with subpixel precision using bilinear + * interpolation. + * + * All valid OpenCV datatypes are supported. If the source datatype is + * fixed-point, and a non-integer offset is supplied, the output will + * be a floating point matrix to preserve subpixel accuracy. + * + * All border types are supported. If no border type is supplied, the + * function defaults to BORDER_CONSTANT with 0-padding. + * + * The function supports in-place operation. + * + * Some common examples are provided following: + * \code + * // read an image from file + * Mat mat = imread(filename); + * Mat dst; + * + * // Perform Matlab-esque 'circshift' in-place + * shift(mat, mat, Point(5, 5), BORDER_WRAP); + * + * // Perform shift with subpixel accuracy, padding the missing pixels with 1s + * // NOTE: if mat is of type CV_8U, then it will be converted to type CV_32F + * shift(mat, mat, Point2f(-13.7, 3.28), BORDER_CONSTANT, 1); + * + * // Perform subpixel shift, preserving the boundary values + * shift(mat, dst, Point2f(0.093, 0.125), BORDER_REPLICATE); + * + * // Perform a vanilla shift, integer offset, very fast + * shift(mat, dst, Point(2, 2)); + * \endcode + * + * @param src the source matrix + * @param dst the destination matrix, can be the same as source + * @param delta the amount to shift the matrix in (x,y) coordinates. Can be + * integer of floating point precision + * @param fill the method used to fill the null entries, defaults to BORDER_CONSTANT + * @param value the value of the null entries if the fill type is BORDER_CONSTANT + */ + +void shift(const cv::Mat& src, cv::Mat& dst, cv::Point2f delta, int fill, cv::Scalar value) { + // error checking + CV_Assert(fabs(delta.x) < src.cols && fabs(delta.y) < src.rows); + + // split the shift into integer and subpixel components + cv::Point2i deltai(static_cast(ceil(delta.x)), static_cast(ceil(delta.y))); + cv::Point2f deltasub(fabs(delta.x - deltai.x), fabs(delta.y - deltai.y)); + + // INTEGER SHIFT + // first create a border around the parts of the Mat that will be exposed + int t = 0, b = 0, l = 0, r = 0; + if (deltai.x > 0) l = deltai.x; + if (deltai.x < 0) r = -deltai.x; + if (deltai.y > 0) t = deltai.y; + if (deltai.y < 0) b = -deltai.y; + cv::Mat padded; + cv::copyMakeBorder(src, padded, t, b, l, r, fill, value); + + // SUBPIXEL SHIFT + float eps = std::numeric_limits::epsilon(); + if (deltasub.x > eps || deltasub.y > eps) { + switch (src.depth()) { + case CV_32F: + { + cv::Matx dx(1 - deltasub.x, deltasub.x); + cv::Matx dy(1 - deltasub.y, deltasub.y); + sepFilter2D(padded, padded, -1, dx, dy, cv::Point(0, 0), 0, cv::BORDER_CONSTANT); + break; + } + case CV_64F: + { + cv::Matx dx(1 - deltasub.x, deltasub.x); + cv::Matx dy(1 - deltasub.y, deltasub.y); + sepFilter2D(padded, padded, -1, dx, dy, cv::Point(0, 0), 0, cv::BORDER_CONSTANT); + break; + } + default: + { + cv::Matx dx(1 - deltasub.x, deltasub.x); + cv::Matx dy(1 - deltasub.y, deltasub.y); + padded.convertTo(padded, CV_32F); + sepFilter2D(padded, padded, CV_32F, dx, dy, cv::Point(0, 0), 0, cv::BORDER_CONSTANT); + break; + } + } + } + + // construct the region of interest around the new matrix + cv::Rect roi = cv::Rect(std::max(-deltai.x, 0), std::max(-deltai.y, 0), 0, 0) + src.size(); + dst = padded(roi); +} + +//#endif /* SHIFT_HPP_ */ diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.hpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.hpp new file mode 100644 index 0000000..a683486 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.hpp @@ -0,0 +1,49 @@ +/* +* Software License Agreement (BSD License) +* +* Copyright (c) 2012, Willow Garage, 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 Willow Garage, 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. +* +* File: shift.hpp +* Author: Hilton Bristow +* Created: Aug 23, 2012 +* + Author: Klaus Haag (split into header/source file) +*/ + +#ifndef SHIFT_HPP_ +#define SHIFT_HPP_ + +#include + +void shift(const cv::Mat& src, cv::Mat& dst, cv::Point2f delta, + int fill = cv::BORDER_CONSTANT, + cv::Scalar value = cv::Scalar(0, 0, 0, 0)); + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.cpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.cpp new file mode 100644 index 0000000..d9056c0 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.cpp @@ -0,0 +1,441 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +//M*/ + +/* +// Original file: https://github.com/Itseez/opencv_contrib/blob/292b8fa6aa403fb7ad6d2afadf4484e39d8ca2f1/modules/tracking/samples/tracker.cpp +// + Author: Klaus Haag +// * Refactor file: Split into files/classes +// * Replace command line arguments +// * Add a variety of additional features +*/ + +#include "tracker_run.hpp" + +#include +#include + +#include "init_box_selector.hpp" +#include "cf_tracker.hpp" + +using namespace cv; +using namespace std; +using namespace TCLAP; +using namespace cf_tracking; + +TrackerRun::TrackerRun(string windowTitle) : +_windowTitle(windowTitle), +_cmd(_windowTitle.c_str(), ' ', "0.1"), +_debug(0) +{ + _tracker = 0; +} + +TrackerRun::~TrackerRun() +{ + if (_resultsFile.is_open()) + _resultsFile.close(); + + if (_tracker) + { + delete _tracker; + _tracker = 0; + } +} + +Parameters TrackerRun::parseCmdArgs(int argc, const char** argv) +{ + Parameters paras; + + try{ + ValueArg deviceIdArg("c", "cam", "Camera device id", false, 0, "integer", _cmd); + ValueArg seqPathArg("s", "seq", "Path to sequence", false, "", "path", _cmd); + ValueArg expansionArg("i", "image_name_expansion", "image name expansion (only necessary for image sequences) ie. /%.05d.jpg", false, "", "string", _cmd); + ValueArg initBbArg("b", "box", "Init Bounding Box", false, "-1,-1,-1,-1", "x,y,w,h", _cmd); + SwitchArg noShowOutputSw("n", "no-show", "Don't show video", _cmd, false); + ValueArg outputPathArg("o", "out", "Path to output file", false, "", "file path", _cmd); + ValueArg imgExportPathArg("e", "export", "Path to output folder where the images will be saved with BB", false, "", "folder path", _cmd); + SwitchArg pausedSw("p", "paused", "Start paused", _cmd, false); + SwitchArg repeatSw("r", "repeat", "endless loop the same sequence", _cmd, false); + ValueArg startFrameArg("", "start_frame", "starting frame idx (starting at 1 for the first frame)", false, 1, "integer", _cmd); + SwitchArg dummySequenceSw("", "mock_sequence", "Instead of processing a regular sequence, a dummy sequence is used to evaluate run time performance.", _cmd, false); + _tracker = parseTrackerParas(_cmd, argc, argv); + + paras.device = deviceIdArg.getValue(); + paras.sequencePath = seqPathArg.getValue(); + string expansion = expansionArg.getValue(); + + size_t foundExpansion = expansion.find_first_of('.'); + + if (foundExpansion != string::npos) + expansion.erase(foundExpansion, 1); + + paras.expansion = expansion; + + paras.outputFilePath = outputPathArg.getValue(); + paras.imgExportPath = imgExportPathArg.getValue(); + paras.showOutput = !noShowOutputSw.getValue(); + paras.paused = pausedSw.getValue(); + paras.repeat = repeatSw.getValue(); + paras.startFrame = startFrameArg.getValue(); + + stringstream initBbSs(initBbArg.getValue()); + + double initBb[4]; + + for (int i = 0; i < 4; ++i) + { + string singleValueStr; + getline(initBbSs, singleValueStr, ','); + initBb[i] = static_cast(stod(singleValueStr.c_str())); + } + + paras.initBb = Rect_(initBb[0], initBb[1], initBb[2], initBb[3]); + + if (_debug != 0) + _debug->init(paras.outputFilePath + "_debug"); + + paras.isMockSequence = dummySequenceSw.getValue(); + } + catch (ArgException &argException) + { + cerr << "Command Line Argument Exception: " << argException.what() << endl; + exit(-1); + } + // TODO: properly check every argument and throw exceptions accordingly + catch (...) + { + cerr << "Command Line Argument Exception!" << endl; + exit(-1); + } + + return paras; +} + +bool TrackerRun::start(int argc, const char** argv) +{ + _paras = parseCmdArgs(argc, argv); + + while (true) + { + if (init() == false) + return false; + if (run() == false) + return false; + + if (!_paras.repeat || _exit) + break; + + _boundingBox = _paras.initBb; + _isTrackerInitialzed = false; + } + + return true; +} + +bool TrackerRun::init() +{ + ImgAcqParas imgAcqParas; + imgAcqParas.device = _paras.device; + imgAcqParas.expansionStr = _paras.expansion; + imgAcqParas.isMock = _paras.isMockSequence; + imgAcqParas.sequencePath = _paras.sequencePath; + _cap.open(imgAcqParas); + + if (!_cap.isOpened()) + { + cerr << "Could not open device/sequence/video!" << endl; + exit(-1); + } + + int startIdx = _paras.startFrame - 1; + + // HACKFIX: + //_cap.set(CV_CAP_PROP_POS_FRAMES, startIdx); + // OpenCV's _cap.set in combination with image sequences is + // currently bugged on Linux + // TODO: review when OpenCV 3.0 is stable + cv::Mat temp; + + for (int i = 0; i < startIdx; ++i) + _cap >> temp; + // HACKFIX END + + if (_paras.showOutput) + namedWindow(_windowTitle.c_str()); + + if (!_paras.outputFilePath.empty()) + { + _resultsFile.open(_paras.outputFilePath.c_str()); + + if (!_resultsFile.is_open()) + { + std::cerr << "Error: Unable to create results file: " + << _paras.outputFilePath.c_str() + << std::endl; + + return false; + } + + _resultsFile.precision(std::numeric_limits::digits10 - 4); + } + + if (_paras.initBb.width > 0 || _paras.initBb.height > 0) + { + _boundingBox = _paras.initBb; + _hasInitBox = true; + } + + _isPaused = _paras.paused; + _frameIdx = 0; + return true; +} + +bool TrackerRun::run() +{ + bool success = true; + + std::cout << "Switch pause with 'p'" << std::endl; + std::cout << "Step frame with 'c'" << std::endl; + std::cout << "Select new target with 'r'" << std::endl; + std::cout << "Update current tracker model at new location 't'" << std::endl; + std::cout << "Quit with 'ESC'" << std::endl; + + while (true) + { + success = update(); + + if (!success) + break; + } + + _cap.release(); + + return true; +} + +bool TrackerRun::update() +{ + int64 tStart = 0; + int64 tDuration = 0; + + if (!_isPaused || _frameIdx == 0 || _isStep) + { + _cap >> _image; + + if (_image.empty()) + return false; + + ++_frameIdx; + } + + if (!_isTrackerInitialzed) + { + if (!_hasInitBox) + { + Rect box; + + if (!InitBoxSelector::selectBox(_image, box)) + return false; + + _boundingBox = Rect_(static_cast(box.x), + static_cast(box.y), + static_cast(box.width), + static_cast(box.height)); + + _hasInitBox = true; + } + + tStart = getTickCount(); + _targetOnFrame = _tracker->reinit(_image, _boundingBox); + tDuration = getTickCount() - tStart; + + if (_targetOnFrame) + _isTrackerInitialzed = true; + } + else if (_isTrackerInitialzed && (!_isPaused || _isStep)) + { + _isStep = false; + + if (_updateAtPos) + { + Rect box; + + if (!InitBoxSelector::selectBox(_image, box)) + return false; + + _boundingBox = Rect_(static_cast(box.x), + static_cast(box.y), + static_cast(box.width), + static_cast(box.height)); + + _updateAtPos = false; + + std::cout << "UpdateAt_: " << _boundingBox << std::endl; + tStart = getTickCount(); + _targetOnFrame = _tracker->updateAt(_image, _boundingBox); + tDuration = getTickCount() - tStart; + + if (!_targetOnFrame) + std::cout << "Target not found!" << std::endl; + } + else + { + tStart = getTickCount(); + _targetOnFrame = _tracker->update(_image, _boundingBox); + tDuration = getTickCount() - tStart; + } + } + + double fps = static_cast(getTickFrequency() / tDuration); + printResults(_boundingBox, _targetOnFrame, fps); + + if (_paras.showOutput) + { + Mat hudImage; + _image.copyTo(hudImage); + rectangle(hudImage, _boundingBox, Scalar(0, 0, 255), 2); + Point_ center; + center.x = _boundingBox.x + _boundingBox.width / 2; + center.y = _boundingBox.y + _boundingBox.height / 2; + circle(hudImage, center, 3, Scalar(0, 0, 255), 2); + + stringstream ss; + ss << "FPS: " << fps; + putText(hudImage, ss.str(), Point(20, 20), FONT_HERSHEY_TRIPLEX, 0.5, Scalar(255, 0, 0)); + + ss.str(""); + ss.clear(); + ss << "#" << _frameIdx; + putText(hudImage, ss.str(), Point(hudImage.cols - 60, 20), FONT_HERSHEY_TRIPLEX, 0.5, Scalar(255, 0, 0)); + + if (_debug != 0) + _debug->printOnImage(hudImage); + + if (!_targetOnFrame) + { + cv::Point_ tl = _boundingBox.tl(); + cv::Point_ br = _boundingBox.br(); + + line(hudImage, tl, br, Scalar(0, 0, 255)); + line(hudImage, cv::Point_(tl.x, br.y), + cv::Point_(br.x, tl.y), Scalar(0, 0, 255)); + } + + imshow(_windowTitle.c_str(), hudImage); + + if (!_paras.imgExportPath.empty()) + { + stringstream ssi; + ssi << setfill('0') << setw(5) << _frameIdx << ".png"; + std::string imgPath = _paras.imgExportPath + ssi.str(); + + try + { + imwrite(imgPath, hudImage); + } + catch (runtime_error& runtimeError) + { + cerr << "Could not write output images: " << runtimeError.what() << endl; + } + } + + char c = (char)waitKey(10); + + if (c == 27) + { + _exit = true; + return false; + } + + switch (c) + { + case 'p': + _isPaused = !_isPaused; + break; + case 'c': + _isStep = true; + break; + case 'r': + _hasInitBox = false; + _isTrackerInitialzed = false; + break; + case 't': + _updateAtPos = true; + break; + default: + ; + } + } + + return true; +} + +void TrackerRun::printResults(const cv::Rect_& boundingBox, bool isConfident, double fps) +{ + if (_resultsFile.is_open()) + { + if (boundingBox.width > 0 && boundingBox.height > 0 && isConfident) + { + _resultsFile << boundingBox.x << "," + << boundingBox.y << "," + << boundingBox.width << "," + << boundingBox.height << "," + << fps << std::endl; + } + else + { + _resultsFile << "NaN, NaN, NaN, NaN, " << fps << std::endl; + } + + if (_debug != 0) + _debug->printToFile(); + } +} + +void TrackerRun::setTrackerDebug(cf_tracking::TrackerDebug* debug) +{ + _debug = debug; +} diff --git a/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.hpp b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.hpp new file mode 100644 index 0000000..f0a06a2 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.hpp @@ -0,0 +1,118 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +// Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +// Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +// Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +// Copyright (C) 2015, OpenCV Foundation, all rights reserved. +// Copyright (C) 2015, Itseez Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +//M*/ + +/* +// Original file: https://github.com/Itseez/opencv_contrib/blob/292b8fa6aa403fb7ad6d2afadf4484e39d8ca2f1/modules/tracking/samples/tracker.cpp +// + Author: Klaus Haag +// * Refactor file: Move target selection to separate class/file +// * Replace command line argumnets +// * Change tracker calling code +// * Add a variety of additional features +*/ + +#ifndef TRACKER_RUN_HPP_ +#define TRACKER_RUN_HPP_ + +#include +#include +#include +#include "cf_tracker.hpp" +#include "tracker_debug.hpp" +#include "dsst_tracker.hpp" +#include "image_acquisition.hpp" + +struct Parameters{ + std::string sequencePath; + std::string outputFilePath; + std::string imgExportPath; + std::string expansion; + cv::Rect initBb; + int device; + int startFrame; + bool showOutput; + bool paused; + bool repeat; + bool isMockSequence; +}; + +class TrackerRun +{ +public: + TrackerRun(std::string windowTitle); + virtual ~TrackerRun(); + bool start(int argc, const char** argv); + void setTrackerDebug(cf_tracking::TrackerDebug* debug); + +private: + Parameters parseCmdArgs(int argc, const char** argv); + bool init(); + bool run(); + bool update(); + void printResults(const cv::Rect_& boundingBox, bool isConfident, double fps); + +protected: + virtual cf_tracking::CfTracker* parseTrackerParas(TCLAP::CmdLine& cmd, int argc, const char** argv) = 0; +private: + cv::Mat _image; + cf_tracking::CfTracker* _tracker; + std::string _windowTitle; + Parameters _paras; + cv::Rect_ _boundingBox; + ImageAcquisition _cap; + std::ofstream _resultsFile; + TCLAP::CmdLine _cmd; + cf_tracking::TrackerDebug* _debug; + int _frameIdx; + bool _isPaused = false; + bool _isStep = false; + bool _exit = false; + bool _hasInitBox = false; + bool _isTrackerInitialzed = false; + bool _targetOnFrame = false; + bool _updateAtPos = false; +}; + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/piotr/README.md b/src/3rdparty/cf_tracking/src/3rdparty/piotr/README.md new file mode 100644 index 0000000..c8f9f0b --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/piotr/README.md @@ -0,0 +1,3 @@ +This module provides the FHOG implementation from +http://vision.ucsd.edu/~pdollar/toolbox/doc/ +with an OpenCV integration. diff --git a/src/3rdparty/cf_tracking/src/3rdparty/piotr/gradientMex.hpp b/src/3rdparty/cf_tracking/src/3rdparty/piotr/gradientMex.hpp new file mode 100644 index 0000000..af25305 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/piotr/gradientMex.hpp @@ -0,0 +1,340 @@ +/* +// Copyright (c) 2014, Klaus Haag +// All rights reserved. +// +// 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 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. +// +// The views and conclusions contained in the software and documentation are those +// of the authors and should not be interpreted as representing official policies, +// either expressed or implied, of the FreeBSD Project. +*/ + +/******************************************************************************* +* OpenCV interface to Piotr's Computer Vision Matlab Toolbox' FHOG implementation: +https://github.com/pdollar/toolbox/blob/612f9a0451a6abbe2a64768c9e6654692929102e/channels/private/gradientMex.cpp + +TODO: +* Rewrite fhog col major (clustered) calculation to row major (interleaved) calculation +** Calculating FHOG on an implicitly transposed image is possible as well (see cvFhogT), +-- but Performance is slightly lower for an unknown reason. +* Remove code duplication +* Fix hackfixes properly + +*******************************************************************************/ + +#ifndef _GRADIENT_MEX_HPP_ +#define _GRADIENT_MEX_HPP_ + +#include +#include "feature_channels.hpp" +#include "wrappers.hpp" + +namespace piotr { + void fhog(float * const M, float * const O, + float * const H, int h, int w, int binSize, + int nOrients, int softBin, float clip, + bool calcEnergy = true); + + void gradMag(float * const I, float * const M, + float * const O, int h, int w, int d, bool full); + + template + void fhogToCol(const cv::Mat& img, cv::Mat& cvFeatures, + int binSize, int colIdx, PRIMITIVE_TYPE cosFactor) + { + const int orientations = 9; + // ensure array is continuous + const cv::Mat& image = (img.isContinuous() ? img : img.clone()); + int channels = image.channels(); + int computeChannels = 32; + int width = image.cols; + int height = image.rows; + int widthBin = width / binSize; + int heightBin = height / binSize; + + CV_Assert(channels == 1 || channels == 3); + CV_Assert(cvFeatures.channels() == 1 && cvFeatures.isContinuous()); + + float* const H = (float*)wrCalloc(static_cast(widthBin * heightBin * computeChannels), sizeof(float)); + float* const I = (float*)wrCalloc(static_cast(width * height * channels), sizeof(float)); + float* const M = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + float* const O = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + + // row major (interleaved) to col major (non-interleaved;clustered;block) + float* imageData = reinterpret_cast(image.data); + + float* const redChannel = I; + float* const greenChannel = I + width * height; + float* const blueChannel = I + 2 * width * height; + int colMajorPos = 0, rowMajorPos = 0; + + for (int row = 0; row < height; ++row) + { + for (int col = 0; col < width; ++col) + { + colMajorPos = col * height + row; + rowMajorPos = row * channels * width + col * channels; + + blueChannel[colMajorPos] = imageData[rowMajorPos]; + greenChannel[colMajorPos] = imageData[rowMajorPos + 1]; + redChannel[colMajorPos] = imageData[rowMajorPos + 2]; + } + } + + // calc fhog in col major + gradMag(I, M, O, height, width, channels, true); + fhog(M, O, H, height, width, binSize, orientations, -1, 0.2f); + + // the order of rows in cvFeatures does not matter + // as long as it is the same for all columns; + // zero channel is not copied as it is the last + // channel in H and cvFeatures rows doesn't include it + PRIMITIVE_TYPE* cdata = reinterpret_cast(cvFeatures.data); + int outputWidth = cvFeatures.cols; + + for (int row = 0; row < cvFeatures.rows; ++row) + cdata[outputWidth*row + colIdx] = H[row] * cosFactor; + + wrFree(H); + wrFree(M); + wrFree(O); + wrFree(I); + } + + template + void fhogToCvColT(const cv::Mat& img, cv::Mat& cvFeatures, + int binSize, int colIdx, PRIMITIVE_TYPE cosFactor) + { + const int orientations = 9; + // ensure array is continuous + const cv::Mat& image = (img.isContinuous() ? img : img.clone()); + int channels = image.channels(); + int computeChannels = 32; + int width = image.cols; + int height = image.rows; + int widthBin = width / binSize; + int heightBin = height / binSize; + + CV_Assert(channels == 1 || channels == 3); + CV_Assert(cvFeatures.channels() == 1 && cvFeatures.isContinuous()); + + float* const H = (float*)wrCalloc(static_cast(widthBin * heightBin * computeChannels), sizeof(float)); + float* const M = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + float* const O = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + + float* I = NULL; + + if (channels == 1) + I = reinterpret_cast(image.data); + else + { + I = (float*)wrCalloc(static_cast(width * height * channels), sizeof(float)); + float* imageData = reinterpret_cast(image.data); + float* redChannel = I; + float* greenChannel = I + width * height; + float* blueChannel = I + 2 * width * height; + + for (int i = 0; i < height * width; ++i) + { + blueChannel[i] = imageData[i * 3]; + greenChannel[i] = imageData[i * 3 + 1]; + redChannel[i] = imageData[i * 3 + 2]; + } + } + + // calc fhog in col major - switch width and height + gradMag(I, M, O, width, height, channels, true); + fhog(M, O, H, width, height, binSize, orientations, -1, 0.2f); + + // the order of rows in cvFeatures does not matter + // as long as it is the same for all columns; + // zero channel is not copied as it is the last + // channel in H and cvFeatures rows doesn't include it + PRIMITIVE_TYPE* cdata = reinterpret_cast(cvFeatures.data); + int outputWidth = cvFeatures.cols; + + for (int row = 0; row < cvFeatures.rows; ++row) + cdata[outputWidth*row + colIdx] = H[row] * cosFactor; + + wrFree(H); + wrFree(M); + wrFree(O); + + if (channels != 1) + wrFree(I); + } + + template + void cvFhog(const cv::Mat& img, std::shared_ptr& cvFeatures, int binSize, int fhogChannelsToCopy = 31) + { + const int orientations = 9; + // ensure array is continuous + const cv::Mat& image = (img.isContinuous() ? img : img.clone()); + int channels = image.channels(); + int computeChannels = 32; + int width = image.cols; + int height = image.rows; + int widthBin = width / binSize; + int heightBin = height / binSize; + + float* const I = (float*)wrCalloc(static_cast(width * height * channels), sizeof(float)); + float* const H = (float*)wrCalloc(static_cast(widthBin * heightBin * computeChannels), sizeof(float)); + float* const M = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + float* const O = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + + // row major (interleaved) to col major (non interleaved;clustered) + float* imageData = reinterpret_cast(image.data); + + float* const redChannel = I; + float* const greenChannel = I + width * height; + float* const blueChannel = I + 2 * width * height; + int colMajorPos = 0, rowMajorPos = 0; + + for (int row = 0; row < height; ++row) + { + for (int col = 0; col < width; ++col) + { + colMajorPos = col * height + row; + rowMajorPos = row * channels * width + col * channels; + + blueChannel[colMajorPos] = imageData[rowMajorPos]; + greenChannel[colMajorPos] = imageData[rowMajorPos + 1]; + redChannel[colMajorPos] = imageData[rowMajorPos + 2]; + } + } + + // calc fhog in col major + gradMag(I, M, O, height, width, channels, true); + + if (fhogChannelsToCopy == 27) + fhog(M, O, H, height, width, binSize, orientations, -1, 0.2f, false); + else + fhog(M, O, H, height, width, binSize, orientations, -1, 0.2f); + + // only copy the amount of the channels the user wants + // or the amount that fits into the output array + int channelsToCopy = std::min(fhogChannelsToCopy, OUT::numberOfChannels()); + + for (int c = 0; c < channelsToCopy; ++c) + { + cv::Mat_ m(heightBin, widthBin); + cvFeatures->channels[c] = m; + } + + PRIMITIVE_TYPE* cdata = 0; + //col major to row major with separate channels + for (int c = 0; c < channelsToCopy; ++c) + { + float* Hc = H + widthBin * heightBin * c; + cdata = reinterpret_cast(cvFeatures->channels[c].data); + + for (int row = 0; row < heightBin; ++row) + for (int col = 0; col < widthBin; ++col) + + cdata[row * widthBin + col] = Hc[row + heightBin * col]; + } + + wrFree(M); + wrFree(O); + wrFree(I); + wrFree(H); + } + + template + void cvFhogT(const cv::Mat& img, std::shared_ptr& cvFeatures, int binSize, int fhogChannelsToCopy = 31) + { + const int orientations = 9; + // ensure array is continuous + const cv::Mat& image = (img.isContinuous() ? img : img.clone()); + + int channels = image.channels(); + int computeChannels = 32; + int width = image.cols; + int height = image.rows; + int widthBin = width / binSize; + int heightBin = height / binSize; + + CV_Assert(channels == 1 || channels == 3); + + float* const H = (float*)wrCalloc(static_cast(widthBin * heightBin * computeChannels), sizeof(float)); + float* const M = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + float* const O = (float*)wrCalloc(static_cast(width * height), sizeof(float)); + + float* I = NULL; + + if (channels == 1) + I = reinterpret_cast(image.data); + else + { + I = (float*)wrCalloc(static_cast(width * height * channels), sizeof(float)); + float* imageData = reinterpret_cast(image.data); + float* redChannel = I; + float* greenChannel = I + width * height; + float* blueChannel = I + 2 * width * height; + + for (int i = 0; i < height * width; ++i) + { + blueChannel[i] = imageData[i * 3]; + greenChannel[i] = imageData[i * 3 + 1]; + redChannel[i] = imageData[i * 3 + 2]; + } + } + + // calc fhog in col major - switch width and height + gradMag(I, M, O, width, height, channels, true); + + if (fhogChannelsToCopy == 27) + fhog(M, O, H, width, height, binSize, orientations, -1, 0.2f, false); + else + fhog(M, O, H, width, height, binSize, orientations, -1, 0.2f); + + // only copy the amount of the channels the user wants + // or the amount that fits into the output array + int channelsToCopy = std::min(fhogChannelsToCopy, OUT::numberOfChannels()); + + // init channels + for (int c = 0; c < channelsToCopy; ++c) + { + cv::Mat_ m(heightBin, widthBin); + cvFeatures->channels[c] = m; + } + + PRIMITIVE_TYPE* cdata = 0; + // implicit transpose on every channel due to col-major to row-major matrix + for (int c = 0; c < channelsToCopy; ++c) + { + float* Hc = H + widthBin * heightBin * c; + cdata = reinterpret_cast(cvFeatures->channels[c].data); + + for (int i = 0; i < heightBin * widthBin; ++i) + cdata[i] = Hc[i]; + } + + wrFree(M); + wrFree(O); + + if (channels != 1) + wrFree(I); + + wrFree(H); + } +} +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/gradientMex.cpp b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/gradientMex.cpp new file mode 100644 index 0000000..cba2a3b --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/gradientMex.cpp @@ -0,0 +1,656 @@ +/* +Copyright (c) 2012, Piotr Dollar +All rights reserved. + +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 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. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +/******************************************************************************* +* Piotr's Computer Vision Matlab Toolbox Version 3.30 +* Copyright 2014 Piotr Dollar & Ron Appel. [pdollar-at-gmail.com] +* Licensed under the Simplified BSD License [see above] +* Project page: http://vision.ucsd.edu/~pdollar/toolbox/doc/ +* original file: https://github.com/pdollar/toolbox/blob/612f9a0451a6abbe2a64768c9e6654692929102e/channels/private/gradientMex.cpp + ++ author: Klaus Haag +* Move external license file into source file +* Hackfix crashes on Windows and Linux when called directly from cpp code +* Allow disabling of energy channels computation +* Remove unnecessary code ++ author: Luka Cehovin: Fix equal results on AMD and Intel CPUs + +TODO: Fix hackfixes properly; see function fhog and grad1... +*******************************************************************************/ +#include "gradientMex.hpp" +#include +#include "string.h" +#include "sse.hpp" +#include + +#define PI 3.14159265f + +namespace piotr { + // compute x and y gradients for just one column (uses sse) + void grad1(float *I, float *Gx, float *Gy, int h, int w, int x) { + int y, y1; float *Ip, *In, r; __m128 *_Ip, *_In, *_G, _r; + // compute column of Gx + Ip = I - h; In = I + h; r = .5f; + if (x == 0) { r = 1; Ip += h; } + else if (x == w - 1) { r = 1; In -= h; } + + if (h < 4 || h % 4>0 || (size_t(I) & 15) || (size_t(Gx) & 15)) + { + // HACKFIX: volatile prevents the compiler from + // optimizing out y. if y is optimized out + // a segfault happens on linux with g++; + // this does not happen with MSVC; + volatile int y; + + for (y = 0; y < h; y++) + *Gx++ = (*In++ - *Ip++)*r; + } + else { + _G = (__m128*) Gx; _Ip = (__m128*) Ip; _In = (__m128*) In; _r = SET(r); + for (y = 0; y < h; y += 4) *_G++ = MUL(SUB(*_In++, *_Ip++), _r); + } + // compute column of Gy +#define GRADY(r) *Gy++=(*In++-*Ip++)*r; + Ip = I; In = Ip + 1; + // GRADY(1); Ip--; for(y=1; y h - 1) + y1 = h - 1; + GRADY(1); + Ip--; + for (y = 1; y < y1; y++) + GRADY(.5f); + _r = SET(.5f); + _G = (__m128*) Gy; + for (; y + 4 < h - 1; y += 4, Ip += 4, In += 4, Gy += 4) + *_G++ = MUL(SUB(LDu(*In), LDu(*Ip)), _r); + for (; y < h - 1; y++) + GRADY(.5f); + In--; + GRADY(1); +#undef GRADY + } + + // compute x and y gradients at each location (uses sse) + void grad2(float *I, float *Gx, float *Gy, int h, int w, int d) { + int o, x, c, a = w*h; for (c = 0; c < d; c++) for (x = 0; x < w; x++) { + o = c*a + x*h; + grad1(I + o, Gx + o, Gy + o, h, w, x); + } + } + + // build lookup table a[] s.t. a[x*n]~=acos(x) for x in [-1,1] + // TODO: check thread safety of statics!!!! + float* acosTable() { + const int n = 10000, b = 10; int i; + static float a[n * 2 + b * 2]; + static bool init = false; + + float *a1 = a + n + b; + if (init) + return a1; + for (i = -n - b; i < -n; i++) + a1[i] = PI; + for (i = -n; i < n; i++) + a1[i] = float(acos(i / float(n))); + for (i = n; i < n + b; i++) + a1[i] = 0; + for (i = -n - b; i PI - 1e-6f) + a1[i] = PI - 1e-6f; + init = true; + + return a1; + } + + // compute gradient magnitude and orientation at each location (uses sse) + void gradMag(float * const I, float * const M, float * const O, + int h, int w, int d, bool full) + { + int x, y, y1, c, h4, s; + __m128 *_Gx, *_Gy, *_M2, _m; + float *acost = acosTable(), acMult = 10000.0f; + // allocate memory for storing one column of output (padded so h4%4==0) + h4 = (h % 4 == 0) ? h : h - (h % 4) + 4; + s = d*h4*sizeof(float); + float * const M2 = (float*)alMalloc(s, 16); + _M2 = (__m128*) M2; + float * const Gx = (float*)alMalloc(s, 16); + _Gx = (__m128*) Gx; + float * const Gy = (float*)alMalloc(s, 16); + _Gy = (__m128*) Gy; + + // compute gradient magnitude and orientation for each column + for (x = 0; x < w; x++) + { + // compute gradients (Gx, Gy) with maximum squared magnitude (M2) + for (c = 0; c < d; c++) + { + grad1(I + x*h + c*w*h, Gx + c*h4, Gy + c*h4, h, w, x); + + for (y = 0; y < h4 / 4; y++) + { + y1 = h4 / 4 * c + y; + _M2[y1] = ADD(MUL(_Gx[y1], _Gx[y1]), MUL(_Gy[y1], _Gy[y1])); + if (c == 0) + continue; + _m = CMPGT(_M2[y1], _M2[y]); + _M2[y] = OR(AND(_m, _M2[y1]), ANDNOT(_m, _M2[y])); + _Gx[y] = OR(AND(_m, _Gx[y1]), ANDNOT(_m, _Gx[y])); + _Gy[y] = OR(AND(_m, _Gy[y1]), ANDNOT(_m, _Gy[y])); + } + } + // compute gradient mangitude (M) and normalize Gx + for (y = 0; y < h4 / 4; y++) { + /* _m = MIN_SSE(RCPSQRT(_M2[y]), SET(1e10f)); + _M2[y] = RCP(_m); + if (O) + _Gx[y] = MUL(MUL(_Gx[y], _m), SET(acMult)); + if (O) + _Gx[y] = XOR(_Gx[y], AND(_Gy[y], SET(-0.f)));*/ + + _m = MAX_SSE(SQRT(_M2[y]), SET(1e-7f)); + _M2[y] = _m; + if (O) _Gx[y] = MUL(DIV(_Gx[y], _m), SET(acMult)); + if (O) _Gx[y] = XOR(_Gx[y], AND(_Gy[y], SET(-0.f))); + }; + + memcpy(M + x*h, M2, h*sizeof(float)); + + // compute and store gradient orientation (O) via table lookup + if (O != 0) + { + for (y = 0; y < h; y++) + O[x*h + y] = acost[(int)Gx[y]]; + } + + if (O != 0 && full) + { + y1 = ((~size_t(O + x*h) + 1) & 15) / 4; y = 0; + for (; y < y1; y++) + O[y + x*h] += (Gy[y] < 0)*PI; + + for (; y < h - 4; y += 4) + { + STRu(O[y + x*h], + ADD(LDu(O[y + x*h]), AND(CMPLT(LDu(Gy[y]), SET(0.f)), SET(PI)))); + } + + for (; y < h; y++) + { + O[y + x*h] += (Gy[y] < 0)*PI; + } + } + } + + alFree(Gx); + alFree(Gy); + alFree(M2); + } + + // normalize gradient magnitude at each location (uses sse) + void gradMagNorm(float *M, float *S, int h, int w, float norm) { + __m128 *_M, *_S, _norm; int i = 0, n = h*w, n4 = n / 4; + _S = (__m128*) S; _M = (__m128*) M; _norm = SET(norm); + bool sse = !(size_t(M) & 15) && !(size_t(S) & 15); + if (sse) for (; i < n4; i++) { *_M = MUL(*_M, RCP(ADD(*_S++, _norm))); _M++; } + if (sse) i *= 4; for (; i < n; i++) M[i] /= (S[i] + norm); + } + + // helper for gradHist, quantize O and M into O0, O1 and M0, M1 (uses sse) + void gradQuantize(float const *O, float * const M, int * const O0, + int * const O1, float * const M0, float * const M1, + int nb, int n, float norm, int nOrients, bool full, bool interpolate) + { + // assumes all *OUTPUT* matrices are 4-byte aligned + int i, o0, o1; float o, od, m; + __m128i _o0, _o1, *_O0, *_O1; __m128 _o, _od, _m, *_M0, *_M1; + // define useful constants + const float oMult = (float)nOrients / (full ? 2 * PI : PI); const int oMax = nOrients*nb; + const __m128 _norm = SET(norm), _oMult = SET(oMult), _nbf = SET((float)nb); + const __m128i _oMax = SET(oMax), _nb = SET(nb); + // perform the majority of the work with sse + _O0 = (__m128i*) O0; _O1 = (__m128i*) O1; _M0 = (__m128*) M0; _M1 = (__m128*) M1; + if (interpolate) for (i = 0; i <= n - 4; i += 4) { + _o = MUL(LDu(O[i]), _oMult); _o0 = CVT(_o); _od = SUB(_o, CVT(_o0)); + _o0 = CVT(MUL(CVT(_o0), _nbf)); _o0 = AND(CMPGT(_oMax, _o0), _o0); *_O0++ = _o0; + _o1 = ADD(_o0, _nb); _o1 = AND(CMPGT(_oMax, _o1), _o1); *_O1++ = _o1; + _m = MUL(LDu(M[i]), _norm); *_M1 = MUL(_od, _m); *_M0++ = SUB(_m, *_M1); _M1++; + } + else for (i = 0; i <= n - 4; i += 4) { + _o = MUL(LDu(O[i]), _oMult); _o0 = CVT(ADD(_o, SET(.5f))); + _o0 = CVT(MUL(CVT(_o0), _nbf)); _o0 = AND(CMPGT(_oMax, _o0), _o0); *_O0++ = _o0; + *_M0++ = MUL(LDu(M[i]), _norm); *_M1++ = SET(0.f); *_O1++ = SET(0); + } + // compute trailing locations without sse + if (interpolate) for (; i < n; i++) { + o = O[i] * oMult; o0 = (int)o; od = o - o0; + o0 *= nb; if (o0 >= oMax) o0 = 0; O0[i] = o0; + o1 = o0 + nb; if (o1 == oMax) o1 = 0; O1[i] = o1; + m = M[i] * norm; M1[i] = od*m; M0[i] = m - M1[i]; + } + else for (; i < n; i++) { + o = O[i] * oMult; o0 = (int)(o + .5f); + o0 *= nb; if (o0 >= oMax) o0 = 0; O0[i] = o0; + M0[i] = M[i] * norm; M1[i] = 0; O1[i] = 0; + } + } + + // compute nOrients gradient histograms per bin x bin block of pixels + void gradHist(float * const M, float * const O, float * const H, int h, int w, + int bin, int nOrients, int softBin, bool full) + { + const int hb = h / bin, wb = w / bin, h0 = hb*bin, w0 = wb*bin, nb = wb*hb; + const float s = (float)bin, sInv = 1 / s, sInv2 = 1 / s / s; + float *H0, *H1; + int x, y; + float xb = 0.f, init = 0.f; + int * const O0 = (int*)alMalloc(h*sizeof(int), 16); + float * const M0 = (float*)alMalloc(h*sizeof(float), 16); + int * const O1 = (int*)alMalloc(h*sizeof(int), 16); + float * const M1 = (float*)alMalloc(h*sizeof(float), 16); + + // main loop + for (x = 0; x < w0; x++) { + // compute target orientation bins for entire column - very fast + gradQuantize(O + x*h, M + x*h, O0, O1, M0, M1, nb, h0, sInv2, nOrients, full, softBin >= 0); + + if (softBin < 0 && softBin % 2 == 0) { + // no interpolation w.r.t. either orienation or spatial bin + H1 = H + (x / bin)*hb; +#define GH H1[O0[y]]+=M0[y]; y++; + if (bin == 1) for (y = 0; y < h0;) { GH; H1++; } + else if (bin == 2) for (y = 0; y < h0;) { GH; GH; H1++; } + else if (bin == 3) for (y = 0; y < h0;) { GH; GH; GH; H1++; } + else if (bin == 4) for (y = 0; y < h0;) { GH; GH; GH; GH; H1++; } + else for (y = 0; y < h0;) { for (int y1 = 0; y1 < bin; y1++) { GH; } H1++; } +#undef GH + } + else if (softBin % 2 == 0 || bin == 1) { + // interpolate w.r.t. orientation only, not spatial bin + H1 = H + (x / bin)*hb; +#define GH H1[O0[y]]+=M0[y]; H1[O1[y]]+=M1[y]; y++; + if (bin == 1) for (y = 0; y < h0;) { GH; H1++; } + else if (bin == 2) for (y = 0; y < h0;) { GH; GH; H1++; } + else if (bin == 3) for (y = 0; y < h0;) { GH; GH; GH; H1++; } + else if (bin == 4) for (y = 0; y < h0;) { GH; GH; GH; GH; H1++; } + else for (y = 0; y < h0;) { for (int y1 = 0; y1 < bin; y1++) { GH; } H1++; } +#undef GH + } + else { + // interpolate using trilinear interpolation + float ms[4], xyd, yb, xd, yd; __m128 _m, _m0, _m1; + bool hasLf, hasRt; int xb0, yb0; + if (x == 0) { init = (0 + .5f)*sInv - 0.5f; xb = init; } + hasLf = xb >= 0; xb0 = hasLf ? (int)xb : -1; hasRt = xb0 < wb - 1; + xd = xb - xb0; xb += sInv; yb = init; y = 0; + // macros for code conciseness +#define GHinit yd=yb-yb0; yb+=sInv; H0=H+xb0*hb+yb0; xyd=xd*yd; \ + ms[0]=1-xd-yd+xyd; ms[1]=yd-xyd; ms[2]=xd-xyd; ms[3]=xyd; +#define GH(H,ma,mb) H1=H; STRu(*H1,ADD(LDu(*H1),MUL(ma,mb))); + // leading rows, no top bin + for (; y < bin / 2; y++) { + yb0 = -1; GHinit; + if (hasLf) { H0[O0[y] + 1] += ms[1] * M0[y]; H0[O1[y] + 1] += ms[1] * M1[y]; } + if (hasRt) { H0[O0[y] + hb + 1] += ms[3] * M0[y]; H0[O1[y] + hb + 1] += ms[3] * M1[y]; } + } + // main rows, has top and bottom bins, use SSE for minor speedup + if (softBin < 0) + { + for (;; y++) + { + yb0 = (int)yb; + if (yb0 >= hb - 1) + break; + GHinit; + _m0 = SET(M0[y]); + + if (hasLf) + { + _m = SET(0, 0, ms[1], ms[0]); + GH(H0 + O0[y], _m, _m0); + } + if (hasRt) + { + _m = SET(0, 0, ms[3], ms[2]); + GH(H0 + O0[y] + hb, _m, _m0); + } + } + } + else for (;; y++) { + yb0 = (int)yb; if (yb0 >= hb - 1) break; GHinit; + _m0 = SET(M0[y]); _m1 = SET(M1[y]); + if (hasLf) { + _m = SET(0, 0, ms[1], ms[0]); + GH(H0 + O0[y], _m, _m0); GH(H0 + O1[y], _m, _m1); + } + if (hasRt) { + _m = SET(0, 0, ms[3], ms[2]); + GH(H0 + O0[y] + hb, _m, _m0); GH(H0 + O1[y] + hb, _m, _m1); + } + } + // final rows, no bottom bin + for (; y < h0; y++) { + yb0 = (int)yb; GHinit; + if (hasLf) { H0[O0[y]] += ms[0] * M0[y]; H0[O1[y]] += ms[0] * M1[y]; } + if (hasRt) { H0[O0[y] + hb] += ms[2] * M0[y]; H0[O1[y] + hb] += ms[2] * M1[y]; } + } +#undef GHinit +#undef GH + } + } + alFree(O0); + alFree(O1); + alFree(M0); + alFree(M1); + + // normalize boundary bins which only get 7/8 of weight of interior bins + if (softBin % 2 != 0) for (int o = 0; o < nOrients; o++) { + x = 0; for (y = 0; y < hb; y++) H[o*nb + x*hb + y] *= 8.f / 7.f; + y = 0; for (x = 0; x < wb; x++) H[o*nb + x*hb + y] *= 8.f / 7.f; + x = wb - 1; for (y = 0; y < hb; y++) H[o*nb + x*hb + y] *= 8.f / 7.f; + y = hb - 1; for (x = 0; x < wb; x++) H[o*nb + x*hb + y] *= 8.f / 7.f; + } + } + + /******************************************************************************/ + + // HOG helper: compute 2x2 block normalization values (padded by 1 pixel) + float* const hogNormMatrix(float *const H, int nOrients, int hb, int wb, int bin) { + float *N1, *n; + int o, x, y, dx, dy, hb1 = hb + 1, wb1 = wb + 1; + float eps = 1e-4f / 4 / bin / bin / bin / bin; // precise backward equality + float * const N = (float*)wrCalloc(hb1*wb1, sizeof(float)); + N1 = N + hb1 + 1; + + for (o = 0; o < nOrients; o++) + for (x = 0; x < wb; x++) + for (y = 0; y < hb; y++) + N1[x*hb1 + y] += H[o*wb*hb + x*hb + y] * H[o*wb*hb + x*hb + y]; + for (x = 0; x < wb - 1; x++) + for (y = 0; y < hb - 1; y++) { + n = N1 + x*hb1 + y; *n = 1 / float(sqrt(n[0] + n[1] + n[hb1] + n[hb1 + 1] + eps)); + } + + x = 0; dx = 1; dy = 1; y = 0; N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + x = 0; dx = 1; dy = 0; for (y = 0; y < hb1; y++) N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + x = 0; dx = 1; dy = -1; y = hb1 - 1; N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + x = wb1 - 1; dx = -1; dy = 1; y = 0; N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + x = wb1 - 1; dx = -1; dy = 0; for (y = 0; y < hb1; y++) N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + x = wb1 - 1; dx = -1; dy = -1; y = hb1 - 1; N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + y = 0; dx = 0; dy = 1; for (x = 0; x < wb1; x++) N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + y = hb1 - 1; dx = 0; dy = -1; for (x = 0; x < wb1; x++) N[x*hb1 + y] = N[(x + dx)*hb1 + y + dy]; + return N; + } + + // HOG helper: compute HOG or FHOG channels + void hogChannels(float * const H, const float * const R, const float * const N, + int hb, int wb, int nOrients, float clip, int type) + { +#define GETT(blk) t=R1[y]*N1[y-(blk)]; if(t>clip) t=clip; c++; +#define GETTT(blk) t=R1[y]*N1[y-(blk)]; if(t>clip) t=clip; + const float r = .2357f; int o, x, y, c; float t; + const int nb = wb*hb, nbo = nOrients*nb, hb1 = hb + 1; + + for (o = 0; o < nOrients; o++) + { + for (x = 0; x < wb; x++) + { + const float *R1 = R + o*nb + x*hb, *N1 = N + x*hb1 + hb1 + 1; + float *H1 = (type <= 1) ? (H + o*nb + x*hb) : (H + x*hb); + if (type == 0) for (y = 0; y < hb; ++y) { + // store each orientation and normalization (nOrients*4 channels) + c = -1; + GETT(0); + H1[c*nbo + y] = t; + GETT(1); + H1[c*nbo + y] = t; + GETT(hb1); + H1[c*nbo + y] = t; + GETT(hb1 + 1); + H1[c*nbo + y] = t; + } + else if (type == 1) for (y = 0; y < hb; ++y) { + // sum across all normalizations (nOrients channels) + GETTT(0); + H1[y] += t*.5f; + GETTT(1); + H1[y] += t*.5f; + GETTT(hb1); + H1[y] += t*.5f; + GETTT(hb1 + 1); + H1[y] += t*.5f; + } + else if (type == 2) for (y = 0; y < hb; ++y) { + // sum across all orientations (4 channels) + c = -1; + GETT(0); + H1[c*nb + y] += t*r; + GETT(1); + H1[c*nb + y] += t*r; + GETT(hb1); + H1[c*nb + y] += t*r; + GETT(hb1 + 1); + H1[c*nb + y] += t*r; + } + } + } +#undef GETT +#undef GETTT + } + + // compute HOG features + void hog(float *M, float *O, float *H, int h, int w, int binSize, + int nOrients, int softBin, bool full, float clip) + { + float *N, *R; const int hb = h / binSize, wb = w / binSize; + // compute unnormalized gradient histograms + R = (float*)wrCalloc(wb*hb*nOrients, sizeof(float)); + gradHist(M, O, R, h, w, binSize, nOrients, softBin, full); + // compute block normalization values + N = hogNormMatrix(R, nOrients, hb, wb, binSize); + // perform four normalizations per spatial block + hogChannels(H, R, N, hb, wb, nOrients, clip, 0); + wrFree(N); wrFree(R); + } + + // compute FHOG features + void fhog(float * const M, float * const O, float * const H, int h, int w, int binSize, + int nOrients, int softBin, float clip, bool calcEnergy) + { + const int hb = h / binSize, wb = w / binSize, nb = hb*wb, nbo = nb*nOrients; + /*float *N, *R1, *R2;*/ + int o, x; + // compute unnormalized constrast sensitive histograms + //TODO: Hackfix - size increased to +1; no idea why; but heap doesn't + // get corrupted this way... + float * const R1 = (float*)wrCalloc(wb*hb*nOrients * 2 + 1, sizeof(float)); + R1[wb*hb*nOrients * 2] = 0.f; + + gradHist(M, O, R1, h, w, binSize, nOrients * 2, softBin, true); + + // compute unnormalized contrast insensitive histograms + float * const R2 = (float*)wrCalloc(wb*hb*nOrients, sizeof(float)); + + for (o = 0; o < nOrients; o++) for (x = 0; x < nb; x++) + R2[o*nb + x] = R1[o*nb + x] + R1[(o + nOrients)*nb + x]; + + // compute block normalization values + float * const N = hogNormMatrix(R2, nOrients, hb, wb, binSize); // only allocs N (wrcalloc) + + // normalized histograms and texture channels + hogChannels(H + nbo * 0, R1, N, hb, wb, nOrients * 2, clip, 1); // no alloc + hogChannels(H + nbo * 2, R2, N, hb, wb, nOrients * 1, clip, 1); // no alloc + + if (calcEnergy) + hogChannels(H + nbo * 3, R1, N, hb, wb, nOrients * 2, clip, 2); // no alloc + + int i = 5; + wrFree(R1); + int j = 12; + j = i + j; + + wrFree(N); + wrFree(R2); // todo check + } + + /******************************************************************************/ +#ifdef MATLAB_MEX_FILE + // Create [hxwxd] mxArray array, initialize to 0 if c=true + mxArray* mxCreateMatrix3(int h, int w, int d, mxClassID id, bool c, void **I){ + const int dims[3] = { h, w, d }, n = h*w*d; int b; + mxArray* M; + + if (id == mxINT32_CLASS) b = sizeof(int); + else if (id == mxDOUBLE_CLASS) b = sizeof(double); + else if (id == mxSINGLE_CLASS) b = sizeof(float); + else mexErrMsgTxt("Unknown mxClassID."); + *I = c ? mxCalloc(n, b) : mxMalloc(n*b); + M = mxCreateNumericMatrix(0, 0, id, mxREAL); + mxSetData(M, *I); mxSetDimensions(M, dims, 3); return M; + } + + // Check inputs and outputs to mex, retrieve first input I + void checkArgs(int nl, mxArray *pl[], int nr, const mxArray *pr[], int nl0, + int nl1, int nr0, int nr1, int *h, int *w, int *d, mxClassID id, void **I) + { + const int *dims; int nDims; + if (nlnl1) + mexErrMsgTxt("Incorrect number of outputs."); + if (nrnr1) + mexErrMsgTxt("Incorrect number of inputs."); + + nDims = mxGetNumberOfDimensions(pr[0]); + dims = mxGetDimensions(pr[0]); + *h = dims[0]; + *w = dims[1]; + *d = (nDims == 2) ? 1 : dims[2]; + *I = mxGetPr(pr[0]); + + if (nDims != 2 && nDims != 3) + mexErrMsgTxt("I must be a 2D or 3D array."); + if (mxGetClassID(pr[0]) != id) + mexErrMsgTxt("I has incorrect type."); + } + + // [Gx,Gy] = grad2(I) - see gradient2.m + void mGrad2(int nl, mxArray *pl[], int nr, const mxArray *pr[]) { + int h, w, d; float *I, *Gx, *Gy; + checkArgs(nl, pl, nr, pr, 1, 2, 1, 1, &h, &w, &d, mxSINGLE_CLASS, (void**)&I); + if (h < 2 || w < 2) mexErrMsgTxt("I must be at least 2x2."); + pl[0] = mxCreateMatrix3(h, w, d, mxSINGLE_CLASS, 0, (void**)&Gx); + pl[1] = mxCreateMatrix3(h, w, d, mxSINGLE_CLASS, 0, (void**)&Gy); + grad2(I, Gx, Gy, h, w, d); + } + + // [M,O] = gradMag( I, channel, full ) - see gradientMag.m + void mGradMag(int nl, mxArray *pl[], int nr, const mxArray *pr[]) { + int h, w, dim, channel, full; + float *I, *M, *O = 0; + + checkArgs(nl, pl, nr, pr, 1, 2, 3, 3, &h, &w, &dim, mxSINGLE_CLASS, (void**)&I); + + if (h < 2 || w < 2) + mexErrMsgTxt("I must be at least 2x2."); + + channel = (int)mxGetScalar(pr[1]); + full = (int)mxGetScalar(pr[2]); + + if (channel > 0 && channel <= dim) + { + I += h*w*(channel - 1); + dim = 1; + } + + pl[0] = mxCreateMatrix3(h, w, 1, mxSINGLE_CLASS, 0, (void**)&M); + + if (nl >= 2) + pl[1] = mxCreateMatrix3(h, w, 1, mxSINGLE_CLASS, 0, (void**)&O); + + gradMag(I, M, O, h, w, dim, full > 0); + } + + // gradMagNorm( M, S, norm ) - operates on M - see gradientMag.m + void mGradMagNorm(int nl, mxArray *pl[], int nr, const mxArray *pr[]) { + int h, w, d; float *M, *S, norm; + checkArgs(nl, pl, nr, pr, 0, 0, 3, 3, &h, &w, &d, mxSINGLE_CLASS, (void**)&M); + if (mxGetM(pr[1]) != h || mxGetN(pr[1]) != w || d != 1 || + mxGetClassID(pr[1]) != mxSINGLE_CLASS) mexErrMsgTxt("M or S is bad."); + S = (float*)mxGetPr(pr[1]); norm = (float)mxGetScalar(pr[2]); + gradMagNorm(M, S, h, w, norm); + } + + // H=gradHist(M,O,[...]) - see gradientHist.m + void mGradHist(int nl, mxArray *pl[], int nr, const mxArray *pr[]) { + int h, w, d, hb, wb, nChns, binSize, nOrients, softBin, useHog; + bool full; float *M, *O, *H, clipHog; + checkArgs(nl, pl, nr, pr, 1, 3, 2, 8, &h, &w, &d, mxSINGLE_CLASS, (void**)&M); + O = (float*)mxGetPr(pr[1]); + if (mxGetM(pr[1]) != h || mxGetN(pr[1]) != w || d != 1 || + mxGetClassID(pr[1]) != mxSINGLE_CLASS) mexErrMsgTxt("M or O is bad."); + binSize = (nr >= 3) ? (int)mxGetScalar(pr[2]) : 8; + nOrients = (nr >= 4) ? (int)mxGetScalar(pr[3]) : 9; + softBin = (nr >= 5) ? (int)mxGetScalar(pr[4]) : 1; + useHog = (nr >= 6) ? (int)mxGetScalar(pr[5]) : 0; + clipHog = (nr >= 7) ? (float)mxGetScalar(pr[6]) : 0.2f; + full = (nr >= 8) ? (bool)(mxGetScalar(pr[7]) > 0) : false; + hb = h / binSize; wb = w / binSize; + nChns = useHog == 0 ? nOrients : (useHog == 1 ? nOrients * 4 : nOrients * 3 + 5); + pl[0] = mxCreateMatrix3(hb, wb, nChns, mxSINGLE_CLASS, 1, (void**)&H); + if (nOrients == 0) return; + if (useHog == 0) { + gradHist(M, O, H, h, w, binSize, nOrients, softBin, full); + } + else if (useHog == 1) { + hog(M, O, H, h, w, binSize, nOrients, softBin, full, clipHog); + } + else { + fhog(M, O, H, h, w, binSize, nOrients, softBin, clipHog); + } + } + + // nlhs Number of output (left-side) arguments, or the size of the plhs array. + // plhs Array of output arguments. + // nrhs Number of input (right-side) arguments, or the size of the prhs array. + // prhs Array of input arguments. + + // inteface to various gradient functions (see corresponding Matlab functions) + void mexFunction(int nl, mxArray *pl[], int nr, const mxArray *pr[]) { + int f; char action[1024]; f = mxGetString(pr[0], action, 1024); nr--; pr++; + if (f) mexErrMsgTxt("Failed to get action."); + else if (!strcmp(action, "gradient2")) mGrad2(nl, pl, nr, pr); + else if (!strcmp(action, "gradientMag")) mGradMag(nl, pl, nr, pr); + else if (!strcmp(action, "gradientMagNorm")) mGradMagNorm(nl, pl, nr, pr); + else if (!strcmp(action, "gradientHist")) mGradHist(nl, pl, nr, pr); + else mexErrMsgTxt("Invalid action."); +} +#endif +} diff --git a/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse.hpp b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse.hpp new file mode 100644 index 0000000..25454c9 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse.hpp @@ -0,0 +1,116 @@ +/* +Copyright (c) 2012, Piotr Dollar +All rights reserved. + +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 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. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +/******************************************************************************* +* Piotr's Computer Vision Matlab Toolbox Version 3.23 +* Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] +* Licensed under the Simplified BSD License [see above] +* Project page: http://vision.ucsd.edu/~pdollar/toolbox/doc/ +* Original file: https://github.com/pdollar/toolbox/blob/612f9a0451a6abbe2a64768c9e6654692929102e/channels/private/sse.hpp + ++ author: Klaus Haag: Move external license into this source file ++ author: Luka Cehovin: Fix equal results on AMD and Intel CPUs +*******************************************************************************/ +#ifndef _SSE_HPP_ +#define _SSE_HPP_ + +#define __ARM_NEON__ + +#ifdef __ARM_NEON__ +#include "sse_to_neon.hpp" +#else +#include +#endif + +#define RETf inline __m128 +#define RETi inline __m128i + +// set, load and store values +RETf SET(const float& x) { return _mm_set1_ps(x); } +RETf SET(float x, float y, float z, float w) { return _mm_set_ps(x, y, z, w); } +RETi SET(const int& x) { return _mm_set1_epi32(x); } +RETf LD(const float& x) { return _mm_load_ps(&x); } +RETf LDu(const float& x) { return _mm_loadu_ps(&x); } +RETf STR(float& x, const __m128 y) { _mm_store_ps(&x, y); return y; } +RETf STR1(float& x, const __m128 y) { _mm_store_ss(&x, y); return y; } +RETf STRu(float& x, const __m128 y) { _mm_storeu_ps(&x, y); return y; } +RETf STR(float& x, const float y) { return STR(x, SET(y)); } + +// arithmetic operators +RETi ADD(const __m128i x, const __m128i y) { return _mm_add_epi32(x, y); } +RETf ADD(const __m128 x, const __m128 y) { return _mm_add_ps(x, y); } +RETf ADD(const __m128 x, const __m128 y, const __m128 z) { + return ADD(ADD(x, y), z); +} +RETf ADD(const __m128 a, const __m128 b, const __m128 c, const __m128& d) { + return ADD(ADD(ADD(a, b), c), d); +} +RETf SUB(const __m128 x, const __m128 y) { return _mm_sub_ps(x, y); } +RETf MUL(const __m128 x, const __m128 y) { return _mm_mul_ps(x, y); } +RETf MUL(const __m128 x, const float y) { return MUL(x, SET(y)); } +RETf MUL(const float x, const __m128 y) { return MUL(SET(x), y); } +RETf INC(__m128& x, const __m128 y) { return x = ADD(x, y); } +RETf INC(float& x, const __m128 y) { __m128 t = ADD(LD(x), y); return STR(x, t); } +RETf DEC(__m128& x, const __m128 y) { return x = SUB(x, y); } +RETf DEC(float& x, const __m128 y) { __m128 t = SUB(LD(x), y); return STR(x, t); } +RETf MIN_SSE(const __m128 x, const __m128 y) { return _mm_min_ps(x, y); } +RETf RCP(const __m128 x) { return _mm_rcp_ps(x); } + +RETf SQRT(const __m128 x) { return _mm_sqrt_ps(x); } +RETf MAX_SSE(const __m128 x, const __m128 y) { return _mm_max_ps(x, y); } +RETf DIV(const __m128 x, const __m128 y) { +#ifdef __ARM_NEON__ // NEON doesn't seem to support this + return x / y; +#else + return _mm_div_ps(x, y); +#endif +} +RETf DIV(const __m128 x, const float y) { return DIV(x, SET(y)); } +RETf DIV(const float x, const __m128 y) { return DIV(SET(x), y); } + +// logical operators +RETf AND(const __m128 x, const __m128 y) { return _mm_and_ps(x, y); } +RETi AND(const __m128i x, const __m128i y) { return _mm_and_si128(x, y); } +RETf ANDNOT(const __m128 x, const __m128 y) { return _mm_andnot_ps(x, y); } +RETf OR(const __m128 x, const __m128 y) { return _mm_or_ps(x, y); } +RETf XOR(const __m128 x, const __m128 y) { return _mm_xor_ps(x, y); } + +// comparison operators +RETf CMPGT(const __m128 x, const __m128 y) { return _mm_cmpgt_ps(x, y); } +RETf CMPLT(const __m128 x, const __m128 y) { return _mm_cmplt_ps(x, y); } +RETi CMPGT(const __m128i x, const __m128i y) { return _mm_cmpgt_epi32(x, y); } +RETi CMPLT(const __m128i x, const __m128i y) { return _mm_cmplt_epi32(x, y); } + +// conversion operators +RETf CVT(const __m128i x) { return _mm_cvtepi32_ps(x); } +RETi CVT(const __m128 x) { return _mm_cvttps_epi32(x); } + +#undef RETf +#undef RETi +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse_to_neon.hpp b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse_to_neon.hpp new file mode 100644 index 0000000..9e4b9de --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse_to_neon.hpp @@ -0,0 +1,177 @@ +#ifndef SSE2NEON_H +#define SSE2NEON_H + +// This header file provides a simple API translation layer +// between SSE intrinsics to their corresponding ARM NEON versions +// +// This header file does not (yet) translate *all* of the SSE intrinsics. +// Since this is in support of a specific porting effort, I have only +// included the intrinsics I needed to get my port to work. +// +// Questions/Comments/Feedback send to: jratcliffscarab@gmail.com +// +// If you want to improve or add to this project, send me an +// email and I will probably approve your access to the depot. +// +// Project is located here: +// +// https://github.com/jratcliff63367/sse2neon +// +// TipJar: 1PzgWDSyq4pmdAXRH8SPUtta4SWGrt4B1p : https://blockchain.info/address/1PzgWDSyq4pmdAXRH8SPUtta4SWGrt4B1p +// +// +// Contributors to this project are: +// +// John W. Ratcliff : jratcliffscarab@gmail.com +// Brandon Rowlett : browlett@nvidia.com +// Ken Fast : kfast@gdeb.com + +#define FORCE_INLINE inline __attribute__((always_inline)) + +#include "arm_neon.h" + +typedef float32x4_t __m128; +typedef int32x4_t __m128i; + +// Sets the four single-precision, floating-point values to w. https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set1_ps(float _w) { + return vdupq_n_f32(_w); +} + +// Sets the four single-precision, floating-point values to the four inputs. https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x) { + float __attribute__((aligned(16))) data[4] = { x, y, z, w }; + return vld1q_f32(data); +} + +// Sets the 4 signed 32-bit integer values to i. https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set1_epi32(int _i) { + return vdupq_n_s32(_i); +} + +// Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx +FORCE_INLINE __m128 _mm_load_ps(const float* p) { + return vld1q_f32(p); +} + +// Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_loadu_ps(const float* p) { + return _mm_load_ps(p); +} + +// Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx +FORCE_INLINE void _mm_store_ps(float* p, __m128 a) { + vst1q_f32(p, a); +} + +// Stores the lower single - precision, floating - point value. https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx +FORCE_INLINE void _mm_store_ss(float* p, __m128 a) { + vst1q_lane_f32(p, a, 0); +} + +// Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx +FORCE_INLINE void _mm_storeu_ps(float* p, __m128 a) { + vst1q_f32(p, a); +} + +// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or unsigned 32-bit integers in b. https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b) { + return vaddq_s32(a, b); +} + +// Adds the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx +FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b) { + return vaddq_f32(a, b); +} + +// Subtracts the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b) { + return vsubq_f32(a, b); +} + +// Multiplies the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx +FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b) { + return vmulq_f32(a, b); +} + +// Computes the minima of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b) { + return vminq_f32(a, b); +} + +// Computes the approximations of reciprocals of the four single-precision, floating-point values of a. https://msdn.microsoft.com/en-us/library/vstudio/796k1tty(v=vs.100).aspx +FORCE_INLINE __m128 _mm_rcp_ps(__m128 in) { + __m128 recip = vrecpeq_f32(in); + recip = vmulq_f32(recip, vrecpsq_f32(recip, in)); + return recip; +} + +// Computes the approximations of square roots of the four single-precision, floating-point values of a. First computes reciprocal square roots and then reciprocals of the four values. https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in) { + __m128 recipsq = vrsqrteq_f32(in); + __m128 sq = vrecpeq_f32(recipsq); + // ??? use step versions of both sqrt and recip for better accuracy? + return sq; +} + +// Computes the maximums of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx +FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b) { + return vmaxq_f32(a, b); +} + +// Computes the bitwise AND of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b) { + return (__m128)vandq_s32((__m128i)a, (__m128i)b); +} + +// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b) { + return (__m128i)vandq_s32(a, b); +} + +// Computes the bitwise AND-NOT of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx +FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b) { + return (__m128)vbicq_s32((__m128i)b, (__m128i)a); // *NOTE* argument swap +} + +// Computes the bitwise OR of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx +FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b) { + return (__m128)vorrq_s32((__m128i)a, (__m128i)b); +} + +// Computes bitwise EXOR (exclusive-or) of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx +FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b) { + return (__m128)veorq_s32((__m128i)a, (__m128i)b); +} + +// Compares for greater than. https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b) { + return (__m128)vcgtq_f32(a, b); +} + +// Compares for less than https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b) { + return (__m128)vcltq_f32(a, b); +} + +// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers in b for greater than. https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b) { + return (__m128i)vcgtq_s32(a, b); +} + +// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers in b for less than. https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b) { + return (__m128i)vcltq_s32(a, b); +} + +// Converts the four signed 32-bit integer values of a to single-precision, floating-point values https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a) { + return vcvtq_f32_s32(a); +} + +// Converts the four single-precision, floating-point values of a to signed 32-bit integer values using truncate. https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a) { + return vcvtq_s32_f32(a); +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/wrappers.hpp b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/wrappers.hpp new file mode 100644 index 0000000..5cd70db --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/piotr/src/wrappers.hpp @@ -0,0 +1,78 @@ +/* +Copyright (c) 2012, Piotr Dollar +All rights reserved. + +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 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. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +/******************************************************************************* +* Piotr's Computer Vision Matlab Toolbox Version 3.00 +* Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] +* Licensed under the Simplified BSD License [see above] +* Project page: http://vision.ucsd.edu/~pdollar/toolbox/doc/ +* Original file: https://github.com/pdollar/toolbox/blob/612f9a0451a6abbe2a64768c9e6654692929102e/channels/private/wrappers.hpp + ++ author: Klaus Haag: Move external license into this source file +*******************************************************************************/ +#ifndef WRAPPERS_HPP_ +#define WRAPPERS_HPP_ + +#ifdef MATLAB_MEX_FILE + +// wrapper functions if compiling from Matlab +#include "mex.h" +inline void wrError(const char *errormsg) { mexErrMsgTxt(errormsg); } +inline void* wrCalloc(size_t num, size_t size) { return mxCalloc(num, size); } +inline void* wrMalloc(size_t size) { return mxMalloc(size); } +inline void wrFree(void * ptr) { mxFree(ptr); } + +#else + +#include +// wrapper functions if compiling from C/C++ +inline void wrError(const char *errormsg) { throw errormsg; } +inline void* wrCalloc(size_t num, size_t size) { return calloc(num, size); } +inline void* wrMalloc(size_t size) { return malloc(size); } +inline void wrFree(void * ptr) { free(ptr); } + +#endif + +// platform independent aligned memory allocation (see also alFree) +inline void* alMalloc(size_t size, int alignment) { + const size_t pSize = sizeof(void*); + const size_t a = alignment - 1; + void *raw = wrMalloc(size + a + pSize); + void *aligned = (void*)(((size_t)raw + pSize + a) & ~a); + *(void**)((size_t)aligned - pSize) = raw; + return aligned; +} + +// platform independent alignned memory de-allocation (see also alMalloc) +inline void alFree(void* aligned) { + const size_t pSize = sizeof(void*); + void* raw = *(void**)((char*)aligned - pSize); + wrFree(raw); +} +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/AUTHORS b/src/3rdparty/cf_tracking/src/3rdparty/tclap/AUTHORS new file mode 100644 index 0000000..875a852 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/AUTHORS @@ -0,0 +1,6 @@ + +original author: Michael E. Smoot +invaluable contributions: Daniel Aarno +more contributions: Erik Zeek +more contributions: Fabien Carmagnac (Tinbergen-AM) +outstanding editing: Carol Smoot diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/COPYING b/src/3rdparty/cf_tracking/src/3rdparty/tclap/COPYING new file mode 100644 index 0000000..987be0c --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/COPYING @@ -0,0 +1,25 @@ + + +Copyright (c) 2003 Michael E. Smoot + +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. + + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/ChangeLog b/src/3rdparty/cf_tracking/src/3rdparty/tclap/ChangeLog new file mode 100644 index 0000000..f117f71 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/ChangeLog @@ -0,0 +1,1760 @@ +2011-04-10 17:08 mes5k + + * include/tclap/Arg.h: patch that allows arg start strings to be + pound defined to easily conform to different platforms + +2011-04-09 11:58 mes5k + + * docs/Makefile.am: being slightly more precise about what we clean + +2011-04-09 11:30 mes5k + + * include/tclap/: DocBookOutput.h, StdOutput.h, + ZshCompletionOutput.h: fixed shadow variable name problem + +2011-04-09 11:05 mes5k + + * include/tclap/CmdLine.h: fixed minor memory leak + +2011-03-15 04:26 macbishop + + * configure.in, config/ac_cxx_warn_effective_cxx.m4: Check if + compiler supports Weffec++ and if so use it (fixes compilation + issue with e.g. SunStudio compiler) + +2011-01-15 09:45 macbishop + + * include/tclap/ArgTraits.h: Updated documentation for ArgTraits to + reference StringLike and ValueLike classes. + +2011-01-15 09:32 macbishop + + * examples/test10.cpp: Added explicit cast to supress warning about + deprecated conversion from string constant to char* + +2011-01-02 17:18 mes5k + + * docs/Makefile.am: now using a slightly different variable for doc + install to support out-of-tree builds + +2011-01-02 16:37 mes5k + + * configure.in: bumped version number to 1.2.1 + +2011-01-02 16:30 mes5k + + * docs/style.css: tweaked style so it doesn't blink + +2011-01-02 16:21 mes5k + + * tests/: test57.out, test57.sh, test76.out: tweaked tests to + reflect fix for mutually exclusive switches + +2011-01-02 16:20 mes5k + + * include/tclap/: SwitchArg.h, XorHandler.h: finally fixed bug + relating to mutually exclusive combined switched + +2011-01-02 15:12 mes5k + + * include/tclap/Arg.h: minor reformat + +2011-01-02 15:10 mes5k + + * include/tclap/CmdLine.h: minor reformatting + +2011-01-02 12:13 mes5k + + * examples/Makefile.am, examples/test20.cpp, tests/Makefile.am, + tests/test74.out, tests/test74.sh, tests/test75.out, + tests/test75.sh, tests/test76.out, tests/test76.sh, + tests/test77.out, tests/test77.sh: added failing tests for XOR + error message bug + +2011-01-02 11:52 mes5k + + * include/tclap/StandardTraits.h: applied Tom Fogal's win64 patch + for size_t + +2011-01-02 11:38 mes5k + + * docs/Makefile.am: hopefully fixed out-of-tree doc installation + +2011-01-02 10:50 mes5k + + * include/tclap/: Arg.h, ArgTraits.h, CmdLine.h, HelpVisitor.h, + MultiArg.h, ValueArg.h, ValuesConstraint.h, VersionVisitor.h, + XorHandler.h, ZshCompletionOutput.h: fixed all effective c++ + warnings based on patch from Andrew Marlow + +2010-12-06 22:41 mes5k + + * configure.in: added more compiler warnings + +2009-10-24 20:49 mes5k + + * include/tclap/SwitchArg.h, include/tclap/ValueArg.h, + tests/test22.out, tests/test24.out: make error message a bit more + meaningful + +2009-10-23 14:42 mes5k + + * include/tclap/StandardTraits.h: added a check for wchar_t to deal + with a potential problem with MS compilers + +2009-09-28 11:28 mes5k + + * docs/index.html: updated for 1.2.0 + +2009-09-26 14:41 mes5k + + * docs/Makefile.am: another update to support older automake + +2009-09-26 14:23 mes5k + + * docs/Makefile.am: removed an errant space + +2009-09-26 14:15 mes5k + + * docs/Makefile.am: added a definition for docdir, which doesnt + exist for old versions of automake + +2009-09-26 14:02 mes5k + + * docs/Makefile.am: corrected the doc install directory structure + +2009-09-26 13:55 mes5k + + * NEWS: updated for 1.2.0 + +2009-09-26 13:53 mes5k + + * docs/: manual.html, manual.xml: updated for 1.2.0 including text + on ArgTraits + +2009-08-22 12:26 mes5k + + * Makefile.am, configure.in, tclap.pc.in, docs/Makefile.am, + examples/Makefile.am: applying patches to make gnu compiler args + conditional, to install docs, and to add pkgconfig support to the + installation + +2009-07-28 12:49 mes5k + + * configure.in, tests/Makefile.am, tests/test73.out, + tests/test73.sh: added test 73 based on bug reported by user + +2009-07-15 08:09 mes5k + + * include/tclap/UnlabeledValueArg.h: updated incorrect api docs + again + +2009-07-15 08:04 mes5k + + * include/tclap/UnlabeledValueArg.h: updated incorrect api doc + +2009-01-09 16:10 mes5k + + * AUTHORS: added author + +2009-01-09 16:05 mes5k + + * include/tclap/: Arg.h, CmdLine.h, CmdLineInterface.h, MultiArg.h, + MultiSwitchArg.h, SwitchArg.h, ValueArg.h: added support for + resetting a command line + +2008-11-07 12:04 mes5k + + * docs/manual.html, docs/manual.xml, examples/Makefile.am, + examples/test19.cpp, include/tclap/Arg.h, tests/Makefile.am, + tests/test29.out, tests/test29.sh, tests/test71.out, + tests/test71.sh, tests/test72.out, tests/test72.sh: added support + for parsing hex and octal ints as well as small fix to support + gcc 4.4 + +2008-09-10 11:29 mes5k + + * docs/manual.xml: updated note on xor + +2008-09-10 11:21 mes5k + + * docs/manual.xml: added note on xor + +2008-08-19 15:18 zeekec + + * examples/test18.cpp, include/tclap/CmdLine.h, tests/Makefile.am, + tests/test70.out, tests/test70.sh: Rethrow ExitExceptions if + we're not handling exceptions. + +2008-08-19 14:52 zeekec + + * include/tclap/Arg.h: Silence some compiler warnings. The const + on return-by-value is ignored. + +2008-07-21 10:20 zeekec + + * include/tclap/CmdLine.h, examples/Makefile.am, + examples/test18.cpp, tests/Makefile.am, tests/test69.out, + tests/test69.sh: Allow internal handling of parse errors to be + turned off. This allows exceptions for parse errors to be + propagated to the caller. Exiting the program in parse is a bad + idea generally, as we have no way of knowing what cleanup needs + to be done in the main program. + +2008-06-17 09:48 mes5k + + * include/tclap/StdOutput.h: bug in while loop + +2008-05-23 15:15 mes5k + + * include/tclap/: CmdLine.h, SwitchArg.h: added length checks to + strings that can otherwise break with Metroworks compilers + +2008-05-21 14:21 macbishop + + * examples/: Makefile.am, test17-a.cpp, test17.cpp: Added test that + tclap does not define any hard symbols (bug 1907017) + +2008-05-13 12:04 mes5k + + * include/tclap/CmdLine.h: added a new include to support exit in + environments where it isnt defined + +2008-05-05 23:02 mes5k + + * examples/test7.cpp, include/tclap/Arg.h, tests/test46.out: + tweaked tests to support dashes in arg names + +2008-05-05 22:28 mes5k + + * include/tclap/Arg.h: allowed dash char in arg names + +2008-01-18 15:05 zeekec + + * include/tclap/Makefile.am: Added Traits files to the list of + files to be installed. + +2007-10-09 11:18 macbishop + + * examples/test14.cpp, examples/test15.cpp, examples/test16.cpp, + include/tclap/Arg.h, include/tclap/ArgTraits.h, + include/tclap/StandardTraits.h, configure.in, + config/ac_cxx_have_long_long.m4, examples/Makefile.am: + Refactoring of the arg-traits functionality. The purpose is to + make it easier to make you own classes, and types defined in the + standard library work well with tclap. I'll try to write up some + documenation of how to achieve this as-well. + +2007-10-01 23:33 mes5k + + * examples/test13.cpp: added attribution + +2007-10-01 23:30 mes5k + + * examples/test13.cpp: fixed a warning message + +2007-10-01 23:27 mes5k + + * examples/Makefile.am, examples/test13.cpp, + include/tclap/SwitchArg.h, tests/Makefile.am, tests/test68.out, + tests/test68.sh: a bug fix for parsing vectors of strings and + making sure that combined switches dont get confused + +2007-09-27 13:49 mes5k + + * include/tclap/OptionalUnlabeledTracker.h: added inline + +2007-09-12 19:09 mes5k + + * include/tclap/Arg.h, tests/test42.out, tests/test54.out: fixed + the delimiter in Arg::longID and Arg::shortID + +2007-09-01 01:17 macbishop + + * examples/Makefile.am, include/tclap/Arg.h, + include/tclap/DocBookOutput.h, + include/tclap/ZshCompletionOutput.h: Suppress some warnings, + compile with -Wextra by default + +2007-06-14 14:02 macbishop + + * include/tclap/Arg.h, include/tclap/MultiArg.h, + include/tclap/ValueArg.h, tests/runtests.sh, tests/test63.out, + tests/test63.sh, tests/test64.out, tests/test64.sh, + tests/test65.out, tests/test65.sh, tests/test66.out, + tests/test66.sh, tests/test67.out, tests/test67.sh, + tests/testCheck.sh, examples/Makefile.am, examples/test11.cpp, + examples/test12.cpp: Use ArgTraits instead of ValueExtractor + specialization Bug 1711487 + +2007-05-02 13:11 macbishop + + * examples/Makefile.am, examples/test10.cpp, + include/tclap/CmdLine.h, include/tclap/CmdLineInterface.h: Run + CmdLine::parse with argv as pointer to const pointer to const + char + +2007-04-20 22:28 mes5k + + * include/tclap/Arg.h, tests/test18.out: changed the blankChar to + the bell character instead of * + +2007-03-04 11:28 mes5k + + * examples/test4.cpp, include/tclap/DocBookOutput.h, + include/tclap/Makefile.am, include/tclap/ZshCompletionOutput.h: + added patches for ZSH and DocBook output + +2007-03-04 11:08 mes5k + + * include/tclap/: CmdLine.h, CmdLineInterface.h: added a new parse + method that accepts a vector + +2007-02-17 06:59 macbishop + + * include/tclap/: MultiArg.h, MultiSwitchArg.h, + UnlabeledMultiArg.h, UnlabeledValueArg.h, ValueArg.h: Supressed + some warnings + +2007-02-17 06:59 macbishop + + * include/tclap/CmdLine.h: Catch ExitException and exit. This + allows all resources used during parsing to be released, bug + 1662188. + +2007-02-17 06:57 macbishop + + * include/tclap/: DocBookOutput.h, HelpVisitor.h, StdOutput.h, + VersionVisitor.h: raise ExitException instead of calling exit + +2007-02-17 06:54 macbishop + + * include/tclap/ArgException.h: Added exit-exception class + +2007-02-17 06:52 macbishop + + * tests/testCheck.sh: Exit with exit status 1 if a test fails + (required by runtests.sh) + +2007-02-17 06:52 macbishop + + * tests/runtests.sh: Run the correct tests (not 0) + +2007-02-17 06:51 macbishop + + * examples/: test4.cpp, test7.cpp: Supressed warnings + +2007-02-07 18:12 mes5k + + * include/tclap/StdOutput.h: minor change to support a bug in + VisualC++ 2005 + +2006-11-26 10:42 mes5k + + * docs/: README, manual.html, manual.xml: updated docs to reflect + that Output must handle the exit rather than the CmdLine object + +2006-11-26 10:32 mes5k + + * include/tclap/: CmdLine.h, DocBookOutput.h, StdOutput.h: moved + exit from CmdLine to StdOutput to provide users more control over + when/how the exit happens + +2006-11-26 10:29 mes5k + + * examples/test4.cpp: added exit() to failure method + +2006-11-26 10:13 mes5k + + * docs/: manual.html, manual.xml: fixed typo in SwitchArg + constructors + +2006-11-04 14:05 mes5k + + * include/tclap/CmdLine.h, tests/Makefile.am, tests/test10.out, + tests/test17.out, tests/test4.out, tests/test51.out, + tests/test62.out, tests/test62.sh: printing more useful message + when missing required args and catching ArgException reference + +2006-10-06 09:49 mes5k + + * include/tclap/SwitchArg.h, tests/Makefile.am, tests/test61.out, + tests/test61.sh: made a fix for a bug where - chars were within + unlabeled value args + +2006-08-21 23:13 mes5k + + * include/tclap/StdOutput.h: minor tweak to a min function + signature + +2006-08-18 20:05 mes5k + + * docs/index.html: updated for 1.1.0 + +2006-08-18 20:04 mes5k + + * AUTHORS: new author + +2006-05-14 17:55 mes5k + + * config/Makefile.am: so that m4 macros will be included in release + files to ease incorporation of tclap in other projects + +2006-05-14 17:36 mes5k + + * include/tclap/CmdLine.h: removed a deprecated constructor + +2006-05-14 17:35 mes5k + + * docs/: manual.xml, manual.html: manual update + +2006-05-14 13:11 mes5k + + * Makefile.am, configure.in: added m4 macros to help others + distributing the software and updated the version number + +2006-05-14 12:52 mes5k + + * config/bb_enable_doxygen.m4: for some reason, the AS_HELP_STRING + function was messing up autoconf 2.57 -- maybe that's just an old + version? We can change it back as necessary + +2006-05-14 12:51 mes5k + + * examples/test8.cpp, include/tclap/SwitchArg.h: SwitchArg + interface change + +2006-04-18 03:59 macbishop + + * docs/: manual.html, manual.xml: Updated the example + +2006-04-05 23:44 mes5k + + * include/tclap/ArgException.h: patch for a mem leak in + ArgException + +2006-03-18 11:16 mes5k + + * include/tclap/: CmdLineOutput.h, Visitor.h: added virtual + destructors + +2006-02-21 18:15 zeekec + + * examples/: test1.cpp, test2.cpp, test3.cpp, test4.cpp, test5.cpp, + test6.cpp, test7.cpp, test8.cpp, test9.cpp: Use local header + files first instead of installed headers. + +2006-02-21 18:12 zeekec + + * Makefile.am: Added ACLOCAL_AMFLAGS for autoreconf. + +2006-02-21 18:10 zeekec + + * config/: ac_cxx_have_sstream.m4, ac_cxx_have_strstream.m4: Moved + the requires, header check, and language save and restore outside + of the cache check. + +2006-02-21 04:00 zeekec + + * config/: stamp-h.in, stamp-h1: Removed timestamp files (generated + by configure). + +2006-02-21 03:05 zeekec + + * include/tclap/Constraint.h: Added virtual destructor to silence + warnings. + +2006-02-21 03:01 zeekec + + * ChangeLog: Generated with cvs2cl. + +2005-09-10 16:25 mes5k + + * config/stamp-h1, examples/test2.cpp, examples/test3.cpp, + examples/test5.cpp, examples/test8.cpp, include/tclap/Arg.h, + include/tclap/CmdLine.h, include/tclap/MultiArg.h, + include/tclap/StdOutput.h, include/tclap/UnlabeledMultiArg.h, + include/tclap/UnlabeledValueArg.h, include/tclap/ValueArg.h, + include/tclap/XorHandler.h: added gcc warning patch + +2005-07-12 20:36 zeekec + + * examples/Makefile.am: Set INCLUDES to top_srcdir for out of + source builds. + +2005-07-12 20:33 zeekec + + * include/tclap/: UnlabeledMultiArg.h, UnlabeledValueArg.h: Add + using toString statements (for gcc >= 3.4). + +2005-07-12 20:31 zeekec + + * config/bb_enable_doxygen.m4: Properly quote BB_ENABLE_DOXYGEN. + +2005-06-29 15:04 mes5k + + * include/tclap/Arg.h: merged some new changes + +2005-06-08 08:28 mes5k + + * docs/index.html: fixed spelling mistake + +2005-06-02 19:35 mes5k + + * include/tclap/: Makefile.am, OptionalUnlabeledTracker.h, + UnlabeledMultiArg.h, UnlabeledValueArg.h: fix to handle optional + unlabeled args + +2005-06-02 19:33 mes5k + + * examples/: test2.cpp, test3.cpp, test7.cpp, test8.cpp, test9.cpp: + Unlabeled changes + +2005-02-03 15:04 mes5k + + * include/tclap/: Arg.h, DocBookOutput.h, MultiArg.h: updated + docbook output + +2005-02-03 08:08 mes5k + + * include/tclap/: ValuesConstraint.h, XorHandler.h: add std:: + prefix to some finds + +2005-02-01 13:35 zeekec + + * include/tclap/CmdLine.h: Made deleteOnExit's protected to + facilitate derivation. + +2005-02-01 13:30 zeekec + + * config/config.h.in: Removed autotools generated file. + +2005-01-28 13:26 zeekec + + * configure.in, docs/Doxyfile.in, tests/Makefile.am, + tests/test1.sh, tests/test10.sh, tests/test11.sh, + tests/test12.sh, tests/test13.sh, tests/test14.sh, + tests/test15.sh, tests/test16.sh, tests/test17.sh, + tests/test18.sh, tests/test19.sh, tests/test2.sh, + tests/test20.sh, tests/test21.sh, tests/test22.sh, + tests/test23.sh, tests/test24.sh, tests/test25.sh, + tests/test26.sh, tests/test27.sh, tests/test28.sh, + tests/test29.sh, tests/test3.sh, tests/test30.sh, + tests/test31.sh, tests/test32.sh, tests/test33.sh, + tests/test34.sh, tests/test35.sh, tests/test36.sh, + tests/test37.sh, tests/test38.sh, tests/test39.sh, + tests/test4.sh, tests/test40.sh, tests/test41.sh, + tests/test42.sh, tests/test43.sh, tests/test44.sh, + tests/test45.sh, tests/test46.sh, tests/test47.sh, + tests/test48.sh, tests/test49.sh, tests/test5.sh, + tests/test50.sh, tests/test51.sh, tests/test52.sh, + tests/test53.sh, tests/test54.sh, tests/test55.sh, + tests/test56.sh, tests/test57.sh, tests/test58.sh, + tests/test59.sh, tests/test6.sh, tests/test60.sh, tests/test7.sh, + tests/test8.sh, tests/test9.sh: Made changes to directory + references to allow out of source builds. + +2005-01-26 10:25 mes5k + + * aclocal.m4: doh + +2005-01-23 19:18 mes5k + + * include/tclap/CmdLine.h: removed -v from version switch + +2005-01-23 19:14 mes5k + + * include/tclap/Arg.h: removed value required + +2005-01-23 19:03 mes5k + + * examples/: test2.cpp, test3.cpp, test6.cpp, test8.cpp, test9.cpp: + UnlabeledValueArg change + +2005-01-23 19:02 mes5k + + * tests/: test10.out, test11.out, test12.out, test15.out, + test16.out, test17.out, test22.out, test23.out, test24.out, + test26.out, test27.out, test28.out, test29.out, test30.out, + test31.out, test32.out, test35.out, test36.out, test38.out, + test39.out, test4.out, test40.out, test41.out, test42.out, + test43.out, test44.out, test45.out, test46.out, test49.out, + test50.out, test51.out, test52.out, test53.out, test54.out, + test57.out, test59.out, test60.out, test7.out: new output for + default version and value required + +2005-01-23 19:01 mes5k + + * tests/: test59.sh, test8.sh: new style version and required + UnlabeledValueArgs + +2005-01-23 18:59 mes5k + + * tests/testCheck.sh: a script to compare test output + +2005-01-23 17:54 mes5k + + * include/tclap/UnlabeledValueArg.h: now optionally required + +2005-01-23 16:33 mes5k + + * tests/: test58.out, test59.out, test58.sh, test59.sh, test60.out, + test60.sh, Makefile.am: tests for MultiSwitchArg + +2005-01-23 16:27 mes5k + + * include/tclap/Makefile.am, examples/Makefile.am, + examples/test9.cpp: MultiSwitchArg + +2005-01-23 16:26 mes5k + + * include/tclap/: CmdLine.h, CmdLineInterface.h, StdOutput.h: added + a bool to the constructor that allows automatic -h and -v to be + turned off + +2005-01-23 14:57 mes5k + + * docs/: manual.html, manual.xml: added MultiSwitchArg docs + +2005-01-23 14:33 mes5k + + * include/tclap/MultiSwitchArg.h: fixed typo + +2005-01-23 14:29 mes5k + + * include/tclap/SwitchArg.h: Fixed minor bug involving combined + switch error messages: now they're consistent. + +2005-01-23 14:28 mes5k + + * include/tclap/MultiSwitchArg.h: initial checkin + +2005-01-22 20:41 mes5k + + * include/tclap/UnlabeledMultiArg.h: added alreadySet + +2005-01-20 20:13 mes5k + + * tests/Makefile.am: xor test + +2005-01-20 20:04 mes5k + + * examples/test5.cpp: change for xor bug + +2005-01-20 20:04 mes5k + + * tests/: test20.out, runtests.sh, test20.sh, test21.out, + test21.sh, test22.out, test23.out, test24.out, test25.out, + test25.sh, test33.out, test33.sh, test44.out, test57.out, + test57.sh: changes for xor bug + +2005-01-20 20:03 mes5k + + * include/tclap/: Arg.h, MultiArg.h, UnlabeledMultiArg.h, + XorHandler.h: fixed xor bug + +2005-01-17 12:48 macbishop + + * include/tclap/Arg.h: Removed check on description in + Arg::operator== since multiple args should be able to have the + same description. + +2005-01-06 20:41 mes5k + + * NEWS: updated for constraints + +2005-01-06 20:37 mes5k + + * docs/: manual.html, manual.xml: updated for constraints + +2005-01-06 20:05 mes5k + + * examples/test7.cpp: changed for constraint + +2005-01-06 20:00 mes5k + + * include/tclap/: MultiArg.h, ValueArg.h: fixed exceptions and + typeDesc for constraints + +2005-01-06 19:59 mes5k + + * tests/: test35.out, test36.out, test38.out, test39.out: changed + for constraints + +2005-01-06 19:07 mes5k + + * examples/test6.cpp: changed to constraint + +2005-01-06 19:06 mes5k + + * include/tclap/Makefile.am: added constraints + +2005-01-06 19:05 mes5k + + * include/tclap/: Constraint.h, ValuesConstraint.h: initial checkin + +2005-01-06 19:05 mes5k + + * include/tclap/StdOutput.h: comment change + +2005-01-06 19:01 mes5k + + * include/tclap/CmdLine.h: added Constraint includes + +2005-01-06 18:55 mes5k + + * include/tclap/: MultiArg.h, UnlabeledMultiArg.h, + UnlabeledValueArg.h, ValueArg.h: Changed allowedList to + Constraint + +2005-01-05 16:08 mes5k + + * configure.in: next vers + +2005-01-05 12:13 mes5k + + * NEWS: update + +2005-01-05 10:51 mes5k + + * docs/: manual.html, manual.xml: fixed output override bug + +2005-01-05 10:45 mes5k + + * tests/: test18.out, test43.out: change for output override bug + +2005-01-05 10:28 mes5k + + * examples/test4.cpp: fixed output override bug + +2005-01-05 10:22 mes5k + + * include/tclap/: CmdLine.h, HelpVisitor.h, VersionVisitor.h: fixed + output bug + +2005-01-04 14:01 mes5k + + * configure.in: 1.0.4 + +2005-01-04 13:16 mes5k + + * examples/test7.cpp: changed for long prog names bug + +2005-01-04 13:15 mes5k + + * tests/: test38.out, test39.out, test46.out: changed test7 for + long prog names + +2005-01-04 12:31 mes5k + + * NEWS: updates for 1.0.3a + +2005-01-04 12:21 mes5k + + * docs/manual.html, docs/manual.xml, include/tclap/CmdLine.h: fixed + output memory leak + +2004-12-08 21:10 mes5k + + * include/tclap/StdOutput.h: hacky fix to long prog name bug + +2004-12-07 19:57 mes5k + + * configure.in: 1.0.3a + +2004-12-07 19:53 mes5k + + * tests/: Makefile.am, test15.out, test16.out, test17.out, + test31.out, test32.out, test13.sh, test14.sh, test15.sh, + test16.sh, test17.sh, test42.out, test55.out, test55.sh, + test56.out, test56.sh: updated for - arg bug + +2004-12-07 19:51 mes5k + + * examples/test3.cpp: tweaked to support tests for '-' arg bug + +2004-12-07 18:16 mes5k + + * include/tclap/Arg.h: fixed a bug involving blank _flags and - as + an UnlabeledValueArg + +2004-12-03 12:19 mes5k + + * docs/style.css: minor tweak for h1 + +2004-12-03 12:10 mes5k + + * NEWS: update + +2004-12-03 11:39 mes5k + + * include/tclap/CmdLine.h: removed ostream include + +2004-11-30 19:11 mes5k + + * include/tclap/: Arg.h, CmdLine.h, CmdLineOutput.h, StdOutput.h: + cleaned up iterator names + +2004-11-30 19:10 mes5k + + * include/tclap/DocBookOutput.h: removed ostream + +2004-11-30 18:35 mes5k + + * configure.in, docs/Doxyfile.in: added dot check + +2004-11-24 19:58 mes5k + + * configure.in: 1.0.3 + +2004-11-24 19:57 mes5k + + * include/tclap/: UnlabeledMultiArg.h, UnlabeledValueArg.h: removed + two stage lookup ifdefs + +2004-11-24 19:56 mes5k + + * docs/index.html: updated + +2004-11-24 19:45 mes5k + + * docs/: manual.html, manual.xml: updates for using stuff and new + output + +2004-11-05 21:05 mes5k + + * include/tclap/: DocBookOutput.h, Makefile.am: adding docbook + stuff + +2004-11-04 21:07 mes5k + + * examples/test4.cpp: reflects new output handling + +2004-11-04 21:07 mes5k + + * include/tclap/: Arg.h, CmdLine.h, CmdLineInterface.h, + CmdLineOutput.h, HelpVisitor.h, Makefile.am, StdOutput.h, + VersionVisitor.h, XorHandler.h: changed output around + +2004-11-04 21:06 mes5k + + * include/tclap/PrintSensibly.h: subsumed by StdOutput + +2004-10-31 14:13 mes5k + + * docs/manual.html: tweak + +2004-10-30 15:58 mes5k + + * NEWS, README: updates + +2004-10-30 15:51 mes5k + + * docs/Makefile.am: added manual.xml + +2004-10-30 15:47 mes5k + + * docs/: manual.html, manual.xml, style.css: minor tweaks + +2004-10-30 15:34 mes5k + + * configure.in: 1.0.2 + +2004-10-30 15:30 mes5k + + * docs/README: init + +2004-10-30 15:30 mes5k + + * docs/style.css: new style + +2004-10-30 15:30 mes5k + + * docs/: manual.html, manual.xml: manual.html is now generated from + manual.xml + +2004-10-30 15:26 mes5k + + * include/tclap/: MultiArg.h, ValueArg.h: yet another fix for + HAVE_SSTREAM stuff + +2004-10-30 08:42 mes5k + + * NEWS: 1.0.1 + +2004-10-30 08:03 mes5k + + * configure.in: new release + +2004-10-28 09:41 mes5k + + * include/tclap/: ValueArg.h, MultiArg.h: fixed config.h problems + +2004-10-27 19:44 mes5k + + * docs/manual.xml: manual as docbook + +2004-10-22 08:56 mes5k + + * docs/style.css: added visited color to links + +2004-10-22 07:38 mes5k + + * docs/index.html: fixed mailto + +2004-10-21 18:58 mes5k + + * docs/: manual.html: minor tweaks + +2004-10-21 18:13 mes5k + + * docs/manual.html: updated for new test1 + +2004-10-21 18:02 mes5k + + * include/tclap/CmdLine.h: catch by ref + +2004-10-21 18:01 mes5k + + * examples/: test1.cpp, test2.cpp, test3.cpp, test4.cpp, test5.cpp, + test6.cpp, test7.cpp, test8.cpp: changed test1 and now catching + exceptions by ref + +2004-10-21 17:38 mes5k + + * tests/: test1.out, test1.sh, test2.out, test3.out, test3.sh, + test4.out, test40.out: changes for new test1 + +2004-10-21 15:50 mes5k + + * examples/test1.cpp: fixed includes + +2004-10-21 10:03 mes5k + + * docs/index.html: changed link + +2004-10-21 09:02 mes5k + + * include/tclap/: ValueArg.h, MultiArg.h: changed enum names + because of alpha conflicts + +2004-10-20 20:04 mes5k + + * include/tclap/: CmdLine.h, CmdLineInterface.h, MultiArg.h, + PrintSensibly.h, SwitchArg.h, UnlabeledMultiArg.h, + UnlabeledValueArg.h, ValueArg.h, XorHandler.h: cleaned up some + includes and added ifdefs for sstream + +2004-10-20 19:00 mes5k + + * examples/test5.cpp: fixed a bizarre bug + +2004-10-20 18:59 mes5k + + * tests/: test20.out, test21.out, test25.out, test33.out: fixed a + test5 bug + +2004-10-20 16:17 mes5k + + * Makefile.am: added msc + +2004-10-20 16:06 mes5k + + * configure.in: added msc stuff + +2004-10-20 16:05 mes5k + + * msc/: examples/Makefile.am, Makefile.am: init + +2004-10-20 16:00 mes5k + + * NEWS: update + +2004-10-20 15:58 mes5k + + * msc/README: init + +2004-10-20 15:47 mes5k + + * msc/: tclap-beta.ncb, tclap-beta.sln, tclap-beta.suo, + tclap-beta.vcproj, examples/test1.vcproj, examples/test2.vcproj, + examples/test3.vcproj, examples/test4.vcproj, + examples/test5.vcproj, examples/test6.vcproj, + examples/test7.vcproj, examples/test8.vcproj: init + +2004-10-19 11:18 mes5k + + * docs/Makefile.am: added stylesheet + +2004-10-19 10:51 mes5k + + * AUTHORS: more + +2004-10-19 10:39 mes5k + + * NEWS, AUTHORS: added 1.0 notes + +2004-10-14 13:04 mes5k + + * examples/test4.cpp: shows how to alter output + +2004-10-14 13:03 mes5k + + * tests/test18.out: updated output + +2004-10-14 12:03 mes5k + + * include/tclap/CmdLineInterface.h: added failure to the interface + +2004-10-14 11:07 mes5k + + * include/tclap/ArgException.h: doh. now what() is proper + +2004-10-14 10:44 mes5k + + * include/tclap/CmdLine.h: made destructor virtual + +2004-10-14 10:20 mes5k + + * include/tclap/CmdLine.h: moved all output handling into separate + methods + +2004-10-14 10:19 mes5k + + * include/tclap/Arg.h: made processArg pure virtual + +2004-10-14 10:19 mes5k + + * include/tclap/ArgException.h: fixed documentation omission + +2004-10-12 14:09 mes5k + + * docs/style.css: tweak + +2004-10-07 11:22 mes5k + + * docs/style.css: color change + +2004-10-01 10:54 mes5k + + * include/tclap/ArgException.h: added type description + +2004-09-30 18:16 mes5k + + * docs/: index.html, manual.html, style.css: added CSS style + +2004-09-30 09:17 mes5k + + * docs/manual.html: more updates + +2004-09-29 08:24 mes5k + + * docs/: index.html, manual.html: proofing updates + +2004-09-27 14:37 mes5k + + * docs/: index.html, manual.html: xhtml and tidied + +2004-09-27 14:36 mes5k + + * docs/Doxyfile.in: added dot handling + +2004-09-27 14:30 mes5k + + * include/tclap/: Arg.h, ArgException.h, CmdLine.h, MultiArg.h, + SwitchArg.h, ValueArg.h: added new Exception classes + +2004-09-27 12:53 mes5k + + * include/tclap/ArgException.h: minor tweaks + +2004-09-26 19:32 mes5k + + * docs/manual.html: updates yet again + +2004-09-26 19:00 mes5k + + * docs/manual.html: updates + +2004-09-26 18:50 mes5k + + * docs/manual.html: substantial updates + +2004-09-26 16:54 mes5k + + * include/tclap/: Arg.h, CmdLine.h, CmdLineInterface.h, MultiArg.h, + PrintSensibly.h, ValueArg.h: minor formatting + +2004-09-26 15:50 mes5k + + * docs/manual.html: updates + +2004-09-26 15:17 mes5k + + * tests/runtests.sh: minor fix so that we run all tests + +2004-09-26 11:51 macbishop + + * docs/Doxyfile.in: Removed src subdir + +2004-09-26 11:49 macbishop + + * examples/Makefile.am: Removed libtclap.a deps + +2004-09-26 11:46 macbishop + + * configure.in: Removed creation of src/Makefile + +2004-09-26 11:34 macbishop + + * Makefile.am: Removed src subdir + +2004-09-26 11:31 macbishop + + * src/: Arg.cpp, CmdLine.cpp, Makefile.am, PrintSensibly.cpp, + SwitchArg.cpp, XorHandler.cpp: Implementation now in header files + +2004-09-26 11:27 macbishop + + * include/tclap/: Arg.h, ArgException.h, CmdLine.h, HelpVisitor.h, + Makefile.am, MultiArg.h, PrintSensibly.h, SwitchArg.h, + UnlabeledMultiArg.h, UnlabeledValueArg.h, ValueArg.h, + VersionVisitor.h, XorHandler.h, CmdLineInterface.h, + CommandLine.h: Moving the implementation of tclap to the header + files presented me with two major problems. 1) There where static + functions and variables that could cause link errors if tclap + where used in different files (e.g. file1.cc and file2.cc + included tclap then compiling both files would give hard symbols + for some variables which would produce multiple definition when + linking) 2) The dependencies of tclap was a bit strange (CmdLine + depends on Args and Args depends on CmdLine for instance) + + The first problem I solved by removing all static variables + putting them in static member functions (which are weak-symbols). + So for instance every where there previously was something like x + = _delimiter there now is x = delimiter() or in case of write + acces delimiterRef() = x instead of _delimiter = x (I had to + append the Ref because there where already functions with the + same name as the variables). To solve the problem with static + functions I simply inlined them. This causes the compiler to + produce a weak symbol or inline if appropriate. We can put the + functions inside the class declaration later to make the code + look better. This worked fine in all but two cases. In the + ValueArg and MultiArg classes I had to do a "hack" to work around + the specialization template for extractValue. The + code for this is very simple but it might look strange an stupid + at first but it is only to resolve the specialisation to a weak + symbol. What I did was I put the implementations of extractValue + in a helper class and I could then create a specialized class + instead of function and everything worked out. I think now in + retrospect there might be better solutions to this but I'll think + a bit more on it (maybe some type of inlining on the specialized + version would suffice but I'm not sure). + + To handle the dependencies I had to do some rewriting. The first + step was to introduce a new class CmdLineInterface that is a + purely abstract base of CmdLine that specifies the functions + needed by Arg and friends. Thus Arg classes now takes an + CmdLineInterface object as input instead (however only CmdLine + can ever be instantiated of-course). With this extra class + cleaning up the dependencies was quite simple, I've attached a + dependency graph to the mail (depgraph.png). I also cleaned up + the #includes so now only what actually needs inclusion is + included. A nice side effect of this is that the impl. of CmdLine + is now put back into CmdLine.h (where I guess you wanted it) + which (recursivly) includes everything else needed. + + Just to make things clear for myself regarding the class + dependencies I made a class TCLAP::Exception that inherits from + std::exception and is a base of ArgException (Exception does + nothing currently). If we don't want the Exception class it can + be removed, however I think it could be a nice logic to have a + base Exception class that every exception inherits from, but we + can discuss that when we decide how to handle exceptions. + +2004-09-26 08:07 macbishop + + * tests/runtests.sh: Now return 0 if all tests fail and 1 if any + test fail + +2004-09-26 07:58 macbishop + + * tests/runtests.sh: Runs all tests and sumarizes the result + +2004-09-20 17:09 mes5k + + * include/tclap/CommandLine.h: added some comments + +2004-09-20 17:08 mes5k + + * src/CmdLine.cpp: formatting only + +2004-09-20 10:05 macbishop + + * include/tclap/CommandLine.h: Recommit because something is + strange. The changes are that memory allocated in _construct is + deallocated when the CmdLine obj is destroyed + +2004-09-19 11:32 macbishop + + * src/CmdLine.cpp: Memory allocated in _constructor is now deleted + when the object is destroyed + +2004-09-18 09:54 mes5k + + * include/tclap/: Arg.h, ArgException.h, CmdLine.h, CommandLine.h, + HelpVisitor.h, IgnoreRestVisitor.h, MultiArg.h, PrintSensibly.h, + SwitchArg.h, UnlabeledMultiArg.h, UnlabeledValueArg.h, + ValueArg.h, VersionVisitor.h, Visitor.h, XorHandler.h: changed + ifndef labels + +2004-09-18 07:53 macbishop + + * include/tclap/Arg.h: Had to make ~Arg() public because it won't + be possible to delete Arg*s if it is not, and we want that (I + think). + +2004-09-15 21:24 mes5k + + * configure.in: version 1.0.0 + +2004-09-15 20:54 mes5k + + * include/tclap/Arg.h, include/tclap/ArgException.h, + include/tclap/HelpVisitor.h, include/tclap/IgnoreRestVisitor.h, + include/tclap/MultiArg.h, include/tclap/SwitchArg.h, + include/tclap/UnlabeledMultiArg.h, include/tclap/ValueArg.h, + include/tclap/VersionVisitor.h, include/tclap/Visitor.h, + src/Arg.cpp, src/SwitchArg.cpp: cleaned up a bunch of things + +2004-09-11 19:35 mes5k + + * tests/: Makefile.am, test47.out, test47.sh, test48.out, + test48.sh, test49.out, test49.sh, test50.out, test50.sh, + test51.out, test51.sh, test52.out, test52.sh, test53.out, + test53.sh, test54.out, test54.sh: added tests for CmdLine arg + +2004-09-11 19:33 mes5k + + * examples/: Makefile.am, test8.cpp: added new test for CmdLine arg + +2004-09-11 19:32 mes5k + + * src/Arg.cpp, src/SwitchArg.cpp, include/tclap/Arg.h, + include/tclap/MultiArg.h, include/tclap/SwitchArg.h, + include/tclap/UnlabeledMultiArg.h, + include/tclap/UnlabeledValueArg.h, include/tclap/ValueArg.h: got + CmdLine arg working + +2004-09-09 19:08 mes5k + + * configure: shouldn't be in cvs + +2004-09-09 12:56 macbishop + + * src/: Arg.cpp, SwitchArg.cpp: Added support for automatic + addition to a CmdLine parser + +2004-09-09 12:55 macbishop + + * include/tclap/: Arg.h, MultiArg.h, SwitchArg.h, + UnlabeledMultiArg.h, UnlabeledValueArg.h, ValueArg.h: Support for + automatic addition to a CmdLine parser + +2004-09-08 20:09 mes5k + + * src/CmdLine.cpp: fixed a warning in MSVC++ + +2004-09-07 16:11 mes5k + + * include/tclap/Makefile.in, docs/Makefile.in, + examples/Makefile.in, tests/Makefile.in: not needed + +2004-09-07 16:08 mes5k + + * Makefile.in, src/Makefile.in, include/Makefile.in: not needed + +2004-09-07 15:14 mes5k + + * src/CmdLine.cpp: now throws exception on matching + names/flags/desc + +2004-09-07 15:12 mes5k + + * examples/test4.cpp, examples/test7.cpp, tests/test38.out, + tests/test39.out, tests/test43.out, tests/test46.out: fixed to + handle new exception on matching names/flags/desc + +2004-09-07 13:25 mes5k + + * docs/Doxyfile.in: updated Doxyfile for newer doxygen + +2004-09-07 11:27 mes5k + + * examples/: test1.cpp, test2.cpp, test3.cpp, test4.cpp, test5.cpp, + test6.cpp: changed namespace std handling + +2004-09-07 11:25 mes5k + + * examples/test7.cpp: added more args to better test output + printing + +2004-09-07 11:24 mes5k + + * src/Arg.cpp, src/CmdLine.cpp, src/PrintSensibly.cpp, + src/SwitchArg.cpp, src/XorHandler.cpp, include/tclap/Arg.h, + include/tclap/ArgException.h, include/tclap/CommandLine.h, + include/tclap/MultiArg.h, include/tclap/PrintSensibly.h, + include/tclap/SwitchArg.h, include/tclap/UnlabeledMultiArg.h, + include/tclap/UnlabeledValueArg.h, include/tclap/ValueArg.h, + include/tclap/XorHandler.h: changed namespace std handling + +2004-09-07 11:24 mes5k + + * tests/: test15.out, test16.out, test17.out, test22.out, + test23.out, test24.out, test31.out, test32.out, test38.out, + test39.out, test42.out, test44.out, test46.out: fixed test output + for new formatting + +2004-09-04 14:09 macbishop + + * include/tclap/: UnlabeledMultiArg.h, UnlabeledValueArg.h: + Compilation was broken due to undef. symbols in compilers with 2 + stage name-lookup (such as gcc >= 3.4). The fix for this is to + tell the compiler what symbols to use withlines like: using + MultiArg::_name; + + This is now done and everything compiles fine. Since I'm not sure + about the support for things like using MultiArg::_name; on + all compilers it is ifdef:ed away by default. To get 2 stage + name-lookup to work you have to add -DTWO_STAGE_NAME_LOOKUP to + your CXXFLAGS before running configure. + +2004-08-18 12:34 mes5k + + * src/PrintSensibly.cpp: smartened printing even further + +2004-08-10 20:35 mes5k + + * src/PrintSensibly.cpp: fixed int messiness + +2004-08-10 20:32 mes5k + + * autotools.sh: made path explicit + +2004-08-10 20:05 mes5k + + * include/tclap/: MultiArg.h, ValueArg.h: changed allowed separator + +2004-08-10 19:53 mes5k + + * tests/: Makefile.am, test10.out, test11.out, test12.out, + test15.out, test16.out, test17.out, test18.out, test22.out, + test23.out, test24.out, test26.out, test27.out, test28.out, + test29.out, test30.out, test31.out, test32.out, test35.out, + test36.out, test38.out, test39.out, test4.out, test40.out, + test40.sh, test41.out, test41.sh, test42.out, test42.sh, + test43.out, test43.sh, test44.out, test44.sh, test45.out, + test45.sh, test46.out, test46.sh, test7.out, test7.sh: changed + error output and added usage stuff + +2004-08-10 19:52 mes5k + + * NEWS, README: updated + +2004-08-10 19:47 mes5k + + * configure.in: changed to 0.9.9 + +2004-08-10 19:46 mes5k + + * examples/test7.cpp: tweaked for usage + +2004-08-10 19:45 mes5k + + * include/tclap/: CmdLine.h, CommandLine.h, Makefile.am, + PrintSensibly.h, XorHandler.h: added usage stuff + +2004-08-10 19:43 mes5k + + * src/: CmdLine.cpp, Makefile.am, PrintSensibly.cpp, + XorHandler.cpp: tweaked usage + +2004-07-05 19:02 mes5k + + * docs/manual.html: updated for allowed + +2004-07-03 20:01 mes5k + + * tests/: test34.out, test34.sh, test35.out, test35.sh, test36.out, + test36.sh, test37.out, test37.sh, test38.out, test38.sh, + test39.out, test39.sh, Makefile.am: allow tests + +2004-07-03 19:56 mes5k + + * include/tclap/ValueArg.h: doh + +2004-07-03 19:34 mes5k + + * NEWS: allow + +2004-07-03 19:31 mes5k + + * include/tclap/Arg.h: made isReq virtual + +2004-07-03 19:30 mes5k + + * include/tclap/: MultiArg.h, UnlabeledMultiArg.h, + UnlabeledValueArg.h, ValueArg.h: added allow + +2004-07-03 19:29 mes5k + + * examples/: Makefile.am, test6.cpp, test7.cpp: added tests for + allowed + +2004-07-03 19:28 mes5k + + * docs/: index.html, manual.html: minor typos + +2004-04-26 08:18 mes5k + + * Makefile.am, autotools.sh, examples/Makefile.am, src/Makefile.am: + fixed for autotools for mandrake + +2004-02-13 20:09 mes5k + + * configure.in: 0.9.8a + +2004-02-13 15:23 mes5k + + * tests/: test22.out, test23.out, test24.out: output updates + +2004-02-13 15:21 mes5k + + * include/tclap/: Arg.h, UnlabeledMultiArg.h, UnlabeledValueArg.h: + now the Arg adds itself to the CmdLine arglist + +2004-02-13 15:20 mes5k + + * src/: Arg.cpp, CmdLine.cpp: reworked how we add args to list + +2004-02-10 08:52 mes5k + + * NEWS: update + +2004-02-09 21:04 mes5k + + * examples/test5.cpp: change + +2004-02-09 21:03 mes5k + + * src/SwitchArg.cpp: allowing blank flags + +2004-02-09 20:54 mes5k + + * configure.in: 0.9.8 + +2004-02-09 20:52 mes5k + + * tests/: Makefile.am, test20.out, test21.out, test22.out, + test23.out, test24.out, test25.out, test33.out, test33.sh: + updates + +2004-02-09 20:39 mes5k + + * docs/manual.html: blank args + +2004-02-09 20:16 mes5k + + * tests/: test15.out, test16.out, test17.out, test20.out, + test20.sh, test21.out, test21.sh, test22.out, test23.out, + test24.out, test25.out, test25.sh, test31.out, test32.out: + updates + +2004-02-09 20:05 mes5k + + * examples/: test5.cpp, test3.cpp: minor fixes and new args + +2004-02-09 19:56 mes5k + + * include/tclap/Arg.h: added new var + +2004-02-09 19:54 mes5k + + * src/: Arg.cpp, CmdLine.cpp, SwitchArg.cpp: allowing blank flags + +2004-02-07 15:37 mes5k + + * src/XorHandler.cpp: fix for the output + +2004-02-06 17:41 mes5k + + * NEWS: added info + +2004-02-06 17:24 mes5k + + * tests/: test12.out, test15.out, test16.out, test17.out: fixed + test3 stuff + +2004-02-06 17:20 mes5k + + * tests/: test26.out, test26.sh, test27.out, test27.sh, test28.out, + test28.sh, test29.out, test29.sh, test30.out, test30.sh, + test31.out, test31.sh, test32.out, test32.sh, Makefile.am: added + tests for reading extra incorrect values from arg + +2004-02-06 17:18 mes5k + + * examples/test3.cpp: add multi float + +2004-02-06 17:18 mes5k + + * include/tclap/: MultiArg.h, ValueArg.h: fixed error reading + incorrect extra values in an arg + +2004-02-04 18:56 mes5k + + * include/tclap/XorHandler.h: added include + +2004-02-03 20:21 mes5k + + * include/tclap/XorHandler.h: added doxyen + +2004-02-03 20:00 mes5k + + * docs/manual.html: xor stuff + +2004-02-03 19:56 mes5k + + * examples/test5.cpp: prettified + +2004-02-03 19:27 mes5k + + * examples/: Makefile.am, test5.cpp: xor stuff + +2004-02-03 19:24 mes5k + + * configure.in: 0.9.7 + +2004-02-03 19:22 mes5k + + * src/: Arg.cpp, CmdLine.cpp, Makefile.am, XorHandler.cpp: added + xor + +2004-02-03 19:20 mes5k + + * include/tclap/: Arg.h, CmdLine.h, CommandLine.h, + UnlabeledValueArg.h, XorHandler.h, Makefile.am: xor stuff + +2004-02-03 19:14 mes5k + + * tests/: test1.sh, test10.sh, test11.sh, test12.sh, test13.sh, + test14.sh, test15.sh, test16.sh, test17.sh, test18.sh, test19.sh, + test2.sh, test20.sh, test21.sh, test22.sh, test23.sh, test24.sh, + test25.sh, test3.sh, test4.sh, test5.sh, test6.sh, test7.sh, + test8.sh, test9.sh, Makefile.am, test20.out, test21.out, + test22.out, test23.out, test24.out, test25.out: added new tests + and comments + +2004-01-29 20:36 mes5k + + * include/tclap/: CmdLine.h, CommandLine.h, MultiArg.h, ValueArg.h: + fix for strings with spaces + +2004-01-10 09:39 mes5k + + * docs/index.html: spelling + +2004-01-07 22:18 mes5k + + * docs/: index.html, manual.html: updates + +2004-01-07 21:51 mes5k + + * NEWS: update + +2004-01-07 21:30 mes5k + + * include/tclap/CmdLine.h, src/CmdLine.cpp: added backward + compatibility + +2004-01-07 21:11 mes5k + + * src/Arg.cpp: fixed warning + +2004-01-07 21:04 mes5k + + * examples/: Makefile.am, test4.cpp: added new test + +2004-01-07 21:00 mes5k + + * tests/Makefile.am: added two new tests + +2004-01-07 20:59 mes5k + + * include/tclap/: Arg.h, ArgException.h, CmdLine.h, HelpVisitor.h, + IgnoreRestVisitor.h, MultiArg.h, SwitchArg.h, + UnlabeledMultiArg.h, UnlabeledValueArg.h, ValueArg.h, + VersionVisitor.h, Visitor.h: fixed combined switch stuff and + added doxygen comments + +2004-01-07 20:58 mes5k + + * src/: Arg.cpp, CmdLine.cpp, SwitchArg.cpp: fixed some combined + switch stuff + +2004-01-07 20:50 mes5k + + * tests/: test18.out, test18.sh, test19.out, test19.sh: new tests + +2003-12-21 18:32 mes5k + + * autotools.sh: init + +2003-12-21 18:31 mes5k + + * include/tclap/UnlabeledMultiArg.h: delim stuff + +2003-12-21 18:14 mes5k + + * examples/test1.cpp: new fangled + +2003-12-21 18:11 mes5k + + * configure.in: 0.9.6 + +2003-12-21 18:10 mes5k + + * tests/: test13.sh, test14.sh: updated + +2003-12-21 18:09 mes5k + + * tests/: test10.out, test11.out, test12.out, test13.out, + test14.out, test15.out, test16.out, test4.out: updates + +2003-12-21 18:07 mes5k + + * tests/Makefile.am: added test + +2003-12-21 18:06 mes5k + + * tests/: test17.out, test17.sh: first checkin + +2003-12-21 18:01 mes5k + + * src/Arg.cpp: removed message + +2003-12-21 17:59 mes5k + + * examples/Makefile.am: added warnings + +2003-12-21 17:58 mes5k + + * examples/: test2.cpp, test3.cpp: fixed warnings + +2003-12-21 17:53 mes5k + + * Makefile.am: added warnings + +2003-12-21 17:52 mes5k + + * src/Arg.cpp, src/CmdLine.cpp, src/SwitchArg.cpp, + examples/test3.cpp: added delimiter + +2003-12-21 17:50 mes5k + + * src/Makefile.am: added warnings + +2003-12-21 17:48 mes5k + + * include/tclap/: Arg.h, ArgException.h, CmdLine.h, MultiArg.h, + UnlabeledValueArg.h, ValueArg.h: delimiter changes + +2003-04-03 10:26 mes5k + + * include/tclap/Makefile.am: added new visitor + +2003-04-03 10:20 mes5k + + * include/tclap/Makefile.am: updates + +2003-04-03 10:13 mes5k + + * config/: mkinstalldirs, install-sh, missing, depcomp: init + checkin + +2003-04-03 10:11 mes5k + + * NEWS: update + +2003-04-03 10:06 mes5k + + * examples/Makefile.am, examples/test1.cpp, examples/test2.cpp, + examples/test3.cpp, INSTALL, Makefile.in: updates + +2003-04-03 10:01 mes5k + + * Makefile.am, configure.in: added tests + +2003-04-03 10:00 mes5k + + * docs/: index.html, manual.html: updated docs + +2003-04-03 09:59 mes5k + + * include/tclap/: Arg.h, CmdLine.h, IgnoreRestVisitor.h, + MultiArg.h, SwitchArg.h, UnlabeledMultiArg.h, + UnlabeledValueArg.h, ValueArg.h: big update + +2003-04-03 09:57 mes5k + + * src/: CmdLine.cpp, SwitchArg.cpp, Arg.cpp: new update + +2003-04-03 09:56 mes5k + + * tests/: test10.sh, test11.sh, test12.sh, test1.sh, test13.sh, + test14.sh, test15.sh, test16.sh, test2.sh, test3.sh, test4.sh, + test5.sh, test6.sh, test7.sh, test8.sh, test9.sh, test10.out, + test11.out, test12.out, test13.out, test14.out, test15.out, + test16.out, test1.out, test2.out, test3.out, test4.out, + test5.out, test6.out, test7.out, Makefile.am, test8.out, + test9.out, Makefile.in, genOut.pl: initial checkin + +2003-03-18 18:39 mes5k + + * NEWS, configure.in, AUTHORS, COPYING, ChangeLog, Makefile.am, + Makefile.in, README, aclocal.m4, configure, + config/ac_cxx_have_sstream.m4, config/ac_cxx_have_strstream.m4, + config/ac_cxx_namespaces.m4, config/bb_enable_doxygen.m4, + config/config.h.in, config/stamp-h.in, config/stamp-h1, + examples/Makefile.am, examples/Makefile.in, examples/test1.cpp, + examples/test2.cpp, include/Makefile.am, include/Makefile.in, + include/tclap/Arg.h, include/tclap/ArgException.h, + include/tclap/CmdLine.h, include/tclap/HelpVisitor.h, + include/tclap/MultiArg.h, docs/Doxyfile.in, docs/Makefile.am, + docs/Makefile.in, docs/index.html, docs/manual.html, + include/tclap/Makefile.am, include/tclap/Makefile.in, + include/tclap/SwitchArg.h, include/tclap/ValueArg.h, + include/tclap/VersionVisitor.h, include/tclap/Visitor.h, + src/Arg.cpp, src/CmdLine.cpp, src/Makefile.am, src/Makefile.in, + src/SwitchArg.cpp: Initial revision + +2003-03-18 18:39 mes5k + + * NEWS, configure.in, AUTHORS, COPYING, ChangeLog, Makefile.am, + Makefile.in, README, aclocal.m4, configure, + config/ac_cxx_have_sstream.m4, config/ac_cxx_have_strstream.m4, + config/ac_cxx_namespaces.m4, config/bb_enable_doxygen.m4, + config/config.h.in, config/stamp-h.in, config/stamp-h1, + examples/Makefile.am, examples/Makefile.in, examples/test1.cpp, + examples/test2.cpp, include/Makefile.am, include/Makefile.in, + include/tclap/Arg.h, include/tclap/ArgException.h, + include/tclap/CmdLine.h, include/tclap/HelpVisitor.h, + include/tclap/MultiArg.h, docs/Doxyfile.in, docs/Makefile.am, + docs/Makefile.in, docs/index.html, docs/manual.html, + include/tclap/Makefile.am, include/tclap/Makefile.in, + include/tclap/SwitchArg.h, include/tclap/ValueArg.h, + include/tclap/VersionVisitor.h, include/tclap/Visitor.h, + src/Arg.cpp, src/CmdLine.cpp, src/Makefile.am, src/Makefile.in, + src/SwitchArg.cpp: initial release + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/INSTALL b/src/3rdparty/cf_tracking/src/3rdparty/tclap/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.am b/src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.am new file mode 100644 index 0000000..766f299 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = tclap diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.in b/src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.in new file mode 100644 index 0000000..7c0898f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.in @@ -0,0 +1,460 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = include +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/ac_cxx_have_long_long.m4 \ + $(top_srcdir)/config/ac_cxx_have_sstream.m4 \ + $(top_srcdir)/config/ac_cxx_have_strstream.m4 \ + $(top_srcdir)/config/ac_cxx_namespaces.m4 \ + $(top_srcdir)/config/ac_cxx_warn_effective_cxx.m4 \ + $(top_srcdir)/config/bb_enable_doxygen.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WARN_EFFECTIVE_CXX = @WARN_EFFECTIVE_CXX@ +WARN_NO_EFFECTIVE_CXX = @WARN_NO_EFFECTIVE_CXX@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = tclap +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-exec-am: + +install-html: install-html-recursive + +install-info: install-info-recursive + +install-man: + +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/README b/src/3rdparty/cf_tracking/src/3rdparty/tclap/README new file mode 100644 index 0000000..225e33f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/README @@ -0,0 +1,16 @@ + +TCLAP - Templatized Command Line Argument Parser + +This is a simple C++ library that facilitates parsing command line +arguments in a type independent manner. It doesn't conform exactly +to either the GNU or POSIX standards, although it is close. See +docs/manual.html for descriptions of how things work or look at the +simple examples in the examples dir. + +To find out what the latest changes are read the NEWS file in this directory. + + +Any and all feedback is welcome to: Mike Smoot + + + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Arg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Arg.h new file mode 100644 index 0000000..b28eef1 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Arg.h @@ -0,0 +1,692 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: Arg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARGUMENT_H +#define TCLAP_ARGUMENT_H + +#ifdef HAVE_CONFIG_H +#include +#else +#define HAVE_SSTREAM +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_SSTREAM) +#include +typedef std::istringstream istringstream; +#elif defined(HAVE_STRSTREAM) +#include +typedef std::istrstream istringstream; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +#include +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A virtual base class that defines the essential data for all arguments. + * This class, or one of its existing children, must be subclassed to do + * anything. + */ +class Arg +{ + private: + /** + * Prevent accidental copying. + */ + Arg(const Arg& rhs); + + /** + * Prevent accidental copying. + */ + Arg& operator=(const Arg& rhs); + + /** + * Indicates whether the rest of the arguments should be ignored. + */ + static bool& ignoreRestRef() { static bool ign = false; return ign; } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char& delimiterRef() { static char delim = ' '; return delim; } + + protected: + + /** + * The single char flag used to identify the argument. + * This value (preceded by a dash {-}), can be used to identify + * an argument on the command line. The _flag can be blank, + * in fact this is how unlabeled args work. Unlabeled args must + * override appropriate functions to get correct handling. Note + * that the _flag does NOT include the dash as part of the flag. + */ + std::string _flag; + + /** + * A single work namd indentifying the argument. + * This value (preceded by two dashed {--}) can also be used + * to identify an argument on the command line. Note that the + * _name does NOT include the two dashes as part of the _name. The + * _name cannot be blank. + */ + std::string _name; + + /** + * Description of the argument. + */ + std::string _description; + + /** + * Indicating whether the argument is required. + */ + bool _required; + + /** + * Label to be used in usage description. Normally set to + * "required", but can be changed when necessary. + */ + std::string _requireLabel; + + /** + * Indicates whether a value is required for the argument. + * Note that the value may be required but the argument/value + * combination may not be, as specified by _required. + */ + bool _valueRequired; + + /** + * Indicates whether the argument has been set. + * Indicates that a value on the command line has matched the + * name/flag of this argument and the values have been set accordingly. + */ + bool _alreadySet; + + /** + * A pointer to a vistitor object. + * The visitor allows special handling to occur as soon as the + * argument is matched. This defaults to NULL and should not + * be used unless absolutely necessary. + */ + Visitor* _visitor; + + /** + * Whether this argument can be ignored, if desired. + */ + bool _ignoreable; + + /** + * Indicates that the arg was set as part of an XOR and not on the + * command line. + */ + bool _xorSet; + + bool _acceptsMultipleValues; + + /** + * Performs the special handling described by the Vistitor. + */ + void _checkWithVisitor() const; + + /** + * Primary constructor. YOU (yes you) should NEVER construct an Arg + * directly, this is a base class that is extended by various children + * that are meant to be used. Use SwitchArg, ValueArg, MultiArg, + * UnlabeledValueArg, or UnlabeledMultiArg instead. + * + * \param flag - The flag identifying the argument. + * \param name - The name identifying the argument. + * \param desc - The description of the argument, used in the usage. + * \param req - Whether the argument is required. + * \param valreq - Whether the a value is required for the argument. + * \param v - The visitor checked by the argument. Defaults to NULL. + */ + Arg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v = NULL ); + + public: + /** + * Destructor. + */ + virtual ~Arg(); + + /** + * Adds this to the specified list of Args. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list& argList ) const; + + /** + * Begin ignoring arguments since the "--" argument was specified. + */ + static void beginIgnoring() { ignoreRestRef() = true; } + + /** + * Whether to ignore the rest. + */ + static bool ignoreRest() { return ignoreRestRef(); } + + /** + * The delimiter that separates an argument flag/name from the + * value. + */ + static char delimiter() { return delimiterRef(); } + + /** + * The char used as a place holder when SwitchArgs are combined. + * Currently set to the bell char (ASCII 7). + */ + static char blankChar() { return (char)7; } + + /** + * The char that indicates the beginning of a flag. Defaults to '-', but + * clients can define TCLAP_FLAGSTARTCHAR to override. + */ +#ifndef TCLAP_FLAGSTARTCHAR +#define TCLAP_FLAGSTARTCHAR '-' +#endif + static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; } + + /** + * The sting that indicates the beginning of a flag. Defaults to "-", but + * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same + * as TCLAP_FLAGSTARTCHAR. + */ +#ifndef TCLAP_FLAGSTARTSTRING +#define TCLAP_FLAGSTARTSTRING "-" +#endif + static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; } + + /** + * The sting that indicates the beginning of a name. Defaults to "--", but + * clients can define TCLAP_NAMESTARTSTRING to override. + */ +#ifndef TCLAP_NAMESTARTSTRING +#define TCLAP_NAMESTARTSTRING "--" +#endif + static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; } + + /** + * The name used to identify the ignore rest argument. + */ + static const std::string ignoreNameString() { return "ignore_rest"; } + + /** + * Sets the delimiter for all arguments. + * \param c - The character that delimits flags/names from values. + */ + static void setDelimiter( char c ) { delimiterRef() = c; } + + /** + * Pure virtual method meant to handle the parsing and value assignment + * of the string on the command line. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. What is + * passed in from main. + */ + virtual bool processArg(int *i, std::vector& args) = 0; + + /** + * Operator ==. + * Equality operator. Must be virtual to handle unlabeled args. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Returns the argument flag. + */ + const std::string& getFlag() const; + + /** + * Returns the argument name. + */ + const std::string& getName() const; + + /** + * Returns the argument description. + */ + std::string getDescription() const; + + /** + * Indicates whether the argument is required. + */ + virtual bool isRequired() const; + + /** + * Sets _required to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void forceRequired(); + + /** + * Sets the _alreadySet value to true. This is used by the XorHandler. + * You really have no reason to ever use it. + */ + void xorSet(); + + /** + * Indicates whether a value must be specified for argument. + */ + bool isValueRequired() const; + + /** + * Indicates whether the argument has already been set. Only true + * if the arg has been matched on the command line. + */ + bool isSet() const; + + /** + * Indicates whether the argument can be ignored, if desired. + */ + bool isIgnoreable() const; + + /** + * A method that tests whether a string matches this argument. + * This is generally called by the processArg() method. This + * method could be re-implemented by a child to change how + * arguments are specified on the command line. + * \param s - The string to be compared to the flag/name to determine + * whether the arg matches. + */ + virtual bool argMatches( const std::string& s ) const; + + /** + * Returns a simple string representation of the argument. + * Primarily for debugging. + */ + virtual std::string toString() const; + + /** + * Returns a short ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string shortID( const std::string& valueId = "val" ) const; + + /** + * Returns a long ID for the usage. + * \param valueId - The value used in the id. + */ + virtual std::string longID( const std::string& valueId = "val" ) const; + + /** + * Trims a value off of the flag. + * \param flag - The string from which the flag and value will be + * trimmed. Contains the flag once the value has been trimmed. + * \param value - Where the value trimmed from the string will + * be stored. + */ + virtual void trimFlag( std::string& flag, std::string& value ) const; + + /** + * Checks whether a given string has blank chars, indicating that + * it is a combined SwitchArg. If so, return true, otherwise return + * false. + * \param s - string to be checked. + */ + bool _hasBlanks( const std::string& s ) const; + + /** + * Sets the requireLabel. Used by XorHandler. You shouldn't ever + * use this. + * \param s - Set the requireLabel to this value. + */ + void setRequireLabel( const std::string& s ); + + /** + * Used for MultiArgs and XorHandler to determine whether args + * can still be set. + */ + virtual bool allowMore(); + + /** + * Use by output classes to determine whether an Arg accepts + * multiple values. + */ + virtual bool acceptsMultipleValues(); + + /** + * Clears the Arg object and allows it to be reused by new + * command lines. + */ + virtual void reset(); +}; + +/** + * Typedef of an Arg list iterator. + */ +typedef std::list::iterator ArgListIterator; + +/** + * Typedef of an Arg vector iterator. + */ +typedef std::vector::iterator ArgVectorIterator; + +/** + * Typedef of a Visitor list iterator. + */ +typedef std::list::iterator VisitorListIterator; + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * ValueLike traits use operator>> to assign the value from strVal. + */ +template void +ExtractValue(T &destVal, const std::string& strVal, ValueLike vl) +{ + static_cast(vl); // Avoid warning about unused vl + std::istringstream is(strVal); + + int valuesRead = 0; + while ( is.good() ) { + if ( is.peek() != EOF ) +#ifdef TCLAP_SETBASE_ZERO + is >> std::setbase(0) >> destVal; +#else + is >> destVal; +#endif + else + break; + + valuesRead++; + } + + if ( is.fail() ) + throw( ArgParseException("Couldn't read argument value " + "from string '" + strVal + "'")); + + + if ( valuesRead > 1 ) + throw( ArgParseException("More than one valid value parsed from " + "string '" + strVal + "'")); + +} + +/* + * Extract a value of type T from it's string representation contained + * in strVal. The ValueLike parameter used to select the correct + * specialization of ExtractValue depending on the value traits of T. + * StringLike uses assignment (operator=) to assign from strVal. + */ +template void +ExtractValue(T &destVal, const std::string& strVal, StringLike sl) +{ + static_cast(sl); // Avoid warning about unused sl + SetString(destVal, strVal); +} + +////////////////////////////////////////////////////////////////////// +//BEGIN Arg.cpp +////////////////////////////////////////////////////////////////////// + +inline Arg::Arg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + bool valreq, + Visitor* v) : + _flag(flag), + _name(name), + _description(desc), + _required(req), + _requireLabel("required"), + _valueRequired(valreq), + _alreadySet(false), + _visitor( v ), + _ignoreable(true), + _xorSet(false), + _acceptsMultipleValues(false) +{ + if ( _flag.length() > 1 ) + throw(SpecificationException( + "Argument flag can only be one character long", toString() ) ); + + if ( _name != ignoreNameString() && + ( _flag == Arg::flagStartString() || + _flag == Arg::nameStartString() || + _flag == " " ) ) + throw(SpecificationException("Argument flag cannot be either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or a space.", + toString() ) ); + + if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) || + ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) || + ( _name.find( " ", 0 ) != std::string::npos ) ) + throw(SpecificationException("Argument name begin with either '" + + Arg::flagStartString() + "' or '" + + Arg::nameStartString() + "' or space.", + toString() ) ); + +} + +inline Arg::~Arg() { } + +inline std::string Arg::shortID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + id = Arg::flagStartString() + _flag; + else + id = Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + if ( !_required ) + id = "[" + id + "]"; + + return id; +} + +inline std::string Arg::longID( const std::string& valueId ) const +{ + std::string id = ""; + + if ( _flag != "" ) + { + id += Arg::flagStartString() + _flag; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + id += ", "; + } + + id += Arg::nameStartString() + _name; + + if ( _valueRequired ) + id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">"; + + return id; + +} + +inline bool Arg::operator==(const Arg& a) const +{ + if ( ( _flag != "" && _flag == a._flag ) || _name == a._name) + return true; + else + return false; +} + +inline std::string Arg::getDescription() const +{ + std::string desc = ""; + if ( _required ) + desc = "(" + _requireLabel + ") "; + +// if ( _valueRequired ) +// desc += "(value required) "; + + desc += _description; + return desc; +} + +inline const std::string& Arg::getFlag() const { return _flag; } + +inline const std::string& Arg::getName() const { return _name; } + +inline bool Arg::isRequired() const { return _required; } + +inline bool Arg::isValueRequired() const { return _valueRequired; } + +inline bool Arg::isSet() const +{ + if ( _alreadySet && !_xorSet ) + return true; + else + return false; +} + +inline bool Arg::isIgnoreable() const { return _ignoreable; } + +inline void Arg::setRequireLabel( const std::string& s) +{ + _requireLabel = s; +} + +inline bool Arg::argMatches( const std::string& argFlag ) const +{ + if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) || + argFlag == Arg::nameStartString() + _name ) + return true; + else + return false; +} + +inline std::string Arg::toString() const +{ + std::string s = ""; + + if ( _flag != "" ) + s += Arg::flagStartString() + _flag + " "; + + s += "(" + Arg::nameStartString() + _name + ")"; + + return s; +} + +inline void Arg::_checkWithVisitor() const +{ + if ( _visitor != NULL ) + _visitor->visit(); +} + +/** + * Implementation of trimFlag. + */ +inline void Arg::trimFlag(std::string& flag, std::string& value) const +{ + int stop = 0; + for ( int i = 0; static_cast(i) < flag.length(); i++ ) + if ( flag[i] == Arg::delimiter() ) + { + stop = i; + break; + } + + if ( stop > 1 ) + { + value = flag.substr(stop+1); + flag = flag.substr(0,stop); + } + +} + +/** + * Implementation of _hasBlanks. + */ +inline bool Arg::_hasBlanks( const std::string& s ) const +{ + for ( int i = 1; static_cast(i) < s.length(); i++ ) + if ( s[i] == Arg::blankChar() ) + return true; + + return false; +} + +inline void Arg::forceRequired() +{ + _required = true; +} + +inline void Arg::xorSet() +{ + _alreadySet = true; + _xorSet = true; +} + +/** + * Overridden by Args that need to added to the end of the list. + */ +inline void Arg::addToList( std::list& argList ) const +{ + argList.push_front( const_cast(this) ); +} + +inline bool Arg::allowMore() +{ + return false; +} + +inline bool Arg::acceptsMultipleValues() +{ + return _acceptsMultipleValues; +} + +inline void Arg::reset() +{ + _xorSet = false; + _alreadySet = false; +} + +////////////////////////////////////////////////////////////////////// +//END Arg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgException.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgException.h new file mode 100644 index 0000000..3411aa9 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgException.h @@ -0,0 +1,200 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgException.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_ARG_EXCEPTION_H +#define TCLAP_ARG_EXCEPTION_H + +#include +#include + +namespace TCLAP { + +/** + * A simple class that defines and argument exception. Should be caught + * whenever a CmdLine is created and parsed. + */ +class ArgException : public std::exception +{ + public: + + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source. + * \param td - Text describing the type of ArgException it is. + * of the exception. + */ + ArgException( const std::string& text = "undefined exception", + const std::string& id = "undefined", + const std::string& td = "Generic ArgException") + : std::exception(), + _errorText(text), + _argId( id ), + _typeDescription(td) + { } + + /** + * Destructor. + */ + virtual ~ArgException() throw() { } + + /** + * Returns the error text. + */ + std::string error() const { return ( _errorText ); } + + /** + * Returns the argument id. + */ + std::string argId() const + { + if ( _argId == "undefined" ) + return " "; + else + return ( "Argument: " + _argId ); + } + + /** + * Returns the arg id and error text. + */ + const char* what() const throw() + { + static std::string ex; + ex = _argId + " -- " + _errorText; + return ex.c_str(); + } + + /** + * Returns the type of the exception. Used to explain and distinguish + * between different child exceptions. + */ + std::string typeDescription() const + { + return _typeDescription; + } + + + private: + + /** + * The text of the exception message. + */ + std::string _errorText; + + /** + * The argument related to this exception. + */ + std::string _argId; + + /** + * Describes the type of the exception. Used to distinguish + * between different child exceptions. + */ + std::string _typeDescription; + +}; + +/** + * Thrown from within the child Arg classes when it fails to properly + * parse the argument it has been passed. + */ +class ArgParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + ArgParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found while parsing " ) + + std::string( "the value the Arg has been passed." )) + { } +}; + +/** + * Thrown from CmdLine when the arguments on the command line are not + * properly specified, e.g. too many arguments, required argument missing, etc. + */ +class CmdLineParseException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + CmdLineParseException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string( "Exception found when the values ") + + std::string( "on the command line do not meet ") + + std::string( "the requirements of the defined ") + + std::string( "Args." )) + { } +}; + +/** + * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. + * same flag as another Arg, same name, etc. + */ +class SpecificationException : public ArgException +{ + public: + /** + * Constructor. + * \param text - The text of the exception. + * \param id - The text identifying the argument source + * of the exception. + */ + SpecificationException( const std::string& text = "undefined exception", + const std::string& id = "undefined" ) + : ArgException( text, + id, + std::string("Exception found when an Arg object ")+ + std::string("is improperly defined by the ") + + std::string("developer." )) + { } + +}; + +class ExitException { +public: + ExitException(int estat) : _estat(estat) {} + + int getExitStatus() const { return _estat; } + +private: + int _estat; +}; + +} // namespace TCLAP + +#endif + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgTraits.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgTraits.h new file mode 100644 index 0000000..0b2c18f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgTraits.h @@ -0,0 +1,87 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ArgTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * 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. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_ARGTRAITS_H +#define TCLAP_ARGTRAITS_H + +namespace TCLAP { + +// We use two empty structs to get compile type specialization +// function to work + +/** + * A value like argument value type is a value that can be set using + * operator>>. This is the default value type. + */ +struct ValueLike { + typedef ValueLike ValueCategory; + virtual ~ValueLike() {} +}; + +/** + * A string like argument value type is a value that can be set using + * operator=(string). Usefull if the value type contains spaces which + * will be broken up into individual tokens by operator>>. + */ +struct StringLike { + virtual ~StringLike() {} +}; + +/** + * A class can inherit from this object to make it have string like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct StringLikeTrait { + typedef StringLike ValueCategory; + virtual ~StringLikeTrait() {} +}; + +/** + * A class can inherit from this object to make it have value like + * traits. This is a compile time thing and does not add any overhead + * to the inherenting class. + */ +struct ValueLikeTrait { + typedef ValueLike ValueCategory; + virtual ~ValueLikeTrait() {} +}; + +/** + * Arg traits are used to get compile type specialization when parsing + * argument values. Using an ArgTraits you can specify the way that + * values gets assigned to any particular type during parsing. The two + * supported types are StringLike and ValueLike. + */ +template +struct ArgTraits { + typedef typename T::ValueCategory ValueCategory; + virtual ~ArgTraits() {} + //typedef ValueLike ValueCategory; +}; + +#endif + +} // namespace diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLine.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLine.h new file mode 100644 index 0000000..0fec8d8 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLine.h @@ -0,0 +1,633 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: CmdLine.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINE_H +#define TCLAP_CMDLINE_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include // Needed for exit(), which isn't defined in some envs. + +namespace TCLAP { + +template void DelPtr(T ptr) +{ + delete ptr; +} + +template void ClearContainer(C &c) +{ + typedef typename C::value_type value_type; + std::for_each(c.begin(), c.end(), DelPtr); + c.clear(); +} + + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLine : public CmdLineInterface +{ + protected: + + /** + * The list of arguments that will be tested against the + * command line. + */ + std::list _argList; + + /** + * The name of the program. Set to argv[0]. + */ + std::string _progName; + + /** + * A message used to describe the program. Used in the usage output. + */ + std::string _message; + + /** + * The version to be displayed with the --version switch. + */ + std::string _version; + + /** + * The number of arguments that are required to be present on + * the command line. This is set dynamically, based on the + * Args added to the CmdLine object. + */ + int _numRequired; + + /** + * The character that is used to separate the argument flag/name + * from the value. Defaults to ' ' (space). + */ + char _delimiter; + + /** + * The handler that manages xoring lists of args. + */ + XorHandler _xorHandler; + + /** + * A list of Args to be explicitly deleted when the destructor + * is called. At the moment, this only includes the three default + * Args. + */ + std::list _argDeleteOnExitList; + + /** + * A list of Visitors to be explicitly deleted when the destructor + * is called. At the moment, these are the Vistors created for the + * default Args. + */ + std::list _visitorDeleteOnExitList; + + /** + * Object that handles all output for the CmdLine. + */ + CmdLineOutput* _output; + + /** + * Should CmdLine handle parsing exceptions internally? + */ + bool _handleExceptions; + + /** + * Throws an exception listing the missing args. + */ + void missingArgsException(); + + /** + * Checks whether a name/flag string matches entirely matches + * the Arg::blankChar. Used when multiple switches are combined + * into a single argument. + * \param s - The message to be used in the usage. + */ + bool _emptyCombined(const std::string& s); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Arg* ptr); + + /** + * Perform a delete ptr; operation on ptr when this object is deleted. + */ + void deleteOnExit(Visitor* ptr); + +private: + + /** + * Prevent accidental copying. + */ + CmdLine(const CmdLine& rhs); + CmdLine& operator=(const CmdLine& rhs); + + /** + * Encapsulates the code common to the constructors + * (which is all of it). + */ + void _constructor(); + + + /** + * Is set to true when a user sets the output object. We use this so + * that we don't delete objects that are created outside of this lib. + */ + bool _userSetOutput; + + /** + * Whether or not to automatically create help and version switches. + */ + bool _helpAndVersion; + + public: + + /** + * Command line constructor. Defines how the arguments will be + * parsed. + * \param message - The message to be used in the usage + * output. + * \param delimiter - The character that is used to separate + * the argument flag/name from the value. Defaults to ' ' (space). + * \param version - The version number to be used in the + * --version switch. + * \param helpAndVersion - Whether or not to create the Help and + * Version switches. Defaults to true. + */ + CmdLine(const std::string& message, + const char delimiter = ' ', + const std::string& version = "none", + bool helpAndVersion = true); + + /** + * Deletes any resources allocated by a CmdLine object. + */ + virtual ~CmdLine(); + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + void add( Arg& a ); + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + void add( Arg* a ); + + /** + * Add two Args that will be xor'd. If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + void xorAdd( Arg& a, Arg& b ); + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + void xorAdd( std::vector& xors ); + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + void parse(int argc, const char * const * argv); + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector& args); + + /** + * + */ + CmdLineOutput* getOutput(); + + /** + * + */ + void setOutput(CmdLineOutput* co); + + /** + * + */ + std::string& getVersion(); + + /** + * + */ + std::string& getProgramName(); + + /** + * + */ + std::list& getArgList(); + + /** + * + */ + XorHandler& getXorHandler(); + + /** + * + */ + char getDelimiter(); + + /** + * + */ + std::string& getMessage(); + + /** + * + */ + bool hasHelpAndVersion(); + + /** + * Disables or enables CmdLine's internal parsing exception handling. + * + * @param state Should CmdLine handle parsing exceptions internally? + */ + void setExceptionHandling(const bool state); + + /** + * Returns the current state of the internal exception handling. + * + * @retval true Parsing exceptions are handled internally. + * @retval false Parsing exceptions are propagated to the caller. + */ + bool getExceptionHandling() const; + + /** + * Allows the CmdLine object to be reused. + */ + void reset(); + +}; + + +/////////////////////////////////////////////////////////////////////////////// +//Begin CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + +inline CmdLine::CmdLine(const std::string& m, + char delim, + const std::string& v, + bool help ) + : + _argList(std::list()), + _progName("not_set_yet"), + _message(m), + _version(v), + _numRequired(0), + _delimiter(delim), + _xorHandler(XorHandler()), + _argDeleteOnExitList(std::list()), + _visitorDeleteOnExitList(std::list()), + _output(0), + _handleExceptions(true), + _userSetOutput(false), + _helpAndVersion(help) +{ + _constructor(); +} + +inline CmdLine::~CmdLine() +{ + ClearContainer(_argDeleteOnExitList); + ClearContainer(_visitorDeleteOnExitList); + + if ( !_userSetOutput ) { + delete _output; + _output = 0; + } +} + +inline void CmdLine::_constructor() +{ + _output = new StdOutput; + + Arg::setDelimiter( _delimiter ); + + Visitor* v; + + if ( _helpAndVersion ) + { + v = new HelpVisitor( this, &_output ); + SwitchArg* help = new SwitchArg("h","help", + "Displays usage information and exits.", + false, v); + add( help ); + deleteOnExit(help); + deleteOnExit(v); + + v = new VersionVisitor( this, &_output ); + SwitchArg* vers = new SwitchArg("","version", + "Displays version information and exits.", + false, v); + add( vers ); + deleteOnExit(vers); + deleteOnExit(v); + } + + v = new IgnoreRestVisitor(); + SwitchArg* ignore = new SwitchArg(Arg::flagStartString(), + Arg::ignoreNameString(), + "Ignores the rest of the labeled arguments following this flag.", + false, v); + add( ignore ); + deleteOnExit(ignore); + deleteOnExit(v); +} + +inline void CmdLine::xorAdd( std::vector& ors ) +{ + _xorHandler.add( ors ); + + for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++) + { + (*it)->forceRequired(); + (*it)->setRequireLabel( "OR required" ); + add( *it ); + } +} + +inline void CmdLine::xorAdd( Arg& a, Arg& b ) +{ + std::vector ors; + ors.push_back( &a ); + ors.push_back( &b ); + xorAdd( ors ); +} + +inline void CmdLine::add( Arg& a ) +{ + add( &a ); +} + +inline void CmdLine::add( Arg* a ) +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + if ( *a == *(*it) ) + throw( SpecificationException( + "Argument with same flag/name already exists!", + a->longID() ) ); + + a->addToList( _argList ); + + if ( a->isRequired() ) + _numRequired++; +} + + +inline void CmdLine::parse(int argc, const char * const * argv) +{ + // this step is necessary so that we have easy access to + // mutable strings. + std::vector args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + + parse(args); +} + +inline void CmdLine::parse(std::vector& args) +{ + bool shouldExit = false; + int estat = 0; + + try { + _progName = args.front(); + args.erase(args.begin()); + + int requiredCount = 0; + + for (int i = 0; static_cast(i) < args.size(); i++) + { + bool matched = false; + for (ArgListIterator it = _argList.begin(); + it != _argList.end(); it++) { + if ( (*it)->processArg( &i, args ) ) + { + requiredCount += _xorHandler.check( *it ); + matched = true; + break; + } + } + + // checks to see if the argument is an empty combined + // switch and if so, then we've actually matched it + if ( !matched && _emptyCombined( args[i] ) ) + matched = true; + + if ( !matched && !Arg::ignoreRest() ) + throw(CmdLineParseException("Couldn't find match " + "for argument", + args[i])); + } + + if ( requiredCount < _numRequired ) + missingArgsException(); + + if ( requiredCount > _numRequired ) + throw(CmdLineParseException("Too many arguments!")); + + } catch ( ArgException& e ) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + try { + _output->failure(*this,e); + } catch ( ExitException &ee ) { + estat = ee.getExitStatus(); + shouldExit = true; + } + } catch (ExitException &ee) { + // If we're not handling the exceptions, rethrow. + if ( !_handleExceptions) { + throw; + } + + estat = ee.getExitStatus(); + shouldExit = true; + } + + if (shouldExit) + exit(estat); +} + +inline bool CmdLine::_emptyCombined(const std::string& s) +{ + if ( s.length() > 0 && s[0] != Arg::flagStartChar() ) + return false; + + for ( int i = 1; static_cast(i) < s.length(); i++ ) + if ( s[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline void CmdLine::missingArgsException() +{ + int count = 0; + + std::string missingArgList; + for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) + { + if ( (*it)->isRequired() && !(*it)->isSet() ) + { + missingArgList += (*it)->getName(); + missingArgList += ", "; + count++; + } + } + missingArgList = missingArgList.substr(0,missingArgList.length()-2); + + std::string msg; + if ( count > 1 ) + msg = "Required arguments missing: "; + else + msg = "Required argument missing: "; + + msg += missingArgList; + + throw(CmdLineParseException(msg)); +} + +inline void CmdLine::deleteOnExit(Arg* ptr) +{ + _argDeleteOnExitList.push_back(ptr); +} + +inline void CmdLine::deleteOnExit(Visitor* ptr) +{ + _visitorDeleteOnExitList.push_back(ptr); +} + +inline CmdLineOutput* CmdLine::getOutput() +{ + return _output; +} + +inline void CmdLine::setOutput(CmdLineOutput* co) +{ + if ( !_userSetOutput ) + delete _output; + _userSetOutput = true; + _output = co; +} + +inline std::string& CmdLine::getVersion() +{ + return _version; +} + +inline std::string& CmdLine::getProgramName() +{ + return _progName; +} + +inline std::list& CmdLine::getArgList() +{ + return _argList; +} + +inline XorHandler& CmdLine::getXorHandler() +{ + return _xorHandler; +} + +inline char CmdLine::getDelimiter() +{ + return _delimiter; +} + +inline std::string& CmdLine::getMessage() +{ + return _message; +} + +inline bool CmdLine::hasHelpAndVersion() +{ + return _helpAndVersion; +} + +inline void CmdLine::setExceptionHandling(const bool state) +{ + _handleExceptions = state; +} + +inline bool CmdLine::getExceptionHandling() const +{ + return _handleExceptions; +} + +inline void CmdLine::reset() +{ + for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ ) + (*it)->reset(); + + _progName.clear(); +} + +/////////////////////////////////////////////////////////////////////////////// +//End CmdLine.cpp +/////////////////////////////////////////////////////////////////////////////// + + + +} //namespace TCLAP +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineInterface.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineInterface.h new file mode 100644 index 0000000..1b25e9b --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineInterface.h @@ -0,0 +1,150 @@ + +/****************************************************************************** + * + * file: CmdLineInterface.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_COMMANDLINE_INTERFACE_H +#define TCLAP_COMMANDLINE_INTERFACE_H + +#include +#include +#include +#include +#include + + +namespace TCLAP { + +class Arg; +class CmdLineOutput; +class XorHandler; + +/** + * The base class that manages the command line definition and passes + * along the parsing to the appropriate Arg classes. + */ +class CmdLineInterface +{ + public: + + /** + * Destructor + */ + virtual ~CmdLineInterface() {} + + /** + * Adds an argument to the list of arguments to be parsed. + * \param a - Argument to be added. + */ + virtual void add( Arg& a )=0; + + /** + * An alternative add. Functionally identical. + * \param a - Argument to be added. + */ + virtual void add( Arg* a )=0; + + /** + * Add two Args that will be xor'd. + * If this method is used, add does + * not need to be called. + * \param a - Argument to be added and xor'd. + * \param b - Argument to be added and xor'd. + */ + virtual void xorAdd( Arg& a, Arg& b )=0; + + /** + * Add a list of Args that will be xor'd. If this method is used, + * add does not need to be called. + * \param xors - List of Args to be added and xor'd. + */ + virtual void xorAdd( std::vector& xors )=0; + + /** + * Parses the command line. + * \param argc - Number of arguments. + * \param argv - Array of arguments. + */ + virtual void parse(int argc, const char * const * argv)=0; + + /** + * Parses the command line. + * \param args - A vector of strings representing the args. + * args[0] is still the program name. + */ + void parse(std::vector& args); + + /** + * Returns the CmdLineOutput object. + */ + virtual CmdLineOutput* getOutput()=0; + + /** + * \param co - CmdLineOutput object that we want to use instead. + */ + virtual void setOutput(CmdLineOutput* co)=0; + + /** + * Returns the version string. + */ + virtual std::string& getVersion()=0; + + /** + * Returns the program name string. + */ + virtual std::string& getProgramName()=0; + + /** + * Returns the argList. + */ + virtual std::list& getArgList()=0; + + /** + * Returns the XorHandler. + */ + virtual XorHandler& getXorHandler()=0; + + /** + * Returns the delimiter string. + */ + virtual char getDelimiter()=0; + + /** + * Returns the message string. + */ + virtual std::string& getMessage()=0; + + /** + * Indicates whether or not the help and version switches were created + * automatically. + */ + virtual bool hasHelpAndVersion()=0; + + /** + * Resets the instance as if it had just been constructed so that the + * instance can be reused. + */ + virtual void reset()=0; +}; + +} //namespace + + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineOutput.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineOutput.h new file mode 100644 index 0000000..71ee5a3 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineOutput.h @@ -0,0 +1,74 @@ + + +/****************************************************************************** + * + * file: CmdLineOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CMDLINEOUTPUT_H +#define TCLAP_CMDLINEOUTPUT_H + +#include +#include +#include +#include +#include +#include + +namespace TCLAP { + +class CmdLineInterface; +class ArgException; + +/** + * The interface that any output object must implement. + */ +class CmdLineOutput +{ + + public: + + /** + * Virtual destructor. + */ + virtual ~CmdLineOutput() {} + + /** + * Generates some sort of output for the USAGE. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for the version. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c)=0; + + /** + * Generates some sort of output for a failure. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure( CmdLineInterface& c, + ArgException& e )=0; + +}; + +} //namespace TCLAP +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Constraint.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Constraint.h new file mode 100644 index 0000000..a92acf9 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Constraint.h @@ -0,0 +1,68 @@ + +/****************************************************************************** + * + * file: Constraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_CONSTRAINT_H +#define TCLAP_CONSTRAINT_H + +#include +#include +#include +#include +#include +#include + +namespace TCLAP { + +/** + * The interface that defines the interaction between the Arg and Constraint. + */ +template +class Constraint +{ + + public: + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const =0; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const =0; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const =0; + + /** + * Destructor. + * Silences warnings about Constraint being a base class with virtual + * functions but without a virtual destructor. + */ + virtual ~Constraint() { ; } +}; + +} //namespace TCLAP +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/DocBookOutput.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/DocBookOutput.h new file mode 100644 index 0000000..a42ca27 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/DocBookOutput.h @@ -0,0 +1,299 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: DocBookOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_DOCBOOKOUTPUT_H +#define TCLAP_DOCBOOKOUTPUT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A class that generates DocBook output for usage() method for the + * given CmdLine and its Args. + */ +class DocBookOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Substitutes the char r for string x in string s. + * \param s - The string to operate on. + * \param r - The char to replace. + * \param x - What to replace r with. + */ + void substituteSpecialChars( std::string& s, char r, std::string& x ); + void removeChar( std::string& s, char r); + void basename( std::string& s ); + + void printShortArg(Arg* it); + void printLongArg(Arg* it); + + char theDelimiter; +}; + + +inline void DocBookOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void DocBookOutput::usage(CmdLineInterface& _cmd ) +{ + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + basename(progName); + + std::cout << "" << std::endl; + std::cout << "" << std::endl << std::endl; + + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << progName << "" << std::endl; + std::cout << "1" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << progName << "" << std::endl; + std::cout << "" << _cmd.getMessage() << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << progName << "" << std::endl; + + // xor + for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) + { + std::cout << "" << std::endl; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + printShortArg((*it)); + + std::cout << "" << std::endl; + } + + // rest of args + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + printShortArg((*it)); + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Description" << std::endl; + std::cout << "" << std::endl; + std::cout << _cmd.getMessage() << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Options" << std::endl; + + std::cout << "" << std::endl; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + printLongArg((*it)); + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "Version" << std::endl; + std::cout << "" << std::endl; + std::cout << xversion << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + +} + +inline void DocBookOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast(_cmd); // unused + std::cout << e.what() << std::endl; + throw ExitException(1); +} + +inline void DocBookOutput::substituteSpecialChars( std::string& s, + char r, + std::string& x ) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + s.insert(p,x); + } +} + +inline void DocBookOutput::removeChar( std::string& s, char r) +{ + size_t p; + while ( (p = s.find_first_of(r)) != std::string::npos ) + { + s.erase(p,1); + } +} + +inline void DocBookOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void DocBookOutput::printShortArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string id = a->shortID(); + substituteSpecialChars(id,'<',lt); + substituteSpecialChars(id,'>',gt); + removeChar(id,'['); + removeChar(id,']'); + + std::string choice = "opt"; + if ( a->isRequired() ) + choice = "plain"; + + std::cout << "acceptsMultipleValues() ) + std::cout << " rep='repeat'"; + + + std::cout << '>'; + if ( !a->getFlag().empty() ) + std::cout << a->flagStartChar() << a->getFlag(); + else + std::cout << a->nameStartString() << a->getName(); + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + removeChar(arg,'['); + removeChar(arg,']'); + removeChar(arg,'<'); + removeChar(arg,'>'); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + std::cout << theDelimiter; + std::cout << "" << arg << ""; + } + std::cout << "" << std::endl; + +} + +inline void DocBookOutput::printLongArg(Arg* a) +{ + std::string lt = "<"; + std::string gt = ">"; + + std::string desc = a->getDescription(); + substituteSpecialChars(desc,'<',lt); + substituteSpecialChars(desc,'>',gt); + + std::cout << "" << std::endl; + + if ( !a->getFlag().empty() ) + { + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + } + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; + std::cout << "" << std::endl; + std::cout << desc << std::endl; + std::cout << "" << std::endl; + std::cout << "" << std::endl; + + std::cout << "" << std::endl; +} + +} //namespace TCLAP +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/HelpVisitor.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/HelpVisitor.h new file mode 100644 index 0000000..cc3bd07 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/HelpVisitor.h @@ -0,0 +1,76 @@ + +/****************************************************************************** + * + * file: HelpVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_HELP_VISITOR_H +#define TCLAP_HELP_VISITOR_H + +#include +#include +#include + +namespace TCLAP { + +/** + * A Visitor object that calls the usage method of the given CmdLineOutput + * object for the specified CmdLine object. + */ +class HelpVisitor: public Visitor +{ + private: + /** + * Prevent accidental copying. + */ + HelpVisitor(const HelpVisitor& rhs); + HelpVisitor& operator=(const HelpVisitor& rhs); + + protected: + + /** + * The CmdLine the output will be generated for. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output will be generated for. + * \param out - The type of output. + */ + HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the usage method of the CmdLineOutput for the + * specified CmdLine. + */ + void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } + +}; + +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/IgnoreRestVisitor.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/IgnoreRestVisitor.h new file mode 100644 index 0000000..e328649 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/IgnoreRestVisitor.h @@ -0,0 +1,52 @@ + +/****************************************************************************** + * + * file: IgnoreRestVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_IGNORE_REST_VISITOR_H +#define TCLAP_IGNORE_REST_VISITOR_H + +#include +#include + +namespace TCLAP { + +/** + * A Vistor that tells the CmdLine to begin ignoring arguments after + * this one is parsed. + */ +class IgnoreRestVisitor: public Visitor +{ + public: + + /** + * Constructor. + */ + IgnoreRestVisitor() : Visitor() {} + + /** + * Sets Arg::_ignoreRest. + */ + void visit() { Arg::beginIgnoring(); } +}; + +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.am b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.am new file mode 100644 index 0000000..0e247bf --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.am @@ -0,0 +1,28 @@ + +libtclapincludedir = $(includedir)/tclap + +libtclapinclude_HEADERS = \ + CmdLineInterface.h \ + ArgException.h \ + CmdLine.h \ + XorHandler.h \ + MultiArg.h \ + UnlabeledMultiArg.h \ + ValueArg.h \ + UnlabeledValueArg.h \ + Visitor.h Arg.h \ + HelpVisitor.h \ + SwitchArg.h \ + MultiSwitchArg.h \ + VersionVisitor.h \ + IgnoreRestVisitor.h \ + CmdLineOutput.h \ + StdOutput.h \ + DocBookOutput.h \ + ZshCompletionOutput.h \ + OptionalUnlabeledTracker.h \ + Constraint.h \ + ValuesConstraint.h \ + ArgTraits.h \ + StandardTraits.h + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.in b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.in new file mode 100644 index 0000000..65ef251 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.in @@ -0,0 +1,403 @@ +# Makefile.in generated by automake 1.10 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = include/tclap +DIST_COMMON = $(libtclapinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/config/ac_cxx_have_long_long.m4 \ + $(top_srcdir)/config/ac_cxx_have_sstream.m4 \ + $(top_srcdir)/config/ac_cxx_have_strstream.m4 \ + $(top_srcdir)/config/ac_cxx_namespaces.m4 \ + $(top_srcdir)/config/ac_cxx_warn_effective_cxx.m4 \ + $(top_srcdir)/config/bb_enable_doxygen.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libtclapincludedir)" +libtclapincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(libtclapinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOT = @DOT@ +DOXYGEN = @DOXYGEN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WARN_EFFECTIVE_CXX = @WARN_EFFECTIVE_CXX@ +WARN_NO_EFFECTIVE_CXX = @WARN_NO_EFFECTIVE_CXX@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +libtclapincludedir = $(includedir)/tclap +libtclapinclude_HEADERS = \ + CmdLineInterface.h \ + ArgException.h \ + CmdLine.h \ + XorHandler.h \ + MultiArg.h \ + UnlabeledMultiArg.h \ + ValueArg.h \ + UnlabeledValueArg.h \ + Visitor.h Arg.h \ + HelpVisitor.h \ + SwitchArg.h \ + MultiSwitchArg.h \ + VersionVisitor.h \ + IgnoreRestVisitor.h \ + CmdLineOutput.h \ + StdOutput.h \ + DocBookOutput.h \ + ZshCompletionOutput.h \ + OptionalUnlabeledTracker.h \ + Constraint.h \ + ValuesConstraint.h \ + ArgTraits.h \ + StandardTraits.h + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/tclap/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/tclap/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libtclapincludeHEADERS: $(libtclapinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(libtclapincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libtclapincludedir)" + @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(libtclapincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ + $(libtclapincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libtclapincludedir)/$$f"; \ + done + +uninstall-libtclapincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libtclapinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(libtclapincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(libtclapincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libtclapincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-libtclapincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libtclapincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + ctags distclean distclean-generic distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libtclapincludeHEADERS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-libtclapincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiArg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiArg.h new file mode 100644 index 0000000..34bb2d7 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiArg.h @@ -0,0 +1,433 @@ +/****************************************************************************** + * + * file: MultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_ARGUMENT_H +#define TCLAP_MULTIPLE_ARGUMENT_H + +#include +#include + +#include +#include + +namespace TCLAP { +/** + * An argument that allows multiple values of type T to be specified. Very + * similar to a ValueArg, except a vector of values will be returned + * instead of just one. + */ +template +class MultiArg : public Arg +{ +public: + typedef std::vector container_type; + typedef typename container_type::iterator iterator; + typedef typename container_type::const_iterator const_iterator; + +protected: + + /** + * The list of values parsed from the CmdLine. + */ + std::vector _values; + + /** + * The description of type T to be used in the usage. + */ + std::string _typeDesc; + + /** + * A list of constraint on this Arg. + */ + Constraint* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - The string to be read. + */ + void _extractValue( const std::string& val ); + + /** + * Used by XorHandler to decide whether to keep parsing for this arg. + */ + bool _allowMore; + +public: + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v = NULL); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + Visitor* v = NULL ); + + /** + * Constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns a vector of type T containing the values parsed from + * the command line. + */ + const std::vector& getValue(); + + /** + * Returns an iterator over the values parsed from the command + * line. + */ + const_iterator begin() const { return _values.begin(); } + + /** + * Returns the end of the values parsed from the command + * line. + */ + const_iterator end() const { return _values.end(); } + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Once we've matched the first value, then the arg is no longer + * required. + */ + virtual bool isRequired() const; + + virtual bool allowMore(); + + virtual void reset(); + +private: + /** + * Prevent accidental copying + */ + MultiArg(const MultiArg& rhs); + MultiArg& operator=(const MultiArg& rhs); + +}; + +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + Visitor* v) : + Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( typeDesc ), + _constraint( NULL ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +/** + * + */ +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + _acceptsMultipleValues = true; +} + +template +MultiArg::MultiArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg( flag, name, desc, req, true, v ), + _values(std::vector()), + _typeDesc( constraint->shortID() ), + _constraint( constraint ), + _allowMore(false) +{ + parser.add( this ); + _acceptsMultipleValues = true; +} + +template +const std::vector& MultiArg::getValue() { return _values; } + +template +bool MultiArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + std::string value = ""; + + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + // always take the first one, regardless of start string + if ( value == "" ) + { + (*i)++; + if ( static_cast(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + /* + // continuing taking the args until we hit one with a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + _checkWithVisitor(); + + return true; + } + else + return false; +} + +/** + * + */ +template +std::string MultiArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::shortID(_typeDesc) + " ... "; +} + +/** + * + */ +template +std::string MultiArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::longID(_typeDesc) + " (accepted multiple times)"; +} + +/** + * Once we've matched the first value, then the arg is no longer + * required. + */ +template +bool MultiArg::isRequired() const +{ + if ( _required ) + { + if ( _values.size() > 1 ) + return false; + else + return true; + } + else + return false; + +} + +template +void MultiArg::_extractValue( const std::string& val ) +{ + try { + T tmp; + ExtractValue(tmp, val, typename ArgTraits::ValueCategory()); + _values.push_back(tmp); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _values.back() ) ) + throw( CmdLineParseException( "Value '" + val + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template +bool MultiArg::allowMore() +{ + bool am = _allowMore; + _allowMore = true; + return am; +} + +template +void MultiArg::reset() +{ + Arg::reset(); + _values.clear(); +} + +} // namespace TCLAP + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiSwitchArg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiSwitchArg.h new file mode 100644 index 0000000..8820b64 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiSwitchArg.h @@ -0,0 +1,216 @@ + +/****************************************************************************** +* +* file: MultiSwitchArg.h +* +* Copyright (c) 2003, Michael E. Smoot . +* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. +* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. +* All rights reverved. +* +* See the file COPYING in the top directory of this distribution for +* more information. +* +* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +* +*****************************************************************************/ + + +#ifndef TCLAP_MULTI_SWITCH_ARG_H +#define TCLAP_MULTI_SWITCH_ARG_H + +#include +#include + +#include + +namespace TCLAP { + +/** +* A multiple switch argument. If the switch is set on the command line, then +* the getValue method will return the number of times the switch appears. +*/ +class MultiSwitchArg : public SwitchArg +{ + protected: + + /** + * The value of the switch. + */ + int _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + int _default; + + public: + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init = 0, + Visitor* v = NULL); + + + /** + * MultiSwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param init - Optional. The initial/default value of this Arg. + * Defaults to 0. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init = 0, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the SwitchArg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns int, the number of times the switch has been set. + */ + int getValue(); + + /** + * Returns the shortID for this Arg. + */ + std::string shortID(const std::string& val) const; + + /** + * Returns the longID for this Arg. + */ + std::string longID(const std::string& val) const; + + void reset(); + +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ } + +inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + int init, + Visitor* v ) +: SwitchArg(flag, name, desc, false, v), +_value( init ), +_default( init ) +{ + parser.add( this ); +} + +inline int MultiSwitchArg::getValue() { return _value; } + +inline bool MultiSwitchArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] )) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + _checkWithVisitor(); + + return true; + } + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // so the isSet() method will work + _alreadySet = true; + + // Matched argument: increment value. + ++_value; + + // Check for more in argument and increment value. + while ( combinedSwitchesMatch( args[*i] ) ) + ++_value; + + _checkWithVisitor(); + + return false; + } + else + return false; +} + +inline std::string +MultiSwitchArg::shortID(const std::string& val) const +{ + return Arg::shortID(val) + " ... "; +} + +inline std::string +MultiSwitchArg::longID(const std::string& val) const +{ + return Arg::longID(val) + " (accepted multiple times)"; +} + +inline void +MultiSwitchArg::reset() +{ + MultiSwitchArg::_value = MultiSwitchArg::_default; +} + +////////////////////////////////////////////////////////////////////// +//END MultiSwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/OptionalUnlabeledTracker.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/OptionalUnlabeledTracker.h new file mode 100644 index 0000000..8174c5f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/OptionalUnlabeledTracker.h @@ -0,0 +1,62 @@ + + +/****************************************************************************** + * + * file: OptionalUnlabeledTracker.h + * + * Copyright (c) 2005, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H +#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H + +#include + +namespace TCLAP { + +class OptionalUnlabeledTracker +{ + + public: + + static void check( bool req, const std::string& argName ); + + static void gotOptional() { alreadyOptionalRef() = true; } + + static bool& alreadyOptional() { return alreadyOptionalRef(); } + + private: + + static bool& alreadyOptionalRef() { static bool ct = false; return ct; } +}; + + +inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) +{ + if ( OptionalUnlabeledTracker::alreadyOptional() ) + throw( SpecificationException( + "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", + argName ) ); + + if ( !req ) + OptionalUnlabeledTracker::gotOptional(); +} + + +} // namespace TCLAP + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StandardTraits.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StandardTraits.h new file mode 100644 index 0000000..46d7f6f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StandardTraits.h @@ -0,0 +1,208 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StandardTraits.h + * + * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * 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. + * + *****************************************************************************/ + +// This is an internal tclap file, you should probably not have to +// include this directly + +#ifndef TCLAP_STANDARD_TRAITS_H +#define TCLAP_STANDARD_TRAITS_H + +#ifdef HAVE_CONFIG_H +#include // To check for long long +#endif + +// If Microsoft has already typedef'd wchar_t as an unsigned +// short, then compiles will break because it's as if we're +// creating ArgTraits twice for unsigned short. Thus... +#ifdef _MSC_VER +#ifndef _NATIVE_WCHAR_T_DEFINED +#define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS +#endif +#endif + +namespace TCLAP { + +// ====================================================================== +// Integer types +// ====================================================================== + +/** + * longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * ints have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * shorts have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * chars have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +#ifdef HAVE_LONG_LONG +/** + * long longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Unsigned integer types +// ====================================================================== + +/** + * unsigned longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned ints have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned shorts have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * unsigned chars have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +// Microsoft implements size_t awkwardly. +#if defined(_MSC_VER) && defined(_M_X64) +/** + * size_ts have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + + +#ifdef HAVE_LONG_LONG +/** + * unsigned long longs have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + +// ====================================================================== +// Float types +// ====================================================================== + +/** + * floats have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +/** + * doubles have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + +// ====================================================================== +// Other types +// ====================================================================== + +/** + * bools have value-like semantics. + */ +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; + + +/** + * wchar_ts have value-like semantics. + */ +#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS +template<> +struct ArgTraits { + typedef ValueLike ValueCategory; +}; +#endif + +/** + * Strings have string like argument traits. + */ +template<> +struct ArgTraits { + typedef StringLike ValueCategory; +}; + +template +void SetString(T &dst, const std::string &src) +{ + dst = src; +} + +} // namespace + +#endif + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StdOutput.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StdOutput.h new file mode 100644 index 0000000..35f7b99 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StdOutput.h @@ -0,0 +1,298 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: StdOutput.h + * + * Copyright (c) 2004, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_STDCMDLINEOUTPUT_H +#define TCLAP_STDCMDLINEOUTPUT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A class that isolates any output from the CmdLine object so that it + * may be easily modified. + */ +class StdOutput : public CmdLineOutput +{ + + public: + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + /** + * Writes a brief usage message with short args. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * Writes a longer usage message with long and short args, + * provides descriptions and prints message. + * \param c - The CmdLine object the output is generated for. + * \param os - The stream to write the message to. + */ + void _longUsage( CmdLineInterface& c, std::ostream& os ) const; + + /** + * This function inserts line breaks and indents long strings + * according the params input. It will only break lines at spaces, + * commas and pipes. + * \param os - The stream to be printed to. + * \param s - The string to be printed. + * \param maxWidth - The maxWidth allowed for the output line. + * \param indentSpaces - The number of spaces to indent the first line. + * \param secondLineOffset - The number of spaces to indent the second + * and all subsequent lines in addition to indentSpaces. + */ + void spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const; + +}; + + +inline void StdOutput::version(CmdLineInterface& _cmd) +{ + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + + std::cout << std::endl << progName << " version: " + << xversion << std::endl << std::endl; +} + +inline void StdOutput::usage(CmdLineInterface& _cmd ) +{ + std::cout << std::endl << "USAGE: " << std::endl << std::endl; + + _shortUsage( _cmd, std::cout ); + + std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; + + _longUsage( _cmd, std::cout ); + + std::cout << std::endl; + +} + +inline void StdOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + std::string progName = _cmd.getProgramName(); + + std::cerr << "PARSE ERROR: " << e.argId() << std::endl + << " " << e.error() << std::endl << std::endl; + + if ( _cmd.hasHelpAndVersion() ) + { + std::cerr << "Brief USAGE: " << std::endl; + + _shortUsage( _cmd, std::cerr ); + + std::cerr << std::endl << "For complete USAGE and HELP type: " + << std::endl << " " << progName << " --help" + << std::endl << std::endl; + } + else + usage(_cmd); + + throw ExitException(1); +} + +inline void +StdOutput::_shortUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + + std::string s = progName + " "; + + // first the xor + for ( int i = 0; static_cast(i) < xorList.size(); i++ ) + { + s += " {"; + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); it++ ) + s += (*it)->shortID() + "|"; + + s[s.length()-1] = '}'; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + s += " " + (*it)->shortID(); + + // if the program name is too long, then adjust the second line offset + int secondLineOffset = static_cast(progName.length()) + 2; + if ( secondLineOffset > 75/2 ) + secondLineOffset = static_cast(75/2); + + spacePrint( os, s, 75, 3, secondLineOffset ); +} + +inline void +StdOutput::_longUsage( CmdLineInterface& _cmd, + std::ostream& os ) const +{ + std::list argList = _cmd.getArgList(); + std::string message = _cmd.getMessage(); + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + + // first the xor + for ( int i = 0; static_cast(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++ ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + + if ( it+1 != xorList[i].end() ) + spacePrint(os, "-- OR --", 75, 9, 0); + } + os << std::endl << std::endl; + } + + // then the rest + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + if ( !xorHandler.contains( (*it) ) ) + { + spacePrint( os, (*it)->longID(), 75, 3, 3 ); + spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); + os << std::endl; + } + + os << std::endl; + + spacePrint( os, message, 75, 3, 0 ); +} + +inline void StdOutput::spacePrint( std::ostream& os, + const std::string& s, + int maxWidth, + int indentSpaces, + int secondLineOffset ) const +{ + int len = static_cast(s.length()); + + if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) + { + int allowedLen = maxWidth - indentSpaces; + int start = 0; + while ( start < len ) + { + // find the substring length + // int stringLen = std::min( len - start, allowedLen ); + // doing it this way to support a VisualC++ 2005 bug + using namespace std; + int stringLen = min( len - start, allowedLen ); + + // trim the length so it doesn't end in middle of a word + if ( stringLen == allowedLen ) + while ( stringLen >= 0 && + s[stringLen+start] != ' ' && + s[stringLen+start] != ',' && + s[stringLen+start] != '|' ) + stringLen--; + + // ok, the word is longer than the line, so just split + // wherever the line ends + if ( stringLen <= 0 ) + stringLen = allowedLen; + + // check for newlines + for ( int i = 0; i < stringLen; i++ ) + if ( s[start+i] == '\n' ) + stringLen = i+1; + + // print the indent + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + + if ( start == 0 ) + { + // handle second line offsets + indentSpaces += secondLineOffset; + + // adjust allowed len + allowedLen -= secondLineOffset; + } + + os << s.substr(start,stringLen) << std::endl; + + // so we don't start a line with a space + while ( s[stringLen+start] == ' ' && start < len ) + start++; + + start += stringLen; + } + } + else + { + for ( int i = 0; i < indentSpaces; i++ ) + os << " "; + os << s << std::endl; + } +} + +} //namespace TCLAP +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/SwitchArg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/SwitchArg.h new file mode 100644 index 0000000..3916109 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/SwitchArg.h @@ -0,0 +1,266 @@ + +/****************************************************************************** + * + * file: SwitchArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_SWITCH_ARG_H +#define TCLAP_SWITCH_ARG_H + +#include +#include + +#include + +namespace TCLAP { + +/** + * A simple switch argument. If the switch is set on the command line, then + * the getValue method will return the opposite of the default value for the + * switch. + */ +class SwitchArg : public Arg +{ + protected: + + /** + * The value of the switch. + */ + bool _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + bool _default; + + public: + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool def = false, + Visitor* v = NULL); + + + /** + * SwitchArg constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param parser - A CmdLine parser object to add this Arg to + * \param def - The default value for this Switch. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool def = false, + Visitor* v = NULL); + + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Checks a string to see if any of the chars in the string + * match the flag for this Switch. + */ + bool combinedSwitchesMatch(std::string& combined); + + /** + * Returns bool, whether or not the switch has been set. + */ + bool getValue(); + + virtual void reset(); + + private: + /** + * Checks to see if we've found the last match in + * a combined string. + */ + bool lastCombined(std::string& combined); + + /** + * Does the common processing of processArg. + */ + void commonProcessing(); +}; + +////////////////////////////////////////////////////////////////////// +//BEGIN SwitchArg.cpp +////////////////////////////////////////////////////////////////////// +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default( default_val ) +{ } + +inline SwitchArg::SwitchArg(const std::string& flag, + const std::string& name, + const std::string& desc, + CmdLineInterface& parser, + bool default_val, + Visitor* v ) +: Arg(flag, name, desc, false, false, v), + _value( default_val ), + _default(default_val) +{ + parser.add( this ); +} + +inline bool SwitchArg::getValue() { return _value; } + +inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) +{ + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( combinedSwitches[i] != Arg::blankChar() ) + return false; + + return true; +} + +inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) +{ + // make sure this is actually a combined switch + if ( combinedSwitches.length() > 0 && + combinedSwitches[0] != Arg::flagStartString()[0] ) + return false; + + // make sure it isn't a long name + if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == + Arg::nameStartString() ) + return false; + + // make sure the delimiter isn't in the string + if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos ) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) + if ( _flag.length() > 0 && + combinedSwitches[i] == _flag[0] && + _flag[0] != Arg::flagStartString()[0] ) + { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + //combinedSwitches.erase(i,1); + combinedSwitches[i] = Arg::blankChar(); + return true; + } + + // none of the switches passed in the list match. + return false; +} + +inline void SwitchArg::commonProcessing() +{ + if ( _xorSet ) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", toString())); + + if ( _alreadySet ) + throw(CmdLineParseException("Argument already set!", toString())); + + _alreadySet = true; + + if ( _value == true ) + _value = false; + else + _value = true; + + _checkWithVisitor(); +} + +inline bool SwitchArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + // if the whole string matches the flag or name string + if ( argMatches( args[*i] ) ) + { + commonProcessing(); + + return true; + } + // if a substring matches the flag as part of a combination + else if ( combinedSwitchesMatch( args[*i] ) ) + { + // check again to ensure we don't misinterpret + // this as a MultiSwitchArg + if ( combinedSwitchesMatch( args[*i] ) ) + throw(CmdLineParseException("Argument already set!", + toString())); + + commonProcessing(); + + // We only want to return true if we've found the last combined + // match in the string, otherwise we return true so that other + // switches in the combination will have a chance to match. + return lastCombined( args[*i] ); + } + else + return false; +} + +inline void SwitchArg::reset() +{ + Arg::reset(); + _value = _default; +} +////////////////////////////////////////////////////////////////////// +//End SwitchArg.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledMultiArg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledMultiArg.h new file mode 100644 index 0000000..d5e1781 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledMultiArg.h @@ -0,0 +1,301 @@ + +/****************************************************************************** + * + * file: UnlabeledMultiArg.h + * + * Copyright (c) 2003, Michael E. Smoot. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H +#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H + +#include +#include + +#include +#include + +namespace TCLAP { + +/** + * Just like a MultiArg, except that the arguments are unlabeled. Basically, + * this Arg will slurp up everything that hasn't been matched to another + * Arg. + */ +template +class UnlabeledMultiArg : public MultiArg +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using MultiArg::_ignoreable; + using MultiArg::_hasBlanks; + using MultiArg::_extractValue; + using MultiArg::_typeDesc; + using MultiArg::_name; + using MultiArg::_description; + using MultiArg::_alreadySet; + using MultiArg::toString; + + public: + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL ); + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Constructor. + * \param name - The name of the Arg. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Whether or not this argument can be ignored + * using the "--" flag. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + UnlabeledMultiArg( const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns the a short id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Returns the a long id string. Used in the usage. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Opertor ==. + * \param a - The Arg to be compared to this. + */ + virtual bool operator==(const Arg& a) const; + + /** + * Pushes this to back of list rather than front. + * \param argList - The list this should be added to. + */ + virtual void addToList( std::list& argList ) const; +}; + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); +} + +template +UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, + const std::string& desc, + bool req, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: MultiArg("", name, desc, req, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(true, toString()); + parser.add( this ); +} + + +template +bool UnlabeledMultiArg::processArg(int *i, std::vector& args) +{ + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled multi arg + + + // always take the first value, regardless of the start string + _extractValue( args[(*i)] ); + + /* + // continue taking args until we hit the end or a start string + while ( (unsigned int)(*i)+1 < args.size() && + args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && + args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) + _extractValue( args[++(*i)] ); + */ + + _alreadySet = true; + + return true; +} + +template +std::string UnlabeledMultiArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> ..."; +} + +template +std::string UnlabeledMultiArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + "> (accepted multiple times)"; +} + +template +bool UnlabeledMultiArg::operator==(const Arg& a) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template +void UnlabeledMultiArg::addToList( std::list& argList ) const +{ + argList.push_back( const_cast(static_cast(this)) ); +} + +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledValueArg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledValueArg.h new file mode 100644 index 0000000..5721d61 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledValueArg.h @@ -0,0 +1,340 @@ + +/****************************************************************************** + * + * file: UnlabeledValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H +#define TCLAP_UNLABELED_VALUE_ARGUMENT_H + +#include +#include + +#include +#include + + +namespace TCLAP { + +/** + * The basic unlabeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when an UnlabeledValueArg + * is reached in the list of args that the CmdLine iterates over. + */ +template +class UnlabeledValueArg : public ValueArg +{ + + // If compiler has two stage name lookup (as gcc >= 3.4 does) + // this is requried to prevent undef. symbols + using ValueArg::_ignoreable; + using ValueArg::_hasBlanks; + using ValueArg::_extractValue; + using ValueArg::_typeDesc; + using ValueArg::_name; + using ValueArg::_description; + using ValueArg::_alreadySet; + using ValueArg::toString; + + public: + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL ); + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + bool ignoreable = false, + Visitor* v = NULL ); + + + /** + * UnlabeledValueArg constructor. + * \param name - A one word name for the argument. Note that this is used for + * identification, not as a long flag. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to + * \param ignoreable - Allows you to specify that this argument can be + * ignored if the '--' flag is set. This defaults to false (cannot + * be ignored) and should generally stay that way unless you have + * some special need for certain arguments to be ignored. + * \param v - Optional Vistor. You should leave this blank unless + * you have a very good reason. + */ + UnlabeledValueArg( const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable = false, + Visitor* v = NULL); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. Handling specific to + * unlabled arguments. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Overrides shortID for specific behavior. + */ + virtual std::string shortID(const std::string& val="val") const; + + /** + * Overrides longID for specific behavior. + */ + virtual std::string longID(const std::string& val="val") const; + + /** + * Overrides operator== for specific behavior. + */ + virtual bool operator==(const Arg& a ) const; + + /** + * Instead of pushing to the front of list, push to the back. + * \param argList - The list to add this to. + */ + virtual void addToList( std::list& argList ) const; + +}; + +/** + * Constructor implemenation. + */ +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + + OptionalUnlabeledTracker::check(req, toString()); + +} + +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, typeDesc, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Constructor implemenation. + */ +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); +} + +template +UnlabeledValueArg::UnlabeledValueArg(const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + CmdLineInterface& parser, + bool ignoreable, + Visitor* v) +: ValueArg("", name, desc, req, val, constraint, v) +{ + _ignoreable = ignoreable; + OptionalUnlabeledTracker::check(req, toString()); + parser.add( this ); +} + +/** + * Implementation of processArg(). + */ +template +bool UnlabeledValueArg::processArg(int *i, std::vector& args) +{ + + if ( _alreadySet ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + // never ignore an unlabeled arg + + _extractValue( args[*i] ); + _alreadySet = true; + return true; +} + +/** + * Overriding shortID for specific output. + */ +template +std::string UnlabeledValueArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding longID for specific output. + */ +template +std::string UnlabeledValueArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + + // Ideally we would like to be able to use RTTI to return the name + // of the type required for this argument. However, g++ at least, + // doesn't appear to return terribly useful "names" of the types. + return std::string("<") + _typeDesc + ">"; +} + +/** + * Overriding operator== for specific behavior. + */ +template +bool UnlabeledValueArg::operator==(const Arg& a ) const +{ + if ( _name == a.getName() || _description == a.getDescription() ) + return true; + else + return false; +} + +template +void UnlabeledValueArg::addToList( std::list& argList ) const +{ + argList.push_back( const_cast(static_cast(this)) ); +} + +} +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValueArg.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValueArg.h new file mode 100644 index 0000000..7ac2952 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValueArg.h @@ -0,0 +1,425 @@ +/****************************************************************************** + * + * file: ValueArg.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VALUE_ARGUMENT_H +#define TCLAP_VALUE_ARGUMENT_H + +#include +#include + +#include +#include + +namespace TCLAP { + +/** + * The basic labeled argument that parses a value. + * This is a template class, which means the type T defines the type + * that a given object will attempt to parse when the flag/name is matched + * on the command line. While there is nothing stopping you from creating + * an unflagged ValueArg, it is unwise and would cause significant problems. + * Instead use an UnlabeledValueArg. + */ +template +class ValueArg : public Arg +{ + protected: + + /** + * The value parsed from the command line. + * Can be of any type, as long as the >> operator for the type + * is defined. + */ + T _value; + + /** + * Used to support the reset() method so that ValueArg can be + * reset to their constructed value. + */ + T _default; + + /** + * A human readable description of the type to be parsed. + * This is a hack, plain and simple. Ideally we would use RTTI to + * return the name of type T, but until there is some sort of + * consistent support for human readable names, we are left to our + * own devices. + */ + std::string _typeDesc; + + /** + * A Constraint this Arg must conform to. + */ + Constraint* _constraint; + + /** + * Extracts the value from the string. + * Attempts to parse string as type T, if this fails an exception + * is thrown. + * \param val - value to be parsed. + */ + void _extractValue( const std::string& val ); + + public: + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + Visitor* v = NULL); + + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param typeDesc - A short, human readable description of the + * type that this object expects. This is used in the generation + * of the USAGE statement. The goal is to be helpful to the end user + * of the program. + * \param parser - A CmdLine parser object to add this Arg to + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param parser - A CmdLine parser object to add this Arg to. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v = NULL ); + + /** + * Labeled ValueArg constructor. + * You could conceivably call this constructor with a blank flag, + * but that would make you a bad person. It would also cause + * an exception to be thrown. If you want an unlabeled argument, + * use the other constructor. + * \param flag - The one character flag that identifies this + * argument on the command line. + * \param name - A one word name for the argument. Can be + * used as a long flag on the command line. + * \param desc - A description of what the argument is for or + * does. + * \param req - Whether the argument is required on the command + * line. + * \param value - The default value assigned to this argument if it + * is not present on the command line. + * \param constraint - A pointer to a Constraint object used + * to constrain this Arg. + * \param v - An optional visitor. You probably should not + * use this unless you have a very good reason. + */ + ValueArg( const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T value, + Constraint* constraint, + Visitor* v = NULL ); + + /** + * Handles the processing of the argument. + * This re-implements the Arg version of this method to set the + * _value of the argument appropriately. It knows the difference + * between labeled and unlabeled. + * \param i - Pointer the the current argument in the list. + * \param args - Mutable list of strings. Passed + * in from main(). + */ + virtual bool processArg(int* i, std::vector& args); + + /** + * Returns the value of the argument. + */ + T& getValue() ; + + /** + * Specialization of shortID. + * \param val - value to be used. + */ + virtual std::string shortID(const std::string& val = "val") const; + + /** + * Specialization of longID. + * \param val - value to be used. + */ + virtual std::string longID(const std::string& val = "val") const; + + virtual void reset() ; + +private: + /** + * Prevent accidental copying + */ + ValueArg(const ValueArg& rhs); + ValueArg& operator=(const ValueArg& rhs); +}; + + +/** + * Constructor implementation. + */ +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ } + +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + const std::string& typeDesc, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( typeDesc ), + _constraint( NULL ) +{ + parser.add( this ); +} + +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ } + +template +ValueArg::ValueArg(const std::string& flag, + const std::string& name, + const std::string& desc, + bool req, + T val, + Constraint* constraint, + CmdLineInterface& parser, + Visitor* v) +: Arg(flag, name, desc, req, true, v), + _value( val ), + _default( val ), + _typeDesc( constraint->shortID() ), + _constraint( constraint ) +{ + parser.add( this ); +} + + +/** + * Implementation of getValue(). + */ +template +T& ValueArg::getValue() { return _value; } + +/** + * Implementation of processArg(). + */ +template +bool ValueArg::processArg(int *i, std::vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( _hasBlanks( args[*i] ) ) + return false; + + std::string flag = args[*i]; + + std::string value = ""; + trimFlag( flag, value ); + + if ( argMatches( flag ) ) + { + if ( _alreadySet ) + { + if ( _xorSet ) + throw( CmdLineParseException( + "Mutually exclusive argument already set!", + toString()) ); + else + throw( CmdLineParseException("Argument already set!", + toString()) ); + } + + if ( Arg::delimiter() != ' ' && value == "" ) + throw( ArgParseException( + "Couldn't find delimiter for this argument!", + toString() ) ); + + if ( value == "" ) + { + (*i)++; + if ( static_cast(*i) < args.size() ) + _extractValue( args[*i] ); + else + throw( ArgParseException("Missing a value for this argument!", + toString() ) ); + } + else + _extractValue( value ); + + _alreadySet = true; + _checkWithVisitor(); + return true; + } + else + return false; +} + +/** + * Implementation of shortID. + */ +template +std::string ValueArg::shortID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::shortID( _typeDesc ); +} + +/** + * Implementation of longID. + */ +template +std::string ValueArg::longID(const std::string& val) const +{ + static_cast(val); // Ignore input, don't warn + return Arg::longID( _typeDesc ); +} + +template +void ValueArg::_extractValue( const std::string& val ) +{ + try { + ExtractValue(_value, val, typename ArgTraits::ValueCategory()); + } catch( ArgParseException &e) { + throw ArgParseException(e.error(), toString()); + } + + if ( _constraint != NULL ) + if ( ! _constraint->check( _value ) ) + throw( CmdLineParseException( "Value '" + val + + + "' does not meet constraint: " + + _constraint->description(), + toString() ) ); +} + +template +void ValueArg::reset() +{ + Arg::reset(); + _value = _default; +} + +} // namespace TCLAP + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValuesConstraint.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValuesConstraint.h new file mode 100644 index 0000000..cb41f64 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValuesConstraint.h @@ -0,0 +1,148 @@ + + +/****************************************************************************** + * + * file: ValuesConstraint.h + * + * Copyright (c) 2005, Michael E. Smoot + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_VALUESCONSTRAINT_H +#define TCLAP_VALUESCONSTRAINT_H + +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#else +#define HAVE_SSTREAM +#endif + +#if defined(HAVE_SSTREAM) +#include +#elif defined(HAVE_STRSTREAM) +#include +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + +namespace TCLAP { + +/** + * A Constraint that constrains the Arg to only those values specified + * in the constraint. + */ +template +class ValuesConstraint : public Constraint +{ + + public: + + /** + * Constructor. + * \param allowed - vector of allowed values. + */ + ValuesConstraint(std::vector& allowed); + + /** + * Virtual destructor. + */ + virtual ~ValuesConstraint() {} + + /** + * Returns a description of the Constraint. + */ + virtual std::string description() const; + + /** + * Returns the short ID for the Constraint. + */ + virtual std::string shortID() const; + + /** + * The method used to verify that the value parsed from the command + * line meets the constraint. + * \param value - The value that will be checked. + */ + virtual bool check(const T& value) const; + + protected: + + /** + * The list of valid values. + */ + std::vector _allowed; + + /** + * The string used to describe the allowed values of this constraint. + */ + std::string _typeDesc; + +}; + +template +ValuesConstraint::ValuesConstraint(std::vector& allowed) +: _allowed(allowed), + _typeDesc("") +{ + for ( unsigned int i = 0; i < _allowed.size(); i++ ) + { + +#if defined(HAVE_SSTREAM) + std::ostringstream os; +#elif defined(HAVE_STRSTREAM) + std::ostrstream os; +#else +#error "Need a stringstream (sstream or strstream) to compile!" +#endif + + os << _allowed[i]; + + std::string temp( os.str() ); + + if ( i > 0 ) + _typeDesc += "|"; + _typeDesc += temp; + } +} + +template +bool ValuesConstraint::check( const T& val ) const +{ + if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) + return false; + else + return true; +} + +template +std::string ValuesConstraint::shortID() const +{ + return _typeDesc; +} + +template +std::string ValuesConstraint::description() const +{ + return _typeDesc; +} + + +} //namespace TCLAP +#endif + diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/VersionVisitor.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/VersionVisitor.h new file mode 100644 index 0000000..c110d4f --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/VersionVisitor.h @@ -0,0 +1,81 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: VersionVisitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VERSION_VISITOR_H +#define TCLAP_VERSION_VISITOR_H + +#include +#include +#include + +namespace TCLAP { + +/** + * A Vistor that will call the version method of the given CmdLineOutput + * for the specified CmdLine object and then exit. + */ +class VersionVisitor: public Visitor +{ + private: + /** + * Prevent accidental copying + */ + VersionVisitor(const VersionVisitor& rhs); + VersionVisitor& operator=(const VersionVisitor& rhs); + + protected: + + /** + * The CmdLine of interest. + */ + CmdLineInterface* _cmd; + + /** + * The output object. + */ + CmdLineOutput** _out; + + public: + + /** + * Constructor. + * \param cmd - The CmdLine the output is generated for. + * \param out - The type of output. + */ + VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) + : Visitor(), _cmd( cmd ), _out( out ) { } + + /** + * Calls the version method of the output object using the + * specified CmdLine. + */ + void visit() { + (*_out)->version(*_cmd); + throw ExitException(0); + } + +}; + +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Visitor.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Visitor.h new file mode 100644 index 0000000..38ddcbd --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Visitor.h @@ -0,0 +1,53 @@ + +/****************************************************************************** + * + * file: Visitor.h + * + * Copyright (c) 2003, Michael E. Smoot . + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + + +#ifndef TCLAP_VISITOR_H +#define TCLAP_VISITOR_H + +namespace TCLAP { + +/** + * A base class that defines the interface for visitors. + */ +class Visitor +{ + public: + + /** + * Constructor. Does nothing. + */ + Visitor() { } + + /** + * Destructor. Does nothing. + */ + virtual ~Visitor() { } + + /** + * Does nothing. Should be overridden by child. + */ + virtual void visit() { } +}; + +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/XorHandler.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/XorHandler.h new file mode 100644 index 0000000..d9dfad3 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/XorHandler.h @@ -0,0 +1,166 @@ + +/****************************************************************************** + * + * file: XorHandler.h + * + * Copyright (c) 2003, Michael E. Smoot . + * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_XORHANDLER_H +#define TCLAP_XORHANDLER_H + +#include +#include +#include +#include +#include + +namespace TCLAP { + +/** + * This class handles lists of Arg's that are to be XOR'd on the command + * line. This is used by CmdLine and you shouldn't ever use it. + */ +class XorHandler +{ + protected: + + /** + * The list of of lists of Arg's to be or'd together. + */ + std::vector< std::vector > _orList; + + public: + + /** + * Constructor. Does nothing. + */ + XorHandler( ) : _orList(std::vector< std::vector >()) {} + + /** + * Add a list of Arg*'s that will be orred together. + * \param ors - list of Arg* that will be xor'd. + */ + void add( std::vector& ors ); + + /** + * Checks whether the specified Arg is in one of the xor lists and + * if it does match one, returns the size of the xor list that the + * Arg matched. If the Arg matches, then it also sets the rest of + * the Arg's in the list. You shouldn't use this. + * \param a - The Arg to be checked. + */ + int check( const Arg* a ); + + /** + * Returns the XOR specific short usage. + */ + std::string shortUsage(); + + /** + * Prints the XOR specific long usage. + * \param os - Stream to print to. + */ + void printLongUsage(std::ostream& os); + + /** + * Simply checks whether the Arg is contained in one of the arg + * lists. + * \param a - The Arg to be checked. + */ + bool contains( const Arg* a ); + + std::vector< std::vector >& getXorList(); + +}; + + +////////////////////////////////////////////////////////////////////// +//BEGIN XOR.cpp +////////////////////////////////////////////////////////////////////// +inline void XorHandler::add( std::vector& ors ) +{ + _orList.push_back( ors ); +} + +inline int XorHandler::check( const Arg* a ) +{ + // iterate over each XOR list + for ( int i = 0; static_cast(i) < _orList.size(); i++ ) + { + // if the XOR list contains the arg.. + ArgVectorIterator ait = std::find( _orList[i].begin(), + _orList[i].end(), a ); + if ( ait != _orList[i].end() ) + { + // first check to see if a mutually exclusive switch + // has not already been set + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) && (*it)->isSet() ) + throw(CmdLineParseException( + "Mutually exclusive argument already set!", + (*it)->toString())); + + // go through and set each arg that is not a + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a != (*it) ) + (*it)->xorSet(); + + // return the number of required args that have now been set + if ( (*ait)->allowMore() ) + return 0; + else + return static_cast(_orList[i].size()); + } + } + + if ( a->isRequired() ) + return 1; + else + return 0; +} + +inline bool XorHandler::contains( const Arg* a ) +{ + for ( int i = 0; static_cast(i) < _orList.size(); i++ ) + for ( ArgVectorIterator it = _orList[i].begin(); + it != _orList[i].end(); + it++ ) + if ( a == (*it) ) + return true; + + return false; +} + +inline std::vector< std::vector >& XorHandler::getXorList() +{ + return _orList; +} + + + +////////////////////////////////////////////////////////////////////// +//END XOR.cpp +////////////////////////////////////////////////////////////////////// + +} //namespace TCLAP + +#endif diff --git a/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ZshCompletionOutput.h b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ZshCompletionOutput.h new file mode 100644 index 0000000..0b37fc7 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ZshCompletionOutput.h @@ -0,0 +1,323 @@ +// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- + +/****************************************************************************** + * + * file: ZshCompletionOutput.h + * + * Copyright (c) 2006, Oliver Kiddle + * All rights reverved. + * + * See the file COPYING in the top directory of this distribution for + * more information. + * + * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + *****************************************************************************/ + +#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H +#define TCLAP_ZSHCOMPLETIONOUTPUT_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace TCLAP { + +/** + * A class that generates a Zsh completion function as output from the usage() + * method for the given CmdLine and its Args. + */ +class ZshCompletionOutput : public CmdLineOutput +{ + + public: + + ZshCompletionOutput(); + + /** + * Prints the usage to stdout. Can be overridden to + * produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void usage(CmdLineInterface& c); + + /** + * Prints the version to stdout. Can be overridden + * to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + */ + virtual void version(CmdLineInterface& c); + + /** + * Prints (to stderr) an error message, short usage + * Can be overridden to produce alternative behavior. + * \param c - The CmdLine object the output is generated for. + * \param e - The ArgException that caused the failure. + */ + virtual void failure(CmdLineInterface& c, + ArgException& e ); + + protected: + + void basename( std::string& s ); + void quoteSpecialChars( std::string& s ); + + std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); + void printOption( Arg* it, std::string mutex ); + void printArg( Arg* it ); + + std::map common; + char theDelimiter; +}; + +ZshCompletionOutput::ZshCompletionOutput() +: common(std::map()), + theDelimiter('=') +{ + common["host"] = "_hosts"; + common["hostname"] = "_hosts"; + common["file"] = "_files"; + common["filename"] = "_files"; + common["user"] = "_users"; + common["username"] = "_users"; + common["directory"] = "_directories"; + common["path"] = "_directories"; + common["url"] = "_urls"; +} + +inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) +{ + std::cout << _cmd.getVersion() << std::endl; +} + +inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) +{ + std::list argList = _cmd.getArgList(); + std::string progName = _cmd.getProgramName(); + std::string xversion = _cmd.getVersion(); + theDelimiter = _cmd.getDelimiter(); + basename(progName); + + std::cout << "#compdef " << progName << std::endl << std::endl << + "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << + "_arguments -s -S"; + + for (ArgListIterator it = argList.begin(); it != argList.end(); it++) + { + if ( (*it)->shortID().at(0) == '<' ) + printArg((*it)); + else if ( (*it)->getFlag() != "-" ) + printOption((*it), getMutexList(_cmd, *it)); + } + + std::cout << std::endl; +} + +inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, + ArgException& e ) +{ + static_cast(_cmd); // unused + std::cout << e.what() << std::endl; +} + +inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) +{ + size_t idx = s.find_last_of(':'); + while ( idx != std::string::npos ) + { + s.insert(idx, 1, '\\'); + idx = s.find_last_of(':', idx); + } + idx = s.find_last_of('\''); + while ( idx != std::string::npos ) + { + s.insert(idx, "'\\'"); + if (idx == 0) + idx = std::string::npos; + else + idx = s.find_last_of('\'', --idx); + } +} + +inline void ZshCompletionOutput::basename( std::string& s ) +{ + size_t p = s.find_last_of('/'); + if ( p != std::string::npos ) + { + s.erase(0, p + 1); + } +} + +inline void ZshCompletionOutput::printArg(Arg* a) +{ + static int count = 1; + + std::cout << " \\" << std::endl << " '"; + if ( a->acceptsMultipleValues() ) + std::cout << '*'; + else + std::cout << count++; + std::cout << ':'; + if ( !a->isRequired() ) + std::cout << ':'; + + std::cout << a->getName() << ':'; + std::map::iterator compArg = common.find(a->getName()); + if ( compArg != common.end() ) + { + std::cout << compArg->second; + } + else + { + std::cout << "_guard \"^-*\" " << a->getName(); + } + std::cout << '\''; +} + +inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) +{ + std::string flag = a->flagStartChar() + a->getFlag(); + std::string name = a->nameStartString() + a->getName(); + std::string desc = a->getDescription(); + + // remove full stop and capitalisation from description as + // this is the convention for zsh function + if (!desc.compare(0, 12, "(required) ")) + { + desc.erase(0, 12); + } + if (!desc.compare(0, 15, "(OR required) ")) + { + desc.erase(0, 15); + } + size_t len = desc.length(); + if (len && desc.at(--len) == '.') + { + desc.erase(len); + } + if (len) + { + desc.replace(0, 1, 1, tolower(desc.at(0))); + } + + std::cout << " \\" << std::endl << " '" << mutex; + + if ( a->getFlag().empty() ) + { + std::cout << name; + } + else + { + std::cout << "'{" << flag << ',' << name << "}'"; + } + if ( theDelimiter == '=' && a->isValueRequired() ) + std::cout << "=-"; + quoteSpecialChars(desc); + std::cout << '[' << desc << ']'; + + if ( a->isValueRequired() ) + { + std::string arg = a->shortID(); + arg.erase(0, arg.find_last_of(theDelimiter) + 1); + if ( arg.at(arg.length()-1) == ']' ) + arg.erase(arg.length()-1); + if ( arg.at(arg.length()-1) == ']' ) + { + arg.erase(arg.length()-1); + } + if ( arg.at(0) == '<' ) + { + arg.erase(arg.length()-1); + arg.erase(0, 1); + } + size_t p = arg.find('|'); + if ( p != std::string::npos ) + { + do + { + arg.replace(p, 1, 1, ' '); + } + while ( (p = arg.find_first_of('|', p)) != std::string::npos ); + quoteSpecialChars(arg); + std::cout << ": :(" << arg << ')'; + } + else + { + std::cout << ':' << arg; + std::map::iterator compArg = common.find(arg); + if ( compArg != common.end() ) + { + std::cout << ':' << compArg->second; + } + } + } + + std::cout << '\''; +} + +inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) +{ + XorHandler xorHandler = _cmd.getXorHandler(); + std::vector< std::vector > xorList = xorHandler.getXorList(); + + if (a->getName() == "help" || a->getName() == "version") + { + return "(-)"; + } + + std::ostringstream list; + if ( a->acceptsMultipleValues() ) + { + list << '*'; + } + + for ( int i = 0; static_cast(i) < xorList.size(); i++ ) + { + for ( ArgVectorIterator it = xorList[i].begin(); + it != xorList[i].end(); + it++) + if ( a == (*it) ) + { + list << '('; + for ( ArgVectorIterator iu = xorList[i].begin(); + iu != xorList[i].end(); + iu++ ) + { + bool notCur = (*iu) != a; + bool hasFlag = !(*iu)->getFlag().empty(); + if ( iu != xorList[i].begin() && (notCur || hasFlag) ) + list << ' '; + if (hasFlag) + list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; + if ( notCur || hasFlag ) + list << (*iu)->nameStartString() << (*iu)->getName(); + } + list << ')'; + return list.str(); + } + } + + // wasn't found in xor list + if (!a->getFlag().empty()) { + list << "(" << a->flagStartChar() << a->getFlag() << ' ' << + a->nameStartString() << a->getName() << ')'; + } + + return list.str(); +} + +} //namespace TCLAP +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/cf_tracker.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/cf_tracker.hpp new file mode 100644 index 0000000..382c858 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/cf_tracker.hpp @@ -0,0 +1,61 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef TRACKER_HPP_ +#define TRACKER_HPP_ + +#include "opencv2/core/core.hpp" +#include "tracker_debug.hpp" + +namespace cf_tracking +{ + class CfTracker + { + public: + virtual ~CfTracker() {}; + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) = 0; + + virtual TrackerDebug* getTrackerDebug() = 0; + virtual const std::string getId() = 0; + }; +} +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/cv_ext.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/cv_ext.hpp new file mode 100644 index 0000000..e72cde4 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/cv_ext.hpp @@ -0,0 +1,38 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef CV_EXT_HPP_ +#define CV_EXT_HPP_ + +#include "math_spectrums.hpp" +#include "shift.hpp" + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/feature_channels.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/feature_channels.hpp new file mode 100644 index 0000000..610c0b5 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/feature_channels.hpp @@ -0,0 +1,186 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +/* + TODO: create class with nonstatic methods and + overlad operators; this class should completely + encapsulate an array of cv::Mat objects + */ + +#ifndef FHOG_FEATURE_CHANNELS_H_ +#define FHOG_FEATURE_CHANNELS_H_ + +#include "opencv2/core/core.hpp" +#include "math_helper.hpp" +#include + +namespace cf_tracking +{ + template + class FeatureChannels_ + { + public: + static void mulValueFeatures(std::shared_ptr& m, + const T value) + { + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + m->channels[i] *= value; + } + + static void addFeatures(std::shared_ptr& A, + const std::shared_ptr& B) + { + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + A->channels[i] += B->channels[i]; + } + + static cv::Mat sumFeatures(const std::shared_ptr& x) + { + cv::Mat res = x->channels[0].clone(); + + for (int i = 1; i < NUMBER_OF_CHANNELS; ++i) + res += x->channels[i]; + + return res; + } + + static cv::Mat sumFeaturesInPlace(const std::shared_ptr& x) + { + for (int i = 1; i < NUMBER_OF_CHANNELS; ++i) + x->channels[0] += x->channels[i]; + + return x->channels[0]; + } + + static void mulFeatures(std::shared_ptr& features, + const cv::Mat& m) + { + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + features->channels[i] = features->channels[i].mul(m); + } + + static std::shared_ptr dftFeatures( + const std::shared_ptr& features, int flags = 0) + { + std::shared_ptr res(new FeatureChannels_()); + + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + cv::dft(features->channels[i], res->channels[i], flags); + + return res; + } + + static std::shared_ptr idftFeatures( + const std::shared_ptr& features) + { + std::shared_ptr res(new FeatureChannels_()); + + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + idft(features->channels[i], res->channels[i], cv::DFT_REAL_OUTPUT | cv::DFT_SCALE, 0); + + return res; + } + + static T squaredNormFeaturesCcs(const std::shared_ptr& Af) + { + // TODO: this is still slow and used frequently by gaussian + // correlation => find an equivalent quicker formulation; + // Note that reshaping and concatenating the mats first + // and then multiplying them is slower than + // this current approach! + int n = Af->channels[0].rows * Af->channels[0].cols; + T sum_ = 0; + cv::Mat elemMul; + + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + { + mulSpectrums(Af->channels[i], Af->channels[i], elemMul, 0, true); + sum_ += static_cast(sumRealOfSpectrum(elemMul)); + } + + return sum_ / n; + } + + static T squaredNormFeaturesNoCcs(const std::shared_ptr& Af) + { + int n = Af->channels[0].rows * Af->channels[0].cols; + T sum_ = 0; + cv::Mat elemMul; + + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + { + mulSpectrums(Af->channels[i], Af->channels[i], elemMul, 0, true); + sum_ += static_cast(cv::sum(elemMul)[0]); + } + + return sum_ / n; + } + + static std::shared_ptr mulSpectrumsFeatures(const std::shared_ptr& Af, + const std::shared_ptr& Bf, + bool conjBf) + { + std::shared_ptr resf(new FeatureChannels_()); + + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + mulSpectrums(Af->channels[i], Bf->channels[i], resf->channels[i], 0, conjBf); + + return resf; + } + + static std::shared_ptr mulSpectrumsFeatures(const cv::Mat& Af, + const std::shared_ptr& Bf, + bool conjBf = false) + { + std::shared_ptr resf(new FeatureChannels_()); + + for (int i = 0; i < NUMBER_OF_CHANNELS; ++i) + mulSpectrums(Af, Bf->channels[i], resf->channels[i], 0, conjBf); + + return resf; + } + + static const int numberOfChannels() + { + return NUMBER_OF_CHANNELS; + } + + cv::Mat channels[NUMBER_OF_CHANNELS]; + }; + + template + using FhogFeatureChannels = FeatureChannels_ < 31, T > ; + + template + using DsstFeatureChannels = FeatureChannels_ < 28, T > ; +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/mat_consts.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/mat_consts.hpp new file mode 100644 index 0000000..2e8a951 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/mat_consts.hpp @@ -0,0 +1,48 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef MAT_CONSTS_H_ +#define MAT_CONSTS_H_ + +namespace mat_consts +{ + template + struct constants + { + const static T c0_5; + const static T c2_0; + }; + + template const T constants::c0_5 = static_cast(0.5); + template const T constants::c2_0 = static_cast(2.0); +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.cpp b/src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.cpp new file mode 100644 index 0000000..7493e34 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.cpp @@ -0,0 +1,67 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 "math_helper.hpp" +#include + +namespace cf_tracking +{ + int mod(int dividend, int divisor) + { + // http://stackoverflow.com/questions/12276675/modulus-with-negative-numbers-in-c + return ((dividend % divisor) + divisor) % divisor; + } + + void dftCcs(const cv::Mat& input, cv::Mat& out, int flags) + { + cv::dft(input, out, flags); + } + + void dftNoCcs(const cv::Mat& input, cv::Mat& out, int flags) + { + flags = flags | cv::DFT_COMPLEX_OUTPUT; + cv::dft(input, out, flags); + } + + // use bi-linear interpolation on zoom, area otherwise + // similar to mexResize.cpp of DSST + // http://www.cvl.isy.liu.se/en/research/objrec/visualtracking/scalvistrack/index.html + void depResize(const cv::Mat& source, cv::Mat& dst, const cv::Size& dsize) + { + int interpolationType = cv::INTER_AREA; + + if (dsize.width > source.cols + || dsize.height > source.rows) + interpolationType = cv::INTER_LINEAR; + + cv::resize(source, dst, dsize, 0, 0, interpolationType); + } +} diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.hpp new file mode 100644 index 0000000..ceaca58 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.hpp @@ -0,0 +1,319 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef HELPER_H_ +#define HELPER_H_ + +#include + +#include "cv_ext.hpp" +#include "mat_consts.hpp" + +namespace cf_tracking +{ + void dftCcs(const cv::Mat& input, cv::Mat& out, int flags = 0); + void dftNoCcs(const cv::Mat& input, cv::Mat& out, int flags = 0); + int mod(int dividend, int divisor); + void depResize(const cv::Mat& source, cv::Mat& dst, const cv::Size& dsize); + + template + cv::Size_ sizeFloor(cv::Size_ size) + { + return cv::Size_(floor(size.width), floor(size.height)); + } + + template + cv::Mat numberToRowVector(int n) + { + cv::Mat_ rowVec(n, 1); + + for (int i = 0; i < n; ++i) + rowVec.template at(i, 0) = static_cast(i + 1); + + return rowVec; + } + + template + cv::Mat numberToColVector(int n) + { + cv::Mat_ colVec(1, n); + + for (int i = 0; i < n; ++i) + colVec.template at(0, i) = static_cast(i + 1); + + return colVec; + } + + // http://home.isr.uc.pt/~henriques/circulant/ + template + T subPixelPeak(T* p) + { + T delta = mat_consts::constants::c0_5 * (p[2] - p[0]) / (2 * p[1] - p[2] - p[0]); + + if (!std::isfinite(delta)) + return 0; + + return delta; + } + + // http://home.isr.uc.pt/~henriques/circulant/ + template + cv::Point_ subPixelDelta(const cv::Mat& response, const cv::Point2i& delta) + { + cv::Point_ subDelta(static_cast(delta.x), static_cast(delta.y)); + T vNeighbors[3] = {}; + T hNeighbors[3] = {}; + + for (int i = -1; i < 2; ++i) + { + vNeighbors[i + 1] = response.template at(mod(delta.y + i, response.rows), delta.x); + hNeighbors[i + 1] = response.template at(delta.y, mod(delta.x + i, response.cols)); + } + + subDelta.y += subPixelPeak(vNeighbors); + subDelta.x += subPixelPeak(hNeighbors); + + return subDelta; + } + + // http://home.isr.uc.pt/~henriques/circulant/ + template + cv::Mat gaussianShapedLabels2D(T sigma, const cv::Size_& size) + { + int width = static_cast(size.width); + int height = static_cast(size.height); + + cv::Mat_ rs(height, width); + + CV_Assert(rs.isContinuous()); + + T lowerBoundX = static_cast(-floor(width * 0.5) + 1); + T lowerBoundY = static_cast(-floor(height * 0.5) + 1); + + T* colValues = new T[width]; + T* rsd = rs.template ptr(0, 0); + T rowValue = 0; + T sigmaMult = static_cast(-0.5 / (sigma*sigma)); + + for (int i = 0; i < width; ++i) + colValues[i] = (i + lowerBoundX) * (i + lowerBoundX); + + for (int row = 0; row < height; ++row) + { + rowValue = (row + lowerBoundY) * (row + lowerBoundY); + + for (int col = 0; col < width; ++col) + { + rsd[row*width + col] = exp((colValues[col] + rowValue) * sigmaMult); + } + } + + delete[] colValues; + + return rs; + } + + // http://home.isr.uc.pt/~henriques/circulant/ + template + cv::Mat gaussianShapedLabelsShifted2D(T sigma, const cv::Size_& size) + { + cv::Mat y = gaussianShapedLabels2D(sigma, size); + cv::Point2f delta(static_cast(1 - floor(size.width * 0.5)), + static_cast(1 - floor(size.height * 0.5))); + + shift(y, y, delta, cv::BORDER_WRAP); + + CV_Assert(y.at(0, 0) == 1.0); + return y; + } + + template + cv::Mat pow(BT base_, const cv::Mat_& exponent) + { + cv::Mat dst = cv::Mat(exponent.rows, exponent.cols, exponent.type()); + int widthChannels = exponent.cols * exponent.channels(); + int height = exponent.rows; + + // http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-efficient-way + if (exponent.isContinuous()) + { + widthChannels *= height; + height = 1; + } + + int row = 0, col = 0; + const ET* exponentd = 0; + ET* dstd = 0; + + for (row = 0; row < height; ++row) + { + exponentd = exponent.template ptr(row); + dstd = dst.template ptr(row); + + for (col = 0; col < widthChannels; ++col) + { + dstd[col] = std::pow(base_, exponentd[col]); + } + } + + return dst; + } + + // http://en.wikipedia.org/wiki/Hann_function + template + cv::Mat hanningWindow(int n) + { + CV_Assert(n > 0); + cv::Mat_ w = cv::Mat_(n, 1); + + if (n == 1) + { + w.template at(0, 0) = 1; + return w; + } + + for (int i = 0; i < n; ++i) + w.template at(i, 0) = static_cast(0.5 * (1.0 - cos(2.0 * 3.14159265358979323846 * i / (n - 1)))); + + return w; + } + + template + void divideSpectrumsNoCcs(const cv::Mat& numerator, const cv::Mat& denominator, cv::Mat& dst) + { + // http://mathworld.wolfram.com/ComplexDivision.html + // (a,b) / (c,d) = ((ac+bd)/v , (bc-ad)/v) + // with v = (c^2 + d^2) + // Performance wise implemented according to + // http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#howtoscanimagesopencv + // TODO: this is still very slow => vectorize (note that mulSpectrums is not vectorized either...) + + int type = numerator.type(); + int channels = numerator.channels(); + + CV_Assert(type == denominator.type() + && numerator.size() == denominator.size() + && channels == denominator.channels() && channels == 2); + CV_Assert(type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2); + + dst = cv::Mat(numerator.rows, numerator.cols, type); + int widthChannels = numerator.cols * channels; + int height = numerator.rows; + + if (numerator.isContinuous() && denominator.isContinuous()) + { + widthChannels *= height; + height = 1; + } + + int row = 0, col = 0; + const T* numd, *denomd; + T* dstd; + T a, b, c, d, v; + + for (row = 0; row < height; ++row) + { + numd = numerator.ptr(row); + denomd = denominator.ptr(row); + dstd = dst.ptr(row); + + for (col = 0; col < widthChannels; col += 2) + { + a = numd[col]; // real part + b = numd[col + 1]; // imag part + c = denomd[col]; // real part + d = denomd[col + 1]; // imag part + + v = (c * c) + (d * d); + + dstd[col] = (a * c + b * d) / v; + dstd[col + 1] = (b * c - a * d) / v; + } + } + } + + // http://home.isr.uc.pt/~henriques/circulant/ + template + bool getSubWindow(const cv::Mat& image, cv::Mat& patch, const cv::Size_& size, + const cv::Point_& pos, cv::Point_* posInSubWindow = 0) + { + int width = static_cast(size.width); + int height = static_cast(size.height); + + int xs = static_cast(std::floor(pos.x) - std::floor(width / 2.0)) + 1; + int ys = static_cast(std::floor(pos.y) - std::floor(height / 2.0)) + 1; + T posInSubWindowX = pos.x - xs; + T posInSubWindowY = pos.y - ys; + + int diffTopX = -xs; + int diffTopY = -ys; + int diffBottomX = image.cols - xs - width; + int diffBottomY = image.rows - ys - height; + + cv::Rect imageRect(0, 0, image.cols, image.rows); + cv::Rect subRect(xs, ys, width, height); + subRect &= imageRect; + cv::Mat subWindow = image(subRect); + + if (subWindow.cols == 0 || subWindow.rows == 0) + return false; + + if (diffTopX > 0 || diffTopY > 0 + || diffBottomX < 0 || diffBottomY < 0) + { + diffTopX = std::max(0, diffTopX); + diffTopY = std::max(0, diffTopY); + diffBottomX = std::min(0, diffBottomX); + diffBottomY = std::min(0, diffBottomY); + + copyMakeBorder(subWindow, subWindow, diffTopY, -diffBottomY, + diffTopX, -diffBottomX, cv::BORDER_REPLICATE); + } + + // this if can be true if the sub window + // is completely outside the image + if (width != subWindow.cols || + height != subWindow.rows) + return false; + + if (posInSubWindow != 0) + { + posInSubWindow->x = posInSubWindowX; + posInSubWindow->y = posInSubWindowY; + } + + patch = subWindow; + + return true; + } +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/scale_estimator.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/scale_estimator.hpp new file mode 100644 index 0000000..4d7e001 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/scale_estimator.hpp @@ -0,0 +1,338 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 class represents the 1D correlation filter proposed in [1]. It is used to estimate the +scale of a target. + +It is implemented closely to the Matlab implementation by the original authors: +http://www.cvl.isy.liu.se/en/research/objrec/visualtracking/scalvistrack/index.html +However, some implementation details differ and some difference in performance +has to be expected. + +Every complex matrix is as default in CCS packed form: +see : https://software.intel.com/en-us/node/504243 +and http://docs.opencv.org/modules/core/doc/operations_on_arrays.html + +References: +[1] M. Danelljan, et al., +"Accurate Scale Estimation for Robust Visual Tracking," +in Proc. BMVC, 2014. + +*/ + +#ifndef SCALE_ESTIMATOR_HPP_ +#define SCALE_ESTIMATOR_HPP_ + +#include +#include +#include + +#include "mat_consts.hpp" +#include "cv_ext.hpp" +#include "feature_channels.hpp" +#include "gradientMex.hpp" +#include "math_helper.hpp" + +namespace cf_tracking +{ + template + struct ScaleEstimatorParas + { + int scaleCellSize = 4; + T scaleModelMaxArea = static_cast(512); + T scaleStep = static_cast(1.02); + int numberOfScales = 33; + T scaleSigmaFactor = static_cast(1.0 / 4.0); + + T lambda = static_cast(0.01); + T learningRate = static_cast(0.025); + + // testing + bool useFhogTranspose = false; + int resizeType = cv::INTER_LINEAR; + bool debugOutput = true; + bool originalVersion = false; + }; + + template + class ScaleEstimator + { + public: + typedef FhogFeatureChannels FFC; + typedef cv::Size_ Size; + typedef cv::Point_ Point; + typedef mat_consts::constants consts; + + ScaleEstimator(ScaleEstimatorParas paras) : + _frameIdx(0), + _isInitialized(false), + _SCALE_CELL_SIZE(paras.scaleCellSize), + _SCALE_MODEL_MAX_AREA(paras.scaleModelMaxArea), + _SCALE_STEP(paras.scaleStep), + _N_SCALES(paras.numberOfScales), + _SCALE_SIGMA_FACTOR(paras.scaleSigmaFactor), + _LAMBDA(paras.lambda), + _LEARNING_RATE(paras.learningRate), + _TYPE(cv::DataType::type), + _RESIZE_TYPE(paras.resizeType), + _DEBUG_OUTPUT(paras.debugOutput), + _ORIGINAL_VERSION(paras.originalVersion) + { + // init dft + cv::Mat initDft = (cv::Mat_(1, 1) << 1); + dft(initDft, initDft); + + if (_DEBUG_OUTPUT) + { + if (CV_MAJOR_VERSION < 3) + { + std::cout << "ScaleEstimator: Using OpenCV Version: " << CV_MAJOR_VERSION << std::endl; + std::cout << "For more speed use 3.0 or higher!" << std::endl; + } + } + + if (paras.useFhogTranspose) + fhogToCvCol = &piotr::fhogToCvColT; + else + fhogToCvCol = &piotr::fhogToCol; + } + + bool reinit(const cv::Mat& image, const Point& pos, + const Size& targetSize, const T& currentScaleFactor) + { + _targetSize = targetSize; + // scale filter output target + T scaleSigma = static_cast(sqrt(_N_SCALES) * _SCALE_SIGMA_FACTOR); + cv::Mat colScales = numberToColVector(_N_SCALES); + T scaleHalf = static_cast(ceil(_N_SCALES / 2.0)); + + cv::Mat ss = colScales - scaleHalf; + cv::Mat ys; + exp(-0.5 * ss.mul(ss) / (scaleSigma * scaleSigma), ys); + + cv::Mat ysf; + // always use CCS here; regular COMPLEX_OUTPUT is bugged + cv::dft(ys, ysf, cv::DFT_ROWS); + + // scale filter cos window + if (_N_SCALES % 2 == 0) + { + _scaleWindow = hanningWindow(_N_SCALES + 1); + _scaleWindow = _scaleWindow.rowRange(1, _scaleWindow.rows); + } + else + { + _scaleWindow = hanningWindow(_N_SCALES); + } + + ss = scaleHalf - colScales; + _scaleFactors = pow(_SCALE_STEP, ss); + _scaleModelFactor = sqrt(_SCALE_MODEL_MAX_AREA / targetSize.area()); + _scaleModelSz = sizeFloor(targetSize * _scaleModelFactor); + + // expand ysf to have the number of rows of scale samples + int ysfRow = static_cast(floor(_scaleModelSz.width / _SCALE_CELL_SIZE) + * floor(_scaleModelSz.height / _SCALE_CELL_SIZE) * FFC::numberOfChannels()); + + _ysf = repeat(ysf, ysfRow, 1); + + cv::Mat sfNum, sfDen; + + if (getScaleTrainingData(image, pos, + currentScaleFactor, sfNum, sfDen) == false) + return false; + + _sfNumerator = sfNum; + _sfDenominator = sfDen; + + _isInitialized = true; + ++_frameIdx; + return true; + } + + virtual ~ScaleEstimator(){} + + bool detectScale(const cv::Mat& image, const Point& pos, + T& currentScaleFactor) const + { + cv::Mat xs; + if (getScaleFeatures(image, pos, xs, currentScaleFactor) == false) + return false; + + cv::Mat xsf; + dft(xs, xsf, cv::DFT_ROWS); + + mulSpectrums(_sfNumerator, xsf, xsf, cv::DFT_ROWS); + reduce(xsf, xsf, 0, cv::REDUCE_SUM, -1); + + cv::Mat sfDenLambda; + sfDenLambda = addRealToSpectrum(_LAMBDA, _sfDenominator, cv::DFT_ROWS); + + cv::Mat responseSf; + divSpectrums(xsf, sfDenLambda, responseSf, cv::DFT_ROWS, false); + + cv::Mat scaleResponse; + idft(responseSf, scaleResponse, cv::DFT_REAL_OUTPUT | cv::DFT_SCALE | cv::DFT_ROWS); + + cv::Point recoveredScale; + double maxScaleResponse; + minMaxLoc(scaleResponse, 0, &maxScaleResponse, 0, &recoveredScale); + + currentScaleFactor *= _scaleFactors.at(recoveredScale); + + currentScaleFactor = std::max(currentScaleFactor, _MIN_SCALE_FACTOR); + currentScaleFactor = std::min(currentScaleFactor, _MAX_SCALE_FACTOR); + return true; + } + + bool updateScale(const cv::Mat& image, const Point& pos, + const T& currentScaleFactor) + { + ++_frameIdx; + cv::Mat sfNum, sfDen; + + if (getScaleTrainingData(image, pos, currentScaleFactor, + sfNum, sfDen) == false) + return false; + + // both summands are in CCS packaged format; thus adding is OK + _sfDenominator = (1 - _LEARNING_RATE) * _sfDenominator + _LEARNING_RATE * sfDen; + _sfNumerator = (1 - _LEARNING_RATE) * _sfNumerator + _LEARNING_RATE * sfNum; + return true; + } + + private: + bool getScaleTrainingData(const cv::Mat& image, + const Point& pos, + const T& currentScaleFactor, + cv::Mat& sfNum, cv::Mat& sfDen) const + { + cv::Mat xs; + if (getScaleFeatures(image, pos, xs, currentScaleFactor) == false) + return false; + + cv::Mat xsf; + dft(xs, xsf, cv::DFT_ROWS); + mulSpectrums(_ysf, xsf, sfNum, cv::DFT_ROWS, true); + cv::Mat mulTemp; + mulSpectrums(xsf, xsf, mulTemp, cv::DFT_ROWS, true); + reduce(mulTemp, sfDen, 0, cv::REDUCE_SUM, -1); + return true; + } + + bool getScaleFeatures(const cv::Mat& image, const Point& pos, + cv::Mat& features, T scale) const + { + int colElems = _ysf.rows; + features = cv::Mat::zeros(colElems, _N_SCALES, _TYPE); + cv::Mat patch; + cv::Mat patchResized; + cv::Mat patchResizedFloat; + cv::Mat firstPatch; + T cosFactor = -1; + + // do not extract features for first and last scale, + // since the scaleWindow will always multiply these with 0; + // extract first required sub window separately; smaller scales are extracted + // from this patch to avoid multiple border replicates on out of image patches + int idxScale = 1; + T patchScale = scale * _scaleFactors.at(0, idxScale); + Size firstPatchSize = sizeFloor(_targetSize * patchScale); + Point posInFirstPatch(0, 0); + cosFactor = _scaleWindow.at(idxScale, 0); + + if (getSubWindow(image, firstPatch, firstPatchSize, pos, &posInFirstPatch) == false) + return false; + + if (_ORIGINAL_VERSION) + depResize(firstPatch, patchResized, _scaleModelSz); + else + cv::resize(firstPatch, patchResized, _scaleModelSz, 0, 0, _RESIZE_TYPE); + + patchResized.convertTo(patchResizedFloat, CV_32FC(3)); + fhogToCvCol(patchResizedFloat, features, _SCALE_CELL_SIZE, idxScale, cosFactor); + + for (idxScale = 2; idxScale < _N_SCALES - 1; ++idxScale) + { + T patchScale = scale *_scaleFactors.at(0, idxScale); + Size patchSize = sizeFloor(_targetSize * patchScale); + cosFactor = _scaleWindow.at(idxScale, 0); + + if (getSubWindow(firstPatch, patch, patchSize, posInFirstPatch) == false) + return false; + + if (_ORIGINAL_VERSION) + depResize(patch, patchResized, _scaleModelSz); + else + cv::resize(patch, patchResized, _scaleModelSz, 0, 0, _RESIZE_TYPE); + + patchResized.convertTo(patchResizedFloat, CV_32FC(3)); + fhogToCvCol(patchResizedFloat, features, _SCALE_CELL_SIZE, idxScale, cosFactor); + } + + return true; + } + + private: + typedef void(*fhogToCvRowPtr) + (const cv::Mat& img, cv::Mat& cvFeatures, int binSize, int rowIdx, T cosFactor); + fhogToCvRowPtr fhogToCvCol = 0; + + cv::Mat _scaleWindow; + T _scaleModelFactor = 0; + cv::Mat _sfNumerator; + cv::Mat _sfDenominator; + cv::Mat _scaleFactors; + Size _scaleModelSz; + Size _targetSize; + cv::Mat _ysf; + int _frameIdx; + bool _isInitialized; + + const int _TYPE; + const int _SCALE_CELL_SIZE; + const T _SCALE_MODEL_MAX_AREA; + const T _SCALE_STEP; + const int _N_SCALES; + const T _SCALE_SIGMA_FACTOR; + const T _LAMBDA; + const T _LEARNING_RATE; + const int _RESIZE_TYPE; + // it should be possible to find more reasonable values for min/max scale; application dependent + T _MIN_SCALE_FACTOR = static_cast(0.01); + T _MAX_SCALE_FACTOR = static_cast(40); + + const bool _DEBUG_OUTPUT; + const bool _ORIGINAL_VERSION; + }; +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/common/tracker_debug.hpp b/src/3rdparty/cf_tracking/src/cf_libs/common/tracker_debug.hpp new file mode 100644 index 0000000..3b7e469 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/common/tracker_debug.hpp @@ -0,0 +1,49 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef TRACKER_DEBUG_HPP_ +#define TRACKER_DEBUG_HPP_ + +namespace cf_tracking +{ + class TrackerDebug + { + public: + virtual ~TrackerDebug(){} + + virtual void init(std::string outputFilePath) = 0; + virtual void printOnImage(cv::Mat& image) = 0; + virtual void printConsoleOutput() = 0; + virtual void printToFile() = 0; + }; +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_debug.hpp b/src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_debug.hpp new file mode 100644 index 0000000..6fc6825 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_debug.hpp @@ -0,0 +1,127 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef DSST_DEBUG_HPP_ +#define DSST_DEBUG_HPP_ + +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/core/core.hpp" +#include +#include + +#include "tracker_debug.hpp" + +namespace cf_tracking +{ + template + class DsstDebug : public TrackerDebug + { + public: + DsstDebug() : + _maxResponse(0), + _psrClamped(0), + _targetSizeArea(0) + {} + + virtual ~DsstDebug() + { + if (_outputFile.is_open()) + _outputFile.close(); + } + + virtual void init(std::string outputFilePath) + { + namedWindow(_SUB_WINDOW_TITLE, cv::WINDOW_NORMAL); + namedWindow(_RESPONSE_TITLE, cv::WINDOW_NORMAL); + _outputFile.open(outputFilePath.c_str()); + } + + virtual void printOnImage(cv::Mat& image) + { + _ss.str(""); + _ss.clear(); + _ss << "Max Response: " << _maxResponse; + putText(image, _ss.str(), cv::Point(20, 40), cv::FONT_HERSHEY_TRIPLEX, 0.5, cv::Scalar(255, 0, 0)); + + _ss.str(""); + _ss.clear(); + _ss << "PSR Clamped: " << _psrClamped; + putText(image, _ss.str(), cv::Point(20, 80), cv::FONT_HERSHEY_TRIPLEX, 0.5, cv::Scalar(255, 0, 0)); + + _ss.str(""); + _ss.clear(); + _ss << "Area: " << _targetSizeArea; + putText(image, _ss.str(), cv::Point(image.cols - 100, 80), cv::FONT_HERSHEY_TRIPLEX, 0.5, cv::Scalar(255, 0, 0)); + } + + virtual void printConsoleOutput() + { + } + + virtual void printToFile() + { + _outputFile << _maxResponse << "," << _psrClamped << std::endl; + } + + void showPatch(const cv::Mat& patchResized) + { + imshow(_SUB_WINDOW_TITLE, patchResized); + } + + void setPsr(double psrClamped) + { + _psrClamped = psrClamped; + } + + void showResponse(const cv::Mat& response, double maxResponse) + { + cv::Mat responseOutput = response.clone(); + _maxResponse = maxResponse; + imshow(_RESPONSE_TITLE, responseOutput); + } + + void setTargetSizeArea(T targetSizeArea) + { + _targetSizeArea = targetSizeArea; + } + + private: + const std::string _SUB_WINDOW_TITLE = "Sub Window"; + const std::string _RESPONSE_TITLE = "Response"; + double _maxResponse; + double _psrClamped; + T _targetSizeArea; + std::stringstream _ss; + std::ofstream _outputFile; + }; +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_tracker.hpp b/src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_tracker.hpp new file mode 100644 index 0000000..20b847e --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_tracker.hpp @@ -0,0 +1,707 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 class represents a C++ implementation of the Discriminative Scale +Space Tracker (DSST) [1]. The class contains the 2D translational filter. +The 1D scale filter can be found in scale_estimator.hpp. + +It is implemented closely to the Matlab implementation by the original authors: +http://www.cvl.isy.liu.se/en/research/objrec/visualtracking/scalvistrack/index.html +However, some implementation details differ and some difference in performance +has to be expected. + +Additionally, target loss detection is implemented according to [2]. + +Every complex matrix is as default in CCS packed form: +see: https://software.intel.com/en-us/node/504243 +and http://docs.opencv.org/modules/core/doc/operations_on_arrays.html + +References: +[1] M. Danelljan, et al., +"Accurate Scale Estimation for Robust Visual Tracking," +in Proc. BMVC, 2014. + +[2] D. Bolme, et al., +“Visual Object Tracking using Adaptive Correlation Filters,” +in Proc. CVPR, 2010. +*/ + +#ifndef DSST_TRACKER_HPP_ +#define DSST_TRACKER_HPP_ + +#include +#include +#include +#include +#include +#include + +#include "cv_ext.hpp" +#include "mat_consts.hpp" +#include "feature_channels.hpp" +#include "gradientMex.hpp" +#include "math_helper.hpp" +#include "cf_tracker.hpp" +#include "scale_estimator.hpp" +#include "dsst_debug.hpp" +#include "psr.hpp" + +namespace cf_tracking +{ + struct DsstParameters + { + double padding = static_cast(1.6); + double outputSigmaFactor = static_cast(0.05); + double lambda = static_cast(0.01); + double learningRate = static_cast(0.012); + int templateSize = 100; + int cellSize = 2; + + bool enableTrackingLossDetection = false; + double psrThreshold = 13.5; + int psrPeakDel = 1; + + bool enableScaleEstimator = true; + double scaleSigmaFactor = static_cast(0.25); + double scaleStep = static_cast(1.02); + int scaleCellSize = 4; + int numberOfScales = 33; + + //testing + bool originalVersion = false; + int resizeType = cv::INTER_LINEAR; + bool useFhogTranspose = false; + }; + + class DsstTracker : public CfTracker + { + public: + typedef float T; // set precision here double or float + static const int CV_TYPE = cv::DataType::type; + typedef cv::Size_ Size; + typedef cv::Point_ Point; + typedef cv::Rect_ Rect; + typedef FhogFeatureChannels FFC; + typedef DsstFeatureChannels DFC; + typedef mat_consts::constants consts; + + DsstTracker(DsstParameters paras, DsstDebug* debug = 0) + : _isInitialized(false), + _scaleEstimator(0), + _PADDING(static_cast(paras.padding)), + _OUTPUT_SIGMA_FACTOR(static_cast(paras.outputSigmaFactor)), + _LAMBDA(static_cast(paras.lambda)), + _LEARNING_RATE(static_cast(paras.learningRate)), + _CELL_SIZE(paras.cellSize), + _TEMPLATE_SIZE(paras.templateSize), + _PSR_THRESHOLD(static_cast(paras.psrThreshold)), + _PSR_PEAK_DEL(paras.psrPeakDel), + _MIN_AREA(10), + _MAX_AREA_FACTOR(0.8), + _ID("DSSTcpp"), + _ENABLE_TRACKING_LOSS_DETECTION(paras.enableTrackingLossDetection), + _ORIGINAL_VERSION(paras.originalVersion), + _RESIZE_TYPE(paras.resizeType), + _USE_CCS(true), + _debug(debug) + { + if (paras.enableScaleEstimator) + { + ScaleEstimatorParas sp; + sp.scaleCellSize = paras.scaleCellSize; + sp.scaleStep = static_cast(paras.scaleStep); + sp.numberOfScales = paras.numberOfScales; + sp.scaleSigmaFactor = static_cast(paras.scaleSigmaFactor); + sp.lambda = static_cast(paras.lambda); + sp.learningRate = static_cast(paras.learningRate); + sp.useFhogTranspose = paras.useFhogTranspose; + sp.resizeType = paras.resizeType; + sp.originalVersion = paras.originalVersion; + _scaleEstimator = new ScaleEstimator(sp); + } + + if (paras.useFhogTranspose) + cvFhog = &piotr::cvFhogT < T, DFC > ; + else + cvFhog = &piotr::cvFhog < T, DFC > ; + + if (_USE_CCS) + calcDft = &cf_tracking::dftCcs; + else + calcDft = &cf_tracking::dftNoCcs; + + // init dft + cv::Mat initDft = (cv::Mat_(1, 1) << 1); + calcDft(initDft, initDft, 0); + + if (CV_MAJOR_VERSION < 3) + { + std::cout << "DsstTracker: Using OpenCV Version: " << CV_MAJOR_VERSION << std::endl; + std::cout << "For more speed use 3.0 or higher!" << std::endl; + } + } + + virtual ~DsstTracker() + { + delete _scaleEstimator; + } + + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + return reinit_(image, bb); + } + + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + return reinit_(image, bb); + } + + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + return reinit_(image, bb); + } + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + if (update_(image, bb) == false) + return false; + + boundingBox.x = static_cast(round(bb.x)); + boundingBox.y = static_cast(round(bb.y)); + boundingBox.width = static_cast(round(bb.width)); + boundingBox.height = static_cast(round(bb.height)); + + return true; + } + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + if (update_(image, bb) == false) + return false; + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + return true; + } + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + if (update_(image, bb) == false) + return false; + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return true; + } + + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = updateAt_(image, bb); + + boundingBox.x = static_cast(round(bb.x)); + boundingBox.y = static_cast(round(bb.y)); + boundingBox.width = static_cast(round(bb.width)); + boundingBox.height = static_cast(round(bb.height)); + + return isValid; + } + + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = updateAt_(image, bb); + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return isValid; + } + + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = updateAt_(image, bb); + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return isValid; + } + + virtual TrackerDebug* getTrackerDebug() + { + return _debug; + } + + virtual const std::string getId() + { + return _ID; + } + + private: + DsstTracker& operator=(const DsstTracker&) + {} + + bool reinit_(const cv::Mat& image, Rect& boundingBox) + { + _pos.x = floor(boundingBox.x) + floor(boundingBox.width * consts::c0_5); + _pos.y = floor(boundingBox.y) + floor(boundingBox.height * consts::c0_5); + Size targetSize = Size(boundingBox.width, boundingBox.height); + + _templateSz = Size(floor(targetSize.width * (1 + _PADDING)), + floor(targetSize.height * (1 + _PADDING))); + + _scale = 1.0; + + if (!_ORIGINAL_VERSION) + { + // resize to fixed side length _TEMPLATE_SIZE to stabilize FPS + if (_templateSz.height > _templateSz.width) + _scale = _templateSz.height / _TEMPLATE_SIZE; + else + _scale = _templateSz.width / _TEMPLATE_SIZE; + + _templateSz = Size(floor(_templateSz.width / _scale), floor(_templateSz.height / _scale)); + } + + _baseTargetSz = Size(targetSize.width / _scale, targetSize.height / _scale); + _templateScaleFactor = 1 / _scale; + + Size templateSzByCells = Size(floor((_templateSz.width) / _CELL_SIZE), + floor((_templateSz.height) / _CELL_SIZE)); + + // translation filter output target + T outputSigma = sqrt(_templateSz.area() / ((1 + _PADDING) * (1 + _PADDING))) + * _OUTPUT_SIGMA_FACTOR / _CELL_SIZE; + _y = gaussianShapedLabels2D(outputSigma, templateSzByCells); + calcDft(_y, _yf, 0); + + // translation filter hann window + cv::Mat cosWindowX; + cv::Mat cosWindowY; + cosWindowY = hanningWindow(_yf.rows); + cosWindowX = hanningWindow(_yf.cols); + _cosWindow = cosWindowY * cosWindowX.t(); + + std::shared_ptr hfNum(0); + cv::Mat hfDen; + + if (getTranslationTrainingData(image, hfNum, hfDen, _pos) == false) + return false; + + _hfNumerator = hfNum; + _hfDenominator = hfDen; + + if (_scaleEstimator) + { + _scaleEstimator->reinit(image, _pos, targetSize, + _scale * _templateScaleFactor); + } + + _lastBoundingBox = boundingBox; + _isInitialized = true; + return true; + } + + bool getTranslationTrainingData(const cv::Mat& image, std::shared_ptr& hfNum, + cv::Mat& hfDen, const Point& pos) const + { + std::shared_ptr xt(0); + + if (getTranslationFeatures(image, xt, pos, _scale) == false) + return false; + + std::shared_ptr xtf; + + if (_USE_CCS) + xtf = DFC::dftFeatures(xt); + else + xtf = DFC::dftFeatures(xt, cv::DFT_COMPLEX_OUTPUT); + + hfNum = DFC::mulSpectrumsFeatures(_yf, xtf, true); + hfDen = DFC::sumFeatures(DFC::mulSpectrumsFeatures(xtf, xtf, true)); + + return true; + } + + bool getTranslationFeatures(const cv::Mat& image, std::shared_ptr& features, + const Point& pos, T scale) const + { + cv::Mat patch; + Size patchSize = _templateSz * scale; + + if (getSubWindow(image, patch, patchSize, pos) == false) + return false; + + if (_ORIGINAL_VERSION) + depResize(patch, patch, _templateSz); + else + resize(patch, patch, _templateSz, 0, 0, _RESIZE_TYPE); + + if (_debug != 0) + _debug->showPatch(patch); + + cv::Mat floatPatch; + patch.convertTo(floatPatch, CV_32FC(3)); + + features.reset(new DFC()); + cvFhog(floatPatch, features, _CELL_SIZE, DFC::numberOfChannels() - 1); + + // append gray-scale image + if (patch.channels() == 1) + { + if (_CELL_SIZE != 1) + resize(patch, patch, features->channels[0].size(), 0, 0, _RESIZE_TYPE); + + features->channels[DFC::numberOfChannels() - 1] = patch / 255.0 - 0.5; + } + else + { + if (_CELL_SIZE != 1) + resize(patch, patch, features->channels[0].size(), 0, 0, _RESIZE_TYPE); + + cv::Mat grayFrame; + cvtColor(patch, grayFrame, cv::COLOR_BGR2GRAY); + grayFrame.convertTo(grayFrame, CV_TYPE); + grayFrame = grayFrame / 255.0 - 0.5; + features->channels[DFC::numberOfChannels() - 1] = grayFrame; + } + + DFC::mulFeatures(features, _cosWindow); + return true; + } + + bool update_(const cv::Mat& image, Rect& boundingBox) + { + return updateAtScalePos(image, _pos, _scale, boundingBox); + } + + bool updateAt_(const cv::Mat& image, Rect& boundingBox) + { + bool isValid = false; + T scale = 0; + Point pos(boundingBox.x + boundingBox.width * consts::c0_5, + boundingBox.y + boundingBox.height * consts::c0_5); + + // caller's box may have a different aspect ratio + // compared to the _targetSize; use the larger side + // to calculate scale + if (boundingBox.width > boundingBox.height) + scale = boundingBox.width / _baseTargetSz.width; + else + scale = boundingBox.height / _baseTargetSz.height; + + isValid = updateAtScalePos(image, pos, scale, boundingBox); + return isValid; + } + + bool updateAtScalePos(const cv::Mat& image, const Point& oldPos, const T oldScale, + Rect& boundingBox) + { + ++_frameIdx; + + if (!_isInitialized) + return false; + + T newScale = oldScale; + Point newPos = oldPos; + cv::Point2i maxResponseIdx; + cv::Mat response; + + // in case of error return the last box + boundingBox = _lastBoundingBox; + + if (detectModel(image, response, maxResponseIdx, newPos, newScale) == false) + return false; + + // return box + Rect tempBoundingBox; + tempBoundingBox.width = _baseTargetSz.width * newScale; + tempBoundingBox.height = _baseTargetSz.height * newScale; + tempBoundingBox.x = newPos.x - tempBoundingBox.width / 2; + tempBoundingBox.y = newPos.y - tempBoundingBox.height / 2; + + if (_ENABLE_TRACKING_LOSS_DETECTION) + { + if (evalReponse(image, response, maxResponseIdx, + tempBoundingBox) == false) + return false; + } + + if (updateModel(image, newPos, newScale) == false) + return false; + + boundingBox &= Rect(0, 0, static_cast(image.cols), static_cast(image.rows)); + boundingBox = tempBoundingBox; + _lastBoundingBox = tempBoundingBox; + return true; + } + + bool evalReponse(const cv::Mat &image, const cv::Mat& response, + const cv::Point2i& maxResponseIdx, + const Rect& tempBoundingBox) const + { + T peakValue = 0; + T psrClamped = calcPsr(response, maxResponseIdx, _PSR_PEAK_DEL, peakValue); + + if (_debug != 0) + { + _debug->showResponse(response, peakValue); + _debug->setPsr(psrClamped); + } + + if (psrClamped < _PSR_THRESHOLD) + return false; + + // check if we are out of image, too small or too large + Rect imageRect(Point(0, 0), image.size()); + Rect intersection = imageRect & tempBoundingBox; + double bbArea = tempBoundingBox.area(); + double areaThreshold = _MAX_AREA_FACTOR * imageRect.area(); + double intersectDiff = std::abs(bbArea - intersection.area()); + + if (intersectDiff > 0.01 || bbArea < _MIN_AREA + || bbArea > areaThreshold) + return false; + + return true; + } + + bool detectModel(const cv::Mat& image, cv::Mat& response, + cv::Point2i& maxResponseIdx, Point& newPos, + T& newScale) const + { + // find translation + std::shared_ptr xt(0); + + if (getTranslationFeatures(image, xt, newPos, newScale) == false) + return false; + + std::shared_ptr xtf; + if (_USE_CCS) + xtf = DFC::dftFeatures(xt); + else + xtf = DFC::dftFeatures(xt, cv::DFT_COMPLEX_OUTPUT); + + std::shared_ptr sampleSpec = DFC::mulSpectrumsFeatures(_hfNumerator, xtf, false); + cv::Mat sumXtf = DFC::sumFeatures(sampleSpec); + cv::Mat hfDenLambda = addRealToSpectrum(_LAMBDA, _hfDenominator); + cv::Mat responseTf; + + if (_USE_CCS) + divSpectrums(sumXtf, hfDenLambda, responseTf, 0, false); + else + divideSpectrumsNoCcs(sumXtf, hfDenLambda, responseTf); + + cv::Mat translationResponse; + idft(responseTf, translationResponse, cv::DFT_REAL_OUTPUT | cv::DFT_SCALE); + + cv::Point delta; + double maxResponse; + cv::Point_ subDelta; + minMaxLoc(translationResponse, 0, &maxResponse, 0, &delta); + subDelta = delta; + + if (_CELL_SIZE != 1) + subDelta = subPixelDelta(translationResponse, delta); + + T posDeltaX = (subDelta.x + 1 - floor(translationResponse.cols / consts::c2_0)) * newScale; + T posDeltaY = (subDelta.y + 1 - floor(translationResponse.rows / consts::c2_0)) * newScale; + newPos.x += round(posDeltaX * _CELL_SIZE); + newPos.y += round(posDeltaY * _CELL_SIZE); + + if (_debug != 0) + _debug->showResponse(translationResponse, maxResponse); + + if (_scaleEstimator) + { + //find scale + T tempScale = newScale * _templateScaleFactor; + + if (_scaleEstimator->detectScale(image, newPos, + tempScale) == false) + return false; + + newScale = tempScale / _templateScaleFactor; + } + + response = translationResponse; + maxResponseIdx = delta; + return true; + } + + bool updateModel(const cv::Mat& image, const Point& newPos, + T newScale) + { + _pos = newPos; + _scale = newScale; + std::shared_ptr hfNum(0); + cv::Mat hfDen; + + if (getTranslationTrainingData(image, hfNum, hfDen, _pos) == false) + return false; + + _hfDenominator = (1 - _LEARNING_RATE) * _hfDenominator + _LEARNING_RATE * hfDen; + DFC::mulValueFeatures(_hfNumerator, (1 - _LEARNING_RATE)); + DFC::mulValueFeatures(hfNum, _LEARNING_RATE); + DFC::addFeatures(_hfNumerator, hfNum); + + if (_scaleEstimator) + { + if (_scaleEstimator->updateScale(image, newPos, newScale * _templateScaleFactor) == false) + return false; + } + + return true; + } + + private: + typedef void(*cvFhogPtr) + (const cv::Mat& img, std::shared_ptr& cvFeatures, int binSize, int fhogChannelsToCopy); + cvFhogPtr cvFhog = 0; + + typedef void(*dftPtr) + (const cv::Mat& input, cv::Mat& output, int flags); + dftPtr calcDft = 0; + + cv::Mat _cosWindow; + cv::Mat _y; + std::shared_ptr _hfNumerator; + cv::Mat _hfDenominator; + cv::Mat _yf; + Point _pos; + Size _templateSz; + Size _templateSizeNoFloor; + Size _baseTargetSz; + Rect _lastBoundingBox; + T _scale; // _scale is the scale of the template; not the target + T _templateScaleFactor; // _templateScaleFactor is used to calc the target scale + ScaleEstimator* _scaleEstimator; + int _frameIdx = 1; + bool _isInitialized; + + const double _MIN_AREA; + const double _MAX_AREA_FACTOR; + const T _PADDING; + const T _OUTPUT_SIGMA_FACTOR; + const T _LAMBDA; + const T _LEARNING_RATE; + const T _PSR_THRESHOLD; + const int _PSR_PEAK_DEL; + const int _CELL_SIZE; + const int _TEMPLATE_SIZE; + const std::string _ID; + const bool _ENABLE_TRACKING_LOSS_DETECTION; + const int _RESIZE_TYPE; + const bool _ORIGINAL_VERSION; + const bool _USE_CCS; + + DsstDebug* _debug; + }; +} + +#endif /* KCF_TRACKER_H_ */ diff --git a/src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_debug.hpp b/src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_debug.hpp new file mode 100644 index 0000000..ca010b8 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_debug.hpp @@ -0,0 +1,116 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef KCF_DEBUG_HPP_ +#define KCF_DEBUG_HPP_ + +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/core/core.hpp" +#include +#include + +#include "tracker_debug.hpp" + +namespace cf_tracking +{ + template + class KcfDebug : public TrackerDebug + { + public: + KcfDebug() : + _maxResponse(0), + _psrClamped(0) + {} + + virtual ~KcfDebug() + { + if (_outputFile.is_open()) + _outputFile.close(); + } + + virtual void init(std::string outputFilePath) + { + namedWindow(_SUB_WINDOW_TITLE, cv::WINDOW_NORMAL); + namedWindow(_RESPONSE_TITLE, cv::WINDOW_NORMAL); + _outputFile.open(outputFilePath.c_str()); + } + + virtual void printOnImage(cv::Mat& image) + { + _ss.str(""); + _ss.clear(); + _ss << "Max Response: " << _maxResponse; + putText(image, _ss.str(), cv::Point(20, 40), cv::FONT_HERSHEY_TRIPLEX, 0.5, cv::Scalar(255, 0, 0)); + + _ss.str(""); + _ss.clear(); + _ss << "PSR Clamped: " << _psrClamped; + putText(image, _ss.str(), cv::Point(20, 80), cv::FONT_HERSHEY_TRIPLEX, 0.5, cv::Scalar(255, 0, 0)); + } + + virtual void printConsoleOutput() + { + } + + virtual void printToFile() + { + _outputFile << _maxResponse << "," << _psrClamped << std::endl; + } + + void showPatch(const cv::Mat& patchResized) + { + imshow(_SUB_WINDOW_TITLE, patchResized); + } + + void setPsr(T psrClamped) + { + _psrClamped = psrClamped; + std::cout << "PSR: " << psrClamped << std::endl; + } + + void showResponse(const cv::Mat& response, T maxResponse) + { + cv::Mat responseOutput = response.clone(); + _maxResponse = maxResponse; + imshow(_RESPONSE_TITLE, responseOutput); + } + + private: + const std::string _SUB_WINDOW_TITLE = "Sub Window"; + const std::string _RESPONSE_TITLE = "Response"; + T _maxResponse; + T _psrClamped; + std::stringstream _ss; + std::ofstream _outputFile; + }; +} + +#endif diff --git a/src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_tracker.hpp b/src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_tracker.hpp new file mode 100644 index 0000000..036a898 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_tracker.hpp @@ -0,0 +1,931 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 class represents a C++ implementation of the Kernelized +Correlation Filter tracker (KCF) [1]. + +It is implemented closely to the Matlab implementation by the original authors: +http://home.isr.uc.pt/~henriques/circulant/ +However, some implementation details differ and some difference in performance +has to be expected. + +This specific implementation features the scale adaption, sub-pixel +accuracy for the correlation response evaluation and a more robust +filter update scheme [2] used by Henriques, et al. in the VOT Challenge 2014. + +As default scale adaption, the tracker uses the 1D scale filter +presented in [3]. The scale filter can be found in scale_estimator.hpp. +Additionally, target loss detection is implemented according to [4]. + +Every complex matrix is as default in CCS packed form: +see : https://software.intel.com/en-us/node/504243 +and http://docs.opencv.org/modules/core/doc/operations_on_arrays.html + +References: +[1] J. Henriques, et al., +"High-Speed Tracking with Kernelized Correlation Filters," +PAMI, 2015. + +[2] M. Danelljan, et al., +“Adaptive Color Attributes for Real-Time Visual Tracking,” +in Proc. CVPR, 2014. + +[3] M. Danelljan, +"Accurate Scale Estimation for Robust Visual Tracking," +Proceedings of the British Machine Vision Conference BMVC, 2014. + +[4] D. Bolme, et al., +“Visual Object Tracking using Adaptive Correlation Filters,” +in Proc. CVPR, 2010. +*/ + +#ifndef KCF_TRACKER_HPP_ +#define KCF_TRACKER_HPP_ + +#include +#include +#include +#include +#include + +#include "cv_ext.hpp" +#include "feature_channels.hpp" +#include "gradientMex.hpp" +#include "mat_consts.hpp" +#include "math_helper.hpp" +#include "cf_tracker.hpp" +#include "kcf_debug.hpp" +#include "scale_estimator.hpp" +#include "psr.hpp" + +namespace cf_tracking +{ + struct KcfParameters + { + double padding = 1.7; + double lambda = 0.0001; + double outputSigmaFactor = 0.05; + double votScaleStep = 1.05; + double votScaleWeight = 0.95; + int templateSize = 100; + double interpFactor = 0.012; + double kernelSigma = 0.6; + int cellSize = 4; + int pixelPadding = 0; + + bool enableTrackingLossDetection = false; + double psrThreshold = 13.5; + int psrPeakDel = 1; + + bool useVotScaleEstimation = false; + bool useDsstScaleEstimation = true; + double scaleSigmaFactor = static_cast(0.25); + double scaleEstimatorStep = static_cast(1.02); + double scaleLambda = static_cast(0.01); + int scaleCellSize = 4; + int numberOfScales = 33; + + // testing + int resizeType = cv::INTER_LINEAR; + bool useFhogTranspose = false; + }; + + class KcfTracker : public CfTracker + { + public: + static const int NUM_FEATURE_CHANNELS = 31; + typedef double T; // set precision here: double or float + static const int CV_TYPE = cv::DataType::type; + typedef cv::Size_ Size; + typedef FhogFeatureChannels FFC; + typedef mat_consts::constants consts; + typedef cv::Point_ Point; + typedef cv::Rect_ Rect; + + KcfTracker(KcfParameters paras, KcfDebug* debug = 0) + : _isInitialized(false), + _PADDING(static_cast(paras.padding)), + _LAMBDA(static_cast(paras.lambda)), + _OUTPUT_SIGMA_FACTOR(static_cast(paras.outputSigmaFactor)), + _SCALE_STEP(static_cast(paras.votScaleStep)), + _SCALE_WEIGHT(static_cast(paras.votScaleWeight)), + _TEMPLATE_SIZE(paras.templateSize), + _INTERP_FACTOR(static_cast(paras.interpFactor)), + _KERNEL_SIGMA(static_cast(paras.kernelSigma)), + _CELL_SIZE(paras.cellSize), + _PIXEL_PADDING(paras.pixelPadding), + _N_SCALES_VOT(3), + _USE_VOT_SCALE_ESTIMATION(paras.useVotScaleEstimation), + _ENABLE_TRACKING_LOSS_DETECTION(paras.enableTrackingLossDetection), + _PSR_THRESHOLD(static_cast(paras.psrThreshold)), + _PSR_PEAK_DEL(paras.psrPeakDel), + _MIN_AREA(10), + _MAX_AREA_FACTOR(static_cast(0.8)), + _RESIZE_TYPE(paras.resizeType), + _ID("KCFcpp"), + _USE_CCS(true), + _scaleEstimator(0), + _debug(debug) + { + correlate = &KcfTracker::gaussianCorrelation; + + if (paras.useDsstScaleEstimation) + { + ScaleEstimatorParas sp; + sp.scaleCellSize = paras.scaleCellSize; + sp.scaleStep = static_cast(paras.scaleEstimatorStep); + sp.numberOfScales = paras.numberOfScales; + sp.scaleSigmaFactor = static_cast(paras.scaleSigmaFactor); + sp.lambda = static_cast(paras.scaleLambda); + sp.learningRate = static_cast(paras.interpFactor); + sp.useFhogTranspose = paras.useFhogTranspose; + _scaleEstimator = new ScaleEstimator(sp); + } + + // init dft + cv::Mat initDft = (cv::Mat_(1, 1) << 1); + dft(initDft, initDft); + + if (paras.useFhogTranspose) + cvFhog = &piotr::cvFhogT < T, FFC > ; + else + cvFhog = &piotr::cvFhog < T, FFC > ; + + if (_debug != 0) + { + if (CV_MAJOR_VERSION < 3) + { + std::cout << "KcfTracker: Using OpenCV Version: " << CV_MAJOR_VERSION << "." << CV_MINOR_VERSION << std::endl; + std::cout << "For more speed use 3.0 or higher!" << std::endl; + } + } + } + + virtual ~KcfTracker() + { + delete _scaleEstimator; + } + + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + return reinit_(image, bb); + } + + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + return reinit_(image, bb); + } + + virtual bool reinit(const cv::Mat& image, cv::Rect_& boundingBox) + { + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + return reinit_(image, bb); + } + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = update_(image, bb); + + boundingBox.x = static_cast(round(bb.x)); + boundingBox.y = static_cast(round(bb.y)); + boundingBox.width = static_cast(round(bb.width)); + boundingBox.height = static_cast(round(bb.height)); + + return isValid; + } + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = update_(image, bb); + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return isValid; + } + + virtual bool update(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = update_(image, bb); + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return isValid; + } + + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = updateAt_(image, bb); + + boundingBox.x = static_cast(round(bb.x)); + boundingBox.y = static_cast(round(bb.y)); + boundingBox.width = static_cast(round(bb.width)); + boundingBox.height = static_cast(round(bb.height)); + + return isValid; + } + + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = updateAt_(image, bb); + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return isValid; + } + + virtual bool updateAt(const cv::Mat& image, cv::Rect_& boundingBox) + { + bool isValid = false; + + Rect bb = Rect( + static_cast(boundingBox.x), + static_cast(boundingBox.y), + static_cast(boundingBox.width), + static_cast(boundingBox.height) + ); + + isValid = updateAt_(image, bb); + + boundingBox.x = static_cast(bb.x); + boundingBox.y = static_cast(bb.y); + boundingBox.width = static_cast(bb.width); + boundingBox.height = static_cast(bb.height); + + return isValid; + } + + virtual TrackerDebug* getTrackerDebug() + { + return _debug; + } + + virtual const std::string getId() + { + return _ID; + } + + private: + bool reinit_(const cv::Mat& image, Rect& boundingBox) + { + if (boundingBox.width < 1 || boundingBox.height < 1) + return false; + + _lastBoundingBox = boundingBox; + _pos.x = boundingBox.x + boundingBox.width * consts::c0_5; + _pos.y = boundingBox.y + boundingBox.height * consts::c0_5; + + // original target size for scale estimation + Size targetSize = Size(boundingBox.width, boundingBox.height); + + _targetSize = targetSize; + T targetPadding = _PADDING * sqrt(_targetSize.width * _targetSize.height); + Size templateSz = Size(floor(_targetSize.width + targetPadding), + floor(_targetSize.height + targetPadding)); + + if (templateSz.height > templateSz.width) + _scale = templateSz.height / _TEMPLATE_SIZE; + else + _scale = templateSz.width / _TEMPLATE_SIZE; + + _templateScaleFactor = 1 / _scale; + _templateSz = Size(floor(templateSz.width / _scale), floor(templateSz.height / _scale)); + + _targetSize = Size(_targetSize.width / _scale, _targetSize.height / _scale); + + T outputSigma = sqrt(_templateSz.area() / ((1 + _PADDING) * (1 + _PADDING))) + * _OUTPUT_SIGMA_FACTOR / _CELL_SIZE; + Size templateSzByCells = Size(floor((_templateSz.width - _PIXEL_PADDING) / _CELL_SIZE), + floor((_templateSz.height - _PIXEL_PADDING) / _CELL_SIZE)); + + _y = gaussianShapedLabelsShifted2D(outputSigma, templateSzByCells); + + if (_USE_CCS) + dft(_y, _yf); + else + dft(_y, _yf, cv::DFT_COMPLEX_OUTPUT); + + cv::Mat cosWindowX; + cv::Mat cosWindowY; + cosWindowY = hanningWindow(_yf.rows); + cosWindowX = hanningWindow(_yf.cols); + _cosWindow = cosWindowY * cosWindowX.t(); + + cv::Mat numeratorf; + cv::Mat denominatorf; + std::shared_ptr xf(0); + + if (_scaleEstimator == 0 && _USE_VOT_SCALE_ESTIMATION) + { + cv::Mat colScales = numberToColVector(_N_SCALES_VOT); + T scaleHalf = static_cast(ceil(_N_SCALES_VOT / 2.0)); + cv::Mat ss = colScales - scaleHalf; + + _scaleFactors = pow(_SCALE_STEP, ss); + } + + if (getTrainingData(image, numeratorf, denominatorf, xf) == false) + return false; + + cv::Mat alphaf; + + if (_USE_CCS) + divSpectrums(numeratorf, denominatorf, alphaf, 0, false); + else + divideSpectrumsNoCcs(numeratorf, denominatorf, alphaf); + + _modelNumeratorf = numeratorf; + _modelDenominatorf = denominatorf; + _modelAlphaf = alphaf; + _modelXf = xf; + + if (_scaleEstimator) + { + if (_scaleEstimator->reinit(image, _pos, targetSize, + static_cast(_scale * _templateScaleFactor)) == false) + return false; + } + + _isInitialized = true; + return true; + } + + bool getTrainingData(const cv::Mat& image, cv::Mat& numeratorf, + cv::Mat& denominatorf, std::shared_ptr& xf) + { + std::shared_ptr features(0); + + if (getFeatures(image, _pos, _scale, features) == false) + return false; + + if (_USE_CCS) + xf = FFC::dftFeatures(features); + else + xf = FFC::dftFeatures(features, cv::DFT_COMPLEX_OUTPUT); + + cv::Mat kf = (this->*correlate)(xf, xf); + + cv::Mat kfLambda; + + if (_USE_CCS) + kfLambda = addRealToSpectrum(_LAMBDA, kf); + else + kfLambda = kf + _LAMBDA; + + mulSpectrums(_yf, kf, numeratorf, 0); + mulSpectrums(kf, kfLambda, denominatorf, 0); + + return true; + } + + cv::Mat gaussianCorrelation(const std::shared_ptr& xf, const std::shared_ptr& yf) const + { + // TODO: optimization: squaredNormFeatures, mulSpectrumsFeatrues, sumFeatures + T xx, yy; + if (_USE_CCS) + { + xx = FFC::squaredNormFeaturesCcs(xf); + + // don't recalculate norm if xf == yf + yy = xx; + + if (xf != yf) + yy = FFC::squaredNormFeaturesCcs(yf); + } + else + { + xx = FFC::squaredNormFeaturesNoCcs(xf); + + // don't recalculate norm if xf == yf + yy = xx; + + if (xf != yf) + yy = FFC::squaredNormFeaturesNoCcs(yf); + } + + std::shared_ptr xyf = FFC::mulSpectrumsFeatures(xf, yf, true); + std::shared_ptr realXy = FFC::idftFeatures(xyf); + cv::Mat xy = FFC::sumFeatures(realXy); + + T numel = static_cast(xf->channels[0].total() * NUM_FEATURE_CHANNELS); + calcGaussianTerm(xy, numel, xx, yy); + cv::Mat kf; + + if (_USE_CCS) + dft(xy, kf); + else + dft(xy, kf, cv::DFT_COMPLEX_OUTPUT); + + return kf; + } + + void calcGaussianTerm(cv::Mat& xy, T numel, T xx, T yy) const + { + int width = xy.cols; + int height = xy.rows; + + // http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-efficient-way + // TODO: this mat is always continuous; remove non-continuous handling + // TODO: numel division can be done outside the loop + if (xy.isContinuous()) + { + width *= height; + height = 1; + } + + int row = 0, col = 0; + T* xyd = 0; + + const T summands = xx + yy; + const T fraction = -1 / (_KERNEL_SIGMA * _KERNEL_SIGMA); + + for (row = 0; row < height; ++row) + { + xyd = xy.ptr(row); + + for (col = 0; col < width; ++col) + { + xyd[col] = (summands - 2 * xyd[col]) / numel; + + if (xyd[col] < 0) + xyd[col] = 0; + + xyd[col] *= fraction; + xyd[col] = exp(xyd[col]); + } + } + } + + bool getFeatures(const cv::Mat& image, const Point& pos, + const T scale, std::shared_ptr& features) const + { + cv::Mat patch; + Size patchSize = _templateSz * scale; + + if (getSubWindow(image, patch, patchSize, pos) == false) + return false; + + cv::Mat patchResized; + resize(patch, patchResized, _templateSz, 0, 0, _RESIZE_TYPE); + + cv::Mat patchResizedFloat; + patchResized.convertTo(patchResizedFloat, CV_32FC(3)); + + if (_debug != 0) + { + _debug->showPatch(patchResized); + } + + patchResizedFloat *= 0.003921568627451; // patchResizedFloat /= 255; + + features.reset(new FFC()); + piotr::cvFhog(patchResizedFloat, features, _CELL_SIZE); + FFC::mulFeatures(features, _cosWindow); + + return true; + } + + bool update_(const cv::Mat& image, Rect& boundingBox) + { + return updateAtScalePos(image, _pos, _scale, boundingBox); + } + + bool updateAt_(const cv::Mat& image, Rect& boundingBox) + { + bool isValid = false; + T scale = 0; + Point pos(boundingBox.x + boundingBox.width * consts::c0_5, + boundingBox.y + boundingBox.height * consts::c0_5); + + // caller's box may have a different aspect ratio + // compared to the _targetSize; use the larger side + // to calculate scale + if (boundingBox.width > boundingBox.height) + scale = boundingBox.width / _targetSize.width; + else + scale = boundingBox.height / _targetSize.height; + + isValid = updateAtScalePos(image, pos, scale, boundingBox); + return isValid; + } + + bool updateAtScalePos(const cv::Mat& image, const Point& oldPos, const T oldScale, + Rect& boundingBox) + { + ++_frameIdx; + + if (!_isInitialized) + return false; + + T newScale = oldScale; + Point newPos = oldPos; + cv::Point2i maxResponseIdx; + cv::Mat response; + + // in case of error return the last box + boundingBox = _lastBoundingBox; + + if (detectModel(image, response, maxResponseIdx, newPos, newScale) == false) + return false; + + // calc new box + Rect tempBoundingBox; + tempBoundingBox.width = newScale * _targetSize.width; + tempBoundingBox.height = newScale * _targetSize.height; + tempBoundingBox.x = newPos.x - tempBoundingBox.width / 2; + tempBoundingBox.y = newPos.y - tempBoundingBox.height / 2; + + if (_ENABLE_TRACKING_LOSS_DETECTION) + { + if (evalReponse(image, response, maxResponseIdx, + tempBoundingBox) == false) + return false; + } + + if (updateModel(image, newPos, newScale) == false) + return false; + + boundingBox &= Rect(0, 0, static_cast(image.cols), static_cast(image.rows)); + boundingBox = tempBoundingBox; + _lastBoundingBox = tempBoundingBox; + return true; + } + + bool evalReponse(const cv::Mat &image, const cv::Mat& response, + const cv::Point2i& maxResponseIdx, + const Rect& tempBoundingBox) const + { + T peakValue = 0; + T psrClamped = calcPsr(response, maxResponseIdx, _PSR_PEAK_DEL, peakValue); + + if (_debug) + { + _debug->showResponse(response, peakValue); + _debug->setPsr(psrClamped); + } + + if (psrClamped < _PSR_THRESHOLD) + return false; + + // check if we are out of image, too small or too large + Rect imageRect(Point(0, 0), image.size()); + Rect intersection = imageRect & tempBoundingBox; + double bbArea = tempBoundingBox.area(); + double areaThreshold = _MAX_AREA_FACTOR * imageRect.area(); + double intersectDiff = std::abs(bbArea - intersection.area()); + + if (intersectDiff > 0.01 || bbArea < _MIN_AREA + || bbArea > areaThreshold) + return false; + + return true; + } + + bool detectModel(const cv::Mat& image, cv::Mat& response, cv::Point2i& maxResponseIdx, + Point& newPos, T& newScale) const + { + double newMaxResponse; + + if (_scaleEstimator || !_USE_VOT_SCALE_ESTIMATION) + { + if (getResponse(image, newPos, + newScale, response, newMaxResponse, + maxResponseIdx) == false) + return false; + } + else + { + if (detectScales(image, newPos, + response, maxResponseIdx, newScale) == false) + return false; + } + + cv::Point_ subDelta = subPixelDelta(response, maxResponseIdx); + if (subDelta.y >= response.rows / 2) + subDelta.y -= response.rows; + + if (subDelta.x >= response.cols / 2) + subDelta.x -= response.cols; + + T posDeltaX = _CELL_SIZE * subDelta.x; + T posDeltaY = _CELL_SIZE * subDelta.y; + + if (_USE_VOT_SCALE_ESTIMATION) + { + newPos.x += newScale * posDeltaX; + newPos.y += newScale * posDeltaY; + } + else + { + newPos.x += _scale * posDeltaX; + newPos.y += _scale * posDeltaY; + } + + if (_scaleEstimator) + { + //find scale + T tempScale = newScale * _templateScaleFactor; + + if (_scaleEstimator->detectScale(image, newPos, + tempScale) == false) + return false; + + newScale = tempScale / _templateScaleFactor; + } + + // shift max response to the middle to ease PSR extraction + cv::Point2f delta(static_cast(floor(_yf.cols * 0.5) + 1), + static_cast(floor(_yf.rows * 0.5) + 1)); + + shift(response, response, delta, cv::BORDER_WRAP); + + maxResponseIdx.x = mod(static_cast(delta.x) + maxResponseIdx.x, _yf.cols); + maxResponseIdx.y = mod(static_cast(delta.y) + maxResponseIdx.y, _yf.rows); + + return true; + } + + bool updateModel(const cv::Mat& image, const Point& newPos, + const T& newScale) + { + _scale = newScale; + _pos = newPos; + cv::Mat numerator; + cv::Mat denominator; + std::shared_ptr xf(0); + + if (getTrainingData(image, numerator, denominator, xf) == false) + return false; + + _modelNumeratorf = (1 - _INTERP_FACTOR) * _modelNumeratorf + _INTERP_FACTOR * numerator; + _modelDenominatorf = (1 - _INTERP_FACTOR) * _modelDenominatorf + _INTERP_FACTOR * denominator; + FFC::mulValueFeatures(_modelXf, (1 - _INTERP_FACTOR)); + FFC::mulValueFeatures(xf, _INTERP_FACTOR); + FFC::addFeatures(_modelXf, xf); + cv::Mat alphaf; + + if (_USE_CCS) + divSpectrums(_modelNumeratorf, _modelDenominatorf, alphaf); + else + divideSpectrumsNoCcs(_modelNumeratorf, _modelDenominatorf, alphaf); + + _modelAlphaf = alphaf; + + if (_scaleEstimator) + { + if (_scaleEstimator->updateScale(image, newPos, newScale * _templateScaleFactor) == false) + return false; + } + + return true; + } + + bool detectScales(const cv::Mat& image, const Point& pos, + cv::Mat& response, cv::Point2i& maxResponseIdx, T& scale) const + { + double maxResponse = 0; + + cv::Mat* newResponses = new cv::Mat[_N_SCALES_VOT]; + cv::Point2i* newMaxIdxs = new cv::Point2i[_N_SCALES_VOT]; + double* newMaxResponses = new double[_N_SCALES_VOT]{}; + bool* validResults = new bool[_N_SCALES_VOT]{}; + T* newScales = new T[_N_SCALES_VOT]{}; + + for (int i = 0; i < _N_SCALES_VOT; ++i) + newScales[i] = scale * _scaleFactors.at(0, i); + +#pragma omp parallel for + for (int i = 0; i < _N_SCALES_VOT; ++i) + validResults[i] = getResponse(image, pos, + newScales[i], newResponses[i], newMaxResponses[i], newMaxIdxs[i]); + + bool validFound = false; + + for (int i = 0; i < _N_SCALES_VOT; ++i) + validFound |= validResults[i]; + + if (validFound == false) + return false; + + int bestIdx = static_cast(floor(_N_SCALES_VOT / 2.0)); + maxResponse = newMaxResponses[bestIdx]; + + for (int i = 0; i < _N_SCALES_VOT; ++i) + { + if (validResults[i] && + newMaxResponses[i] * _SCALE_WEIGHT > maxResponse) + { + maxResponse = newMaxResponses[i]; + bestIdx = i; + } + } + + response = newResponses[bestIdx]; + maxResponseIdx = newMaxIdxs[bestIdx]; + scale = newScales[bestIdx]; + scale = std::max(_VOT_MIN_SCALE_FACTOR, scale); + scale = std::min(_VOT_MAX_SCALE_FACTOR, scale); + + delete[] newResponses; + delete[] newMaxIdxs; + delete[] newMaxResponses; + delete[] validResults; + delete[] newScales; + + return true; + } + + bool getResponse(const cv::Mat& image, const Point& pos, + T scale, cv::Mat &newResponse, double& newMaxResponse, + cv::Point2i& newMaxIdx) const + { + if (detect(image, pos, scale, newResponse) == false) + return false; + + minMaxLoc(newResponse, 0, &newMaxResponse, 0, &newMaxIdx); + + return true; + } + + bool detect(const cv::Mat& image, const Point& pos, + T scale, cv::Mat& response) const + { + std::shared_ptr features(0); + + if (getFeatures(image, pos, scale, features) == false) + return false; + + std::shared_ptr zf; + if (_USE_CCS) + zf = FFC::dftFeatures(features); + else + zf = FFC::dftFeatures(features, cv::DFT_COMPLEX_OUTPUT); + + cv::Mat kzf = (this->*correlate)(zf, _modelXf); + cv::Mat responsef; + mulSpectrums(_modelAlphaf, kzf, responsef, 0, false); + idft(responsef, response, cv::DFT_REAL_OUTPUT | cv::DFT_SCALE); + return true; + } + + private: + KcfTracker& operator=(const KcfTracker&) + {} + + private: + typedef cv::Mat(KcfTracker::*correlatePtr)(const std::shared_ptr&, + const std::shared_ptr&) const; + correlatePtr correlate = 0; + + typedef void(*cvFhogPtr) + (const cv::Mat& img, std::shared_ptr& cvFeatures, int binSize, int fhogChannelsToCopy); + cvFhogPtr cvFhog = 0; + + cv::Mat _cosWindow; + cv::Mat _y; + std::shared_ptr _modelXf = 0; + cv::Mat _modelNumeratorf; + cv::Mat _modelDenominatorf; + cv::Mat _modelAlphaf; + cv::Mat _yf; + cv::Mat _scaleFactors; + Rect _lastBoundingBox; + Point _pos; + Size _targetSize; + Size _templateSz; + T _scale; + T _templateScaleFactor; + int _frameIdx = 1; + bool _isInitialized; + ScaleEstimator* _scaleEstimator; + + const double _MIN_AREA; + const double _MAX_AREA_FACTOR; + const T _PADDING; + const T _LAMBDA; + const T _OUTPUT_SIGMA_FACTOR; + const T _SCALE_STEP; + const T _SCALE_WEIGHT; + const T _INTERP_FACTOR; + const T _KERNEL_SIGMA; + const T _PSR_THRESHOLD; + const int _TEMPLATE_SIZE; + const int _PSR_PEAK_DEL; + const int _CELL_SIZE; + const int _N_SCALES_VOT; + const int _PIXEL_PADDING; + const int _RESIZE_TYPE; + const std::string _ID; + const bool _USE_VOT_SCALE_ESTIMATION; + const bool _ENABLE_TRACKING_LOSS_DETECTION; + const bool _USE_CCS; + // it should be possible to find more reasonable values for min/max scale; application dependent + T _VOT_MIN_SCALE_FACTOR = static_cast(0.01); + T _VOT_MAX_SCALE_FACTOR = static_cast(40); + + KcfDebug* _debug; + }; +} + +#endif /* KCF_TRACKER_H_ */ diff --git a/src/3rdparty/cf_tracking/src/main/image_acquisition.cpp b/src/3rdparty/cf_tracking/src/main/image_acquisition.cpp new file mode 100644 index 0000000..c0da019 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/main/image_acquisition.cpp @@ -0,0 +1,130 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 "image_acquisition.hpp" + +ImageAcquisition::ImageAcquisition() +{ +} + +ImageAcquisition& ImageAcquisition::operator>>(CV_OUT cv::Mat& image) +{ + if (_paras.isMock) + _mockCap >> image; + else + _cvCap >> image; + + return *this; +} + +void ImageAcquisition::release() +{ + if (!_paras.isMock) + _cvCap.release(); +} + +bool ImageAcquisition::isOpened() +{ + if (_paras.isMock) + return _mockCap.isOpened(); + else + return _cvCap.isOpened(); +} + +void ImageAcquisition::set(int key, int value) +{ + if (!_paras.isMock) + _cvCap.set(key, value); +} + +void ImageAcquisition::open(ImgAcqParas paras) +{ + _paras = paras; + + if (_paras.isMock) + { + _mockCap.open(); + } + else + { + if (_paras.sequencePath.empty()) + _cvCap.open(_paras.device); + else + { + std::string sequenceExpansion = + _paras.sequencePath + _paras.expansionStr; + + _cvCap.open(sequenceExpansion); + } + } +} + +ImageAcquisition::~ImageAcquisition() +{ +} + +double ImageAcquisition::get(int key) +{ + if (!_paras.isMock) + return _cvCap.get(key); + + return 0.0; +} + +void VideoCaptureMock::release() +{ +} + +bool VideoCaptureMock::isOpened() +{ + return isOpen; +} + +VideoCaptureMock& VideoCaptureMock::operator>>(CV_OUT cv::Mat& image) +{ + image = _staticImage; + return *this; +} + +void VideoCaptureMock::open() +{ + isOpen = true; +} + +VideoCaptureMock::~VideoCaptureMock() +{ +} + +VideoCaptureMock::VideoCaptureMock() : isOpen(false) +{ + _staticImage = cv::Mat(360, 640, CV_8UC3); + cv::randu(_staticImage, cv::Scalar::all(0), cv::Scalar::all(255)); +} diff --git a/src/3rdparty/cf_tracking/src/main/image_acquisition.hpp b/src/3rdparty/cf_tracking/src/main/image_acquisition.hpp new file mode 100644 index 0000000..cd0bef7 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/main/image_acquisition.hpp @@ -0,0 +1,90 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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. +*/ + +#ifndef IMAGE_ACQUISITION_HPP_ +#define IMAGE_ACQUISITION_HPP_ + +#include "opencv2/highgui/highgui.hpp" + +struct ImgAcqParas +{ + bool isMock = false; + int device = -1; + std::string sequencePath = ""; + std::string expansionStr = ""; +}; + +class VideoCaptureMock +{ +public: + VideoCaptureMock(); + + virtual ~VideoCaptureMock(); + + void open(); + + VideoCaptureMock& operator >> (CV_OUT cv::Mat& image); + + bool isOpened(); + + void release(); + +private: + bool isOpen; + cv::Mat _staticImage; +}; + +class ImageAcquisition +{ +public: + ImageAcquisition(); + + virtual ~ImageAcquisition(); + + void open(ImgAcqParas paras); + + void set(int key, int value); + + double get(int key); + + bool isOpened(); + + void release(); + + ImageAcquisition& operator >> (CV_OUT cv::Mat& image); + +private: + cv::VideoCapture _cvCap; + ImgAcqParas _paras; + VideoCaptureMock _mockCap; +}; + +#endif diff --git a/src/3rdparty/cf_tracking/src/main/main_dsst.cpp b/src/3rdparty/cf_tracking/src/main/main_dsst.cpp new file mode 100644 index 0000000..a0df3e1 --- /dev/null +++ b/src/3rdparty/cf_tracking/src/main/main_dsst.cpp @@ -0,0 +1,139 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 +#include "dsst_tracker.hpp" +#include "tracker_run.hpp" + +class DsstTrackerRun : public TrackerRun +{ +public: + DsstTrackerRun() : TrackerRun("DSSTcpp") + {} + + virtual ~DsstTrackerRun() + {} + + virtual cf_tracking::CfTracker* parseTrackerParas(TCLAP::CmdLine& cmd, int argc, const char** argv) + { + cf_tracking::DsstParameters paras; + TCLAP::SwitchArg debugOutput("v", "debug", "Output Debug info!", cmd, false); + TCLAP::SwitchArg originalVersion("", "original_version", "Use the original parameters found in the DSST paper. Performance is close, " + "but differences do still exist!", cmd, false); + TCLAP::ValueArg templateSize("", "para_template_size", "template size", false, + paras.templateSize, "integer", cmd); + TCLAP::ValueArg padding("", "para_padding", "padding around the target", false, + paras.padding, "double", cmd); + TCLAP::ValueArg outputSigmaFactor("", "para_output_sigma_factor", "spatial bandwitdh of the target", + false, paras.outputSigmaFactor, "double", cmd); + TCLAP::ValueArg cellSize("", "para_cell_size", "cell size of fhog", false, paras.cellSize, "integer", cmd); + TCLAP::ValueArg lambda("", "para_lambda", "regularization factor", false, paras.lambda, "double", cmd); + TCLAP::ValueArg interpFactor("", "para_interpFactor", "interpolation factor for learning", + false, paras.learningRate, "double", cmd); + TCLAP::ValueArg scaleSigmaFactor("", "para_scale_sigma_factor", "spatial bandwitdh of the target(scale)", + false, paras.scaleSigmaFactor, "double", cmd); + TCLAP::ValueArg scaleStep("", "para_scale_step", "scale_step", false, paras.scaleStep, "double", cmd); + TCLAP::ValueArg scaleCellSize("", "para_scale_cell_size", "cell size of fhog (scale filter)", false, paras.scaleCellSize, "integer", cmd); + TCLAP::ValueArg numberOfScales("", "para_scale_number", "number of scale steps", false, paras.numberOfScales, "integer", cmd); + TCLAP::SwitchArg enableTrackingLossDetection("", "para_enable_tracking_loss", "Enable the tracking loss detection!", cmd, paras.enableTrackingLossDetection); + TCLAP::ValueArg psrThreshold("", "para_psr_threshold", + "if psr is lower than psr threshold, tracking will stop", + false, paras.psrThreshold, "double", cmd); + TCLAP::ValueArg psrPeakDel("", "para_psr_peak_del", "amount of pixels that are deleted" + "for psr calculation around the peak (1 means that a window of 3 by 3 is deleted; 0 means" + "that max response is deleted; 2 * peak_del + 1 pixels are deleted)", + false, paras.psrPeakDel, "integer", cmd); + + cmd.parse(argc, argv); + + paras.padding = padding.getValue(); + paras.outputSigmaFactor = outputSigmaFactor.getValue(); + paras.lambda = lambda.getValue(); + paras.learningRate = interpFactor.getValue(); + paras.cellSize = cellSize.getValue(); + + paras.scaleSigmaFactor = scaleSigmaFactor.getValue(); + paras.scaleStep = scaleStep.getValue(); + paras.scaleCellSize = scaleCellSize.getValue(); + paras.numberOfScales = numberOfScales.getValue(); + paras.psrThreshold = psrThreshold.getValue(); + paras.psrPeakDel = psrPeakDel.getValue(); + paras.templateSize = templateSize.getValue(); + paras.enableTrackingLossDetection = enableTrackingLossDetection.getValue(); + + // use original paper parameters from + // Danelljan, Martin, et al., "Accurate scale estimation for robust visual tracking," in Proc. BMVC, 2014 + if (originalVersion.getValue()) + { + paras.padding = static_cast(1); + paras.outputSigmaFactor = static_cast(1.0 / 16.0); + paras.lambda = static_cast(0.01); + paras.learningRate = static_cast(0.025); + paras.templateSize = 100; + paras.cellSize = 1; + + paras.enableTrackingLossDetection = false; + paras.psrThreshold = 0; + paras.psrPeakDel = 1; + + paras.enableScaleEstimator = true; + paras.scaleSigmaFactor = static_cast(0.25); + paras.scaleStep = static_cast(1.02); + paras.scaleCellSize = 4; + paras.numberOfScales = 33; + + paras.originalVersion = true; + paras.resizeType = cv::INTER_AREA; + } + + if (debugOutput.getValue()) + { + setTrackerDebug(&_debug); + return new cf_tracking::DsstTracker(paras, &_debug); + } + + return new cf_tracking::DsstTracker(paras); + } + +private: + cf_tracking::DsstDebug _debug; +}; + +int main(int argc, const char** argv) +{ + DsstTrackerRun mainObj; + + if (!mainObj.start(argc, argv)) + return -1; + + return 0; +} diff --git a/src/3rdparty/cf_tracking/src/main/main_kcf.cpp b/src/3rdparty/cf_tracking/src/main/main_kcf.cpp new file mode 100644 index 0000000..988d46d --- /dev/null +++ b/src/3rdparty/cf_tracking/src/main/main_kcf.cpp @@ -0,0 +1,149 @@ +/* +// License Agreement (3-clause BSD License) +// Copyright (c) 2015, Klaus Haag, all rights reserved. +// Third party copyrights and patents are property of their respective owners. +// +// 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 names of the copyright holders nor the names of the 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 copyright holders 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 +#include "kcf_tracker.hpp" +#include "tracker_run.hpp" +#include "kcf_debug.hpp" + +class KcfTrackerRun : public TrackerRun +{ +public: + KcfTrackerRun() : TrackerRun("KCFcpp") + {} + + virtual ~KcfTrackerRun() + { + } + + virtual cf_tracking::CfTracker* parseTrackerParas(TCLAP::CmdLine& cmd, int argc, const char** argv) + { + cf_tracking::KcfParameters paras; + TCLAP::SwitchArg debugOutput("v", "debug", "Output Debug info!", cmd, false); + TCLAP::SwitchArg originalVersion("", "original_version", "Parameters and performance as close to the KCF VOT version as possible.", cmd, false); + TCLAP::SwitchArg originalParametersWithScaleFilter("", "original_parameters_scale_filter", "KCF VOT version parameters with DSST scale filter.", cmd, false); + TCLAP::ValueArg templateSize("", "para_template_size", "template size", false, paras.templateSize, "integer", cmd); + TCLAP::ValueArg cellSize("", "para_cell_size", "cell size of fhog", false, paras.cellSize, "integer", cmd); + TCLAP::ValueArg padding("", "para_padding", "padding around the target", false, paras.padding, "double", cmd); + TCLAP::ValueArg lambda("", "para_lambda", "regularization factor", false, paras.lambda, "double", cmd); + TCLAP::ValueArg outputSigmaFactor("", "para_output_sigma_factor", "spatial bandwidth of the target", false, paras.outputSigmaFactor, "double", cmd); + TCLAP::ValueArg scaleStep("", "para_vot_scale_step", "scale_step", false, paras.votScaleStep, "double", cmd); + TCLAP::ValueArg scaleWeight("", "para_vot_scale_weight", "scale_weight", false, paras.votScaleWeight, "double", cmd); + TCLAP::ValueArg interpFactor("", "para_interpFactor", "interpolation factor for learning", false, paras.interpFactor, "double", cmd); + TCLAP::ValueArg kernelSigma("", "para_kernel_sigma", "sigma for Gaussian kernel", false, paras.kernelSigma, "double", cmd); + TCLAP::ValueArg psrThreshold("", "para_psr_threshold", "if psr is lower than " + "psr threshold, target is assumed to be lost", false, paras.psrThreshold, "double", cmd); + TCLAP::ValueArg psrPeakDel("", "para_psr_peak_del", "amount of pixels that are " + "deleted for psr calculation around the peak (1 means that a window of 3 by 3 is " + "deleted; 0 means that max response is deleted; 2 * peak_del + 1 pixels are deleted)", false, paras.psrPeakDel, "integer", cmd); + TCLAP::SwitchArg useDsstScale("", "para_use_dsst_scale", "Uses the DSST scale filter for scale estimation. " + "Disable for more speed!", cmd, paras.useDsstScaleEstimation); + TCLAP::ValueArg scaleSigmaFactor("", "para_dsst_sigma_factor", "DSST: spatial bandwidth of the target", false, paras.scaleSigmaFactor, "double", cmd); + TCLAP::ValueArg scaleEstimatorStep("", "para_dsst_scale_step", "DSST: scale step", false, paras.scaleEstimatorStep, "double", cmd); + TCLAP::ValueArg scaleLambda("", "para_dsst_lambda", "DSST: regularization for scale estimation", false, paras.scaleLambda, "double", cmd); + TCLAP::ValueArg scaleCellSize("", "para_dsst_cell_size", "DSST: hog cell size for scale estimation", false, paras.scaleCellSize, "integer", cmd); + TCLAP::ValueArg numberOfScales("", "para_dsst_scales", "DSST: number of scales", false, paras.numberOfScales, "integer", cmd); + TCLAP::SwitchArg enableTrackingLossDetection("", "para_enable_tracking_loss", "Enables the tracking loss detection!", cmd, paras.enableTrackingLossDetection); + + cmd.parse(argc, argv); + + paras.padding = padding.getValue(); + paras.lambda = lambda.getValue(); + paras.outputSigmaFactor = outputSigmaFactor.getValue(); + paras.votScaleStep = scaleStep.getValue(); + paras.votScaleWeight = scaleWeight.getValue(); + paras.templateSize = templateSize.getValue(); + paras.interpFactor = interpFactor.getValue(); + paras.kernelSigma = kernelSigma.getValue(); + paras.cellSize = cellSize.getValue(); + paras.psrThreshold = psrThreshold.getValue(); + paras.psrPeakDel = psrPeakDel.getValue(); + paras.enableTrackingLossDetection = enableTrackingLossDetection.getValue(); + + paras.useDsstScaleEstimation = useDsstScale.getValue(); + paras.scaleSigmaFactor = scaleSigmaFactor.getValue(); + paras.scaleEstimatorStep = scaleEstimatorStep.getValue(); + paras.scaleLambda = scaleLambda.getValue(); + paras.scaleCellSize = scaleCellSize.getValue(); + paras.numberOfScales = numberOfScales.getValue(); + + if (originalVersion.getValue() || originalParametersWithScaleFilter.getValue()) + { + paras.padding = 1.5; + paras.lambda = 0.0001; + paras.outputSigmaFactor = 0.1; + paras.votScaleStep = 1.05; + paras.votScaleWeight = 0.95; + paras.templateSize = 100; + paras.interpFactor = 0.012; + paras.kernelSigma = 0.6; + paras.cellSize = 4; + paras.pixelPadding = 0; + + paras.enableTrackingLossDetection = false; + + if (originalParametersWithScaleFilter.getValue()) + { + paras.useVotScaleEstimation = false; + paras.useDsstScaleEstimation = true; + } + else + { + paras.useVotScaleEstimation = true; + paras.useDsstScaleEstimation = false; + } + + paras.useFhogTranspose = false; + } + + if (debugOutput.getValue()) + { + setTrackerDebug(&_debug); + return new cf_tracking::KcfTracker(paras, &_debug); + } + + return new cf_tracking::KcfTracker(paras); + } + +private: + cf_tracking::KcfDebug _debug; +}; + +int main(int argc, const char** argv) +{ + KcfTrackerRun mainObj; + + if (!mainObj.start(argc, argv)) + return -1; + + return 0; +} diff --git a/src/3rdparty/libconfig/CMakeLists.txt b/src/3rdparty/libconfig/CMakeLists.txt new file mode 100644 index 0000000..59dec98 --- /dev/null +++ b/src/3rdparty/libconfig/CMakeLists.txt @@ -0,0 +1,21 @@ +#This are the defines for building a static libconfig for windows +if(WIN32) + add_definitions(-DLIBCONFIGXX_STATIC -DLIBCONFIG_STATIC -DYY_NO_UNISTD_H -DYY_USE_CONST -D_CRT_SECURE_NO_DEPRECATE -D_STDLIB_H) +endif(WIN32) + +add_library(config++ + grammar.c + libconfig.c + libconfigcpp.cc + scanctx.c + scanner.c + strbuf.c + grammar.h + libconfig.h + libconfig.hh + parsectx.h + scanctx.h + scanner.h + strbuf.h + wincompat.h) + diff --git a/src/3rdparty/libconfig/grammar.c b/src/3rdparty/libconfig/grammar.c new file mode 100644 index 0000000..e95a569 --- /dev/null +++ b/src/3rdparty/libconfig/grammar.c @@ -0,0 +1,2001 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse libconfig_yyparse +#define yylex libconfig_yylex +#define yyerror libconfig_yyerror +#define yylval libconfig_yylval +#define yychar libconfig_yychar +#define yydebug libconfig_yydebug +#define yynerrs libconfig_yynerrs + + +/* Copy the first part of user declarations. */ + +/* Line 189 of yacc.c */ +#line 32 "grammar.y" + +#include +#include +#include "libconfig.h" +#ifdef WIN32 +#include "wincompat.h" + +/* prevent warnings about redefined malloc/free in generated code: */ +#ifndef _STDLIB_H +#define _STDLIB_H +#endif + +#include +#endif +#include "parsectx.h" +#include "scanctx.h" + +/* these delcarations are provided to suppress compiler warnings */ +extern int libconfig_yylex(); +extern int libconfig_yyget_lineno(); + +static const char *err_array_elem_type = "mismatched element type in array"; +static const char *err_duplicate_setting = "duplicate setting name"; + +#define _delete(P) free((void *)(P)) + +#define IN_ARRAY() \ + (ctx->parent && (ctx->parent->type == CONFIG_TYPE_ARRAY)) + +#define IN_LIST() \ + (ctx->parent && (ctx->parent->type == CONFIG_TYPE_LIST)) + +static void capture_parse_pos(void *scanner, struct scan_context *scan_ctx, + config_setting_t *setting) +{ + setting->line = (unsigned int)libconfig_yyget_lineno(scanner); + setting->file = scanctx_current_filename(scan_ctx); +} + +#define CAPTURE_PARSE_POS(S) \ + capture_parse_pos(scanner, scan_ctx, (S)) + +void libconfig_yyerror(void *scanner, struct parse_context *ctx, + struct scan_context *scan_ctx, char const *s) +{ + if(ctx->config->error_text) return; + ctx->config->error_line = libconfig_yyget_lineno(scanner); + ctx->config->error_text = s; +} + + + +/* Line 189 of yacc.c */ +#line 134 "grammar.c" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_BOOLEAN = 258, + TOK_INTEGER = 259, + TOK_HEX = 260, + TOK_INTEGER64 = 261, + TOK_HEX64 = 262, + TOK_FLOAT = 263, + TOK_STRING = 264, + TOK_NAME = 265, + TOK_EQUALS = 266, + TOK_NEWLINE = 267, + TOK_ARRAY_START = 268, + TOK_ARRAY_END = 269, + TOK_LIST_START = 270, + TOK_LIST_END = 271, + TOK_COMMA = 272, + TOK_GROUP_START = 273, + TOK_GROUP_END = 274, + TOK_SEMICOLON = 275, + TOK_GARBAGE = 276, + TOK_ERROR = 277 + }; +#endif +/* Tokens. */ +#define TOK_BOOLEAN 258 +#define TOK_INTEGER 259 +#define TOK_HEX 260 +#define TOK_INTEGER64 261 +#define TOK_HEX64 262 +#define TOK_FLOAT 263 +#define TOK_STRING 264 +#define TOK_NAME 265 +#define TOK_EQUALS 266 +#define TOK_NEWLINE 267 +#define TOK_ARRAY_START 268 +#define TOK_ARRAY_END 269 +#define TOK_LIST_START 270 +#define TOK_LIST_END 271 +#define TOK_COMMA 272 +#define TOK_GROUP_START 273 +#define TOK_GROUP_END 274 +#define TOK_SEMICOLON 275 +#define TOK_GARBAGE 276 +#define TOK_ERROR 277 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 214 of yacc.c */ +#line 85 "grammar.y" + + int ival; + long long llval; + double fval; + char *sval; + + + +/* Line 214 of yacc.c */ +#line 223 "grammar.c" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 264 of yacc.c */ +#line 235 "grammar.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 6 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 35 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 23 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 20 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 39 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 47 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 277 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 4, 6, 8, 11, 12, 14, 15, + 17, 19, 20, 26, 27, 32, 33, 38, 40, 42, + 44, 46, 48, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 71, 72, 74, 76, 80, 81, 83, 84 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 24, 0, -1, -1, 25, -1, 28, -1, 25, 28, + -1, -1, 25, -1, -1, 20, -1, 17, -1, -1, + 10, 29, 11, 34, 27, -1, -1, 13, 31, 40, + 14, -1, -1, 15, 33, 38, 16, -1, 36, -1, + 30, -1, 32, -1, 41, -1, 9, -1, 35, 9, + -1, 3, -1, 4, -1, 6, -1, 5, -1, 7, + -1, 8, -1, 35, -1, 34, -1, 37, 17, 34, + -1, -1, 37, -1, 36, -1, 39, 17, 36, -1, + -1, 39, -1, -1, 18, 42, 26, 19, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 100, 100, 102, 106, 107, 110, 112, 115, 117, + 118, 123, 122, 142, 141, 165, 164, 187, 188, 189, + 190, 194, 195, 199, 219, 241, 263, 285, 307, 325, + 353, 354, 357, 359, 363, 364, 367, 369, 374, 373 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TOK_BOOLEAN", "TOK_INTEGER", "TOK_HEX", + "TOK_INTEGER64", "TOK_HEX64", "TOK_FLOAT", "TOK_STRING", "TOK_NAME", + "TOK_EQUALS", "TOK_NEWLINE", "TOK_ARRAY_START", "TOK_ARRAY_END", + "TOK_LIST_START", "TOK_LIST_END", "TOK_COMMA", "TOK_GROUP_START", + "TOK_GROUP_END", "TOK_SEMICOLON", "TOK_GARBAGE", "TOK_ERROR", "$accept", + "configuration", "setting_list", "setting_list_optional", + "setting_terminator", "setting", "$@1", "array", "$@2", "list", "$@3", + "value", "string", "simple_value", "value_list", "value_list_optional", + "simple_value_list", "simple_value_list_optional", "group", "$@4", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 27, 29, 28, 31, 30, 33, 32, 34, 34, 34, + 34, 35, 35, 36, 36, 36, 36, 36, 36, 36, + 37, 37, 38, 38, 39, 39, 40, 40, 42, 41 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 1, 1, 2, 0, 1, 0, 1, + 1, 0, 5, 0, 4, 0, 4, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 0, 1, 1, 3, 0, 1, 0, 4 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 11, 0, 3, 4, 0, 1, 5, 0, 23, + 24, 26, 25, 27, 28, 21, 13, 15, 38, 18, + 19, 8, 29, 17, 20, 36, 32, 6, 10, 9, + 12, 22, 34, 37, 0, 30, 33, 0, 7, 0, + 0, 14, 0, 16, 39, 35, 31 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 2, 3, 39, 30, 4, 5, 19, 25, 20, + 26, 21, 22, 23, 36, 37, 33, 34, 24, 27 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -26 +static const yytype_int8 yypact[] = +{ + -8, -26, 12, -8, -26, 5, -26, -26, 0, -26, + -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -6, 10, -26, -26, 23, 0, -8, -26, -26, + -26, -26, -26, 3, 7, -26, 6, 8, -8, 14, + 23, -26, 0, -26, -26, -26, -26 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -26, -26, -5, -26, -26, -3, -26, -26, -26, -26, + -26, -25, -26, -15, -26, -26, -26, -26, -26, -26 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 7, 35, 1, 9, 10, 11, 12, 13, 14, 15, + 32, 28, 6, 16, 29, 17, 8, 46, 18, 31, + 40, 41, 38, 42, 43, 45, 9, 10, 11, 12, + 13, 14, 15, 44, 0, 7 +}; + +static const yytype_int8 yycheck[] = +{ + 3, 26, 10, 3, 4, 5, 6, 7, 8, 9, + 25, 17, 0, 13, 20, 15, 11, 42, 18, 9, + 17, 14, 27, 17, 16, 40, 3, 4, 5, 6, + 7, 8, 9, 19, -1, 38 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 10, 24, 25, 28, 29, 0, 28, 11, 3, + 4, 5, 6, 7, 8, 9, 13, 15, 18, 30, + 32, 34, 35, 36, 41, 31, 33, 42, 17, 20, + 27, 9, 36, 39, 40, 34, 37, 38, 25, 26, + 17, 14, 17, 16, 19, 36, 34 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (scanner, ctx, scan_ctx, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, scanner) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, scanner, ctx, scan_ctx); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + if (!yyvaluep) + return; + YYUSE (scanner); + YYUSE (ctx); + YYUSE (scan_ctx); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yy_reduce_print (yyvsp, yyrule, scanner, ctx, scan_ctx) + YYSTYPE *yyvsp; + int yyrule; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , scanner, ctx, scan_ctx); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule, scanner, ctx, scan_ctx); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, scanner, ctx, scan_ctx) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + YYUSE (yyvaluep); + YYUSE (scanner); + YYUSE (ctx); + YYUSE (scan_ctx); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +int +yyparse (scanner, ctx, scan_ctx) + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +#endif +{ +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 11: + +/* Line 1455 of yacc.c */ +#line 123 "grammar.y" + { + ctx->setting = config_setting_add(ctx->parent, (yyvsp[(1) - (1)].sval), CONFIG_TYPE_NONE); + + if(ctx->setting == NULL) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_duplicate_setting); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(ctx->setting); + } + } + break; + + case 13: + +/* Line 1455 of yacc.c */ +#line 142 "grammar.y" + { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_ARRAY); + CAPTURE_PARSE_POS(ctx->parent); + } + else + { + ctx->setting->type = CONFIG_TYPE_ARRAY; + ctx->parent = ctx->setting; + ctx->setting = NULL; + } + } + break; + + case 14: + +/* Line 1455 of yacc.c */ +#line 157 "grammar.y" + { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } + break; + + case 15: + +/* Line 1455 of yacc.c */ +#line 165 "grammar.y" + { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_LIST); + CAPTURE_PARSE_POS(ctx->parent); + } + else + { + ctx->setting->type = CONFIG_TYPE_LIST; + ctx->parent = ctx->setting; + ctx->setting = NULL; + } + } + break; + + case 16: + +/* Line 1455 of yacc.c */ +#line 180 "grammar.y" + { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } + break; + + case 21: + +/* Line 1455 of yacc.c */ +#line 194 "grammar.y" + { parsectx_append_string(ctx, (yyvsp[(1) - (1)].sval)); free((yyvsp[(1) - (1)].sval)); } + break; + + case 22: + +/* Line 1455 of yacc.c */ +#line 195 "grammar.y" + { parsectx_append_string(ctx, (yyvsp[(2) - (2)].sval)); free((yyvsp[(2) - (2)].sval)); } + break; + + case 23: + +/* Line 1455 of yacc.c */ +#line 200 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_bool_elem(ctx->parent, -1, + (int)(yyvsp[(1) - (1)].ival)); + + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(e); + } + } + else + config_setting_set_bool(ctx->setting, (int)(yyvsp[(1) - (1)].ival)); + } + break; + + case 24: + +/* Line 1455 of yacc.c */ +#line 220 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[(1) - (1)].ival)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_DEFAULT); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int(ctx->setting, (yyvsp[(1) - (1)].ival)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT); + } + } + break; + + case 25: + +/* Line 1455 of yacc.c */ +#line 242 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[(1) - (1)].llval)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_DEFAULT); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int64(ctx->setting, (yyvsp[(1) - (1)].llval)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT); + } + } + break; + + case 26: + +/* Line 1455 of yacc.c */ +#line 264 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[(1) - (1)].ival)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_HEX); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int(ctx->setting, (yyvsp[(1) - (1)].ival)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX); + } + } + break; + + case 27: + +/* Line 1455 of yacc.c */ +#line 286 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[(1) - (1)].llval)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_HEX); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int64(ctx->setting, (yyvsp[(1) - (1)].llval)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX); + } + } + break; + + case 28: + +/* Line 1455 of yacc.c */ +#line 308 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_float_elem(ctx->parent, -1, (yyvsp[(1) - (1)].fval)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(e); + } + } + else + config_setting_set_float(ctx->setting, (yyvsp[(1) - (1)].fval)); + } + break; + + case 29: + +/* Line 1455 of yacc.c */ +#line 326 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + const char *s = parsectx_take_string(ctx); + config_setting_t *e = config_setting_set_string_elem(ctx->parent, -1, s); + _delete(s); + + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(e); + } + } + else + { + const char *s = parsectx_take_string(ctx); + config_setting_set_string(ctx->setting, s); + _delete(s); + } + } + break; + + case 38: + +/* Line 1455 of yacc.c */ +#line 374 "grammar.y" + { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_GROUP); + CAPTURE_PARSE_POS(ctx->parent); + } + else + { + ctx->setting->type = CONFIG_TYPE_GROUP; + ctx->parent = ctx->setting; + ctx->setting = NULL; + } + } + break; + + case 39: + +/* Line 1455 of yacc.c */ +#line 389 "grammar.y" + { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } + break; + + + +/* Line 1455 of yacc.c */ +#line 1788 "grammar.c" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (scanner, ctx, scan_ctx, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (scanner, ctx, scan_ctx, yymsg); + } + else + { + yyerror (scanner, ctx, scan_ctx, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, scanner, ctx, scan_ctx); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, scanner, ctx, scan_ctx); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (scanner, ctx, scan_ctx, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, scanner, ctx, scan_ctx); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, scanner, ctx, scan_ctx); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + +/* Line 1675 of yacc.c */ +#line 395 "grammar.y" + + diff --git a/src/3rdparty/libconfig/grammar.h b/src/3rdparty/libconfig/grammar.h new file mode 100644 index 0000000..2ce199d --- /dev/null +++ b/src/3rdparty/libconfig/grammar.h @@ -0,0 +1,113 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_BOOLEAN = 258, + TOK_INTEGER = 259, + TOK_HEX = 260, + TOK_INTEGER64 = 261, + TOK_HEX64 = 262, + TOK_FLOAT = 263, + TOK_STRING = 264, + TOK_NAME = 265, + TOK_EQUALS = 266, + TOK_NEWLINE = 267, + TOK_ARRAY_START = 268, + TOK_ARRAY_END = 269, + TOK_LIST_START = 270, + TOK_LIST_END = 271, + TOK_COMMA = 272, + TOK_GROUP_START = 273, + TOK_GROUP_END = 274, + TOK_SEMICOLON = 275, + TOK_GARBAGE = 276, + TOK_ERROR = 277 + }; +#endif +/* Tokens. */ +#define TOK_BOOLEAN 258 +#define TOK_INTEGER 259 +#define TOK_HEX 260 +#define TOK_INTEGER64 261 +#define TOK_HEX64 262 +#define TOK_FLOAT 263 +#define TOK_STRING 264 +#define TOK_NAME 265 +#define TOK_EQUALS 266 +#define TOK_NEWLINE 267 +#define TOK_ARRAY_START 268 +#define TOK_ARRAY_END 269 +#define TOK_LIST_START 270 +#define TOK_LIST_END 271 +#define TOK_COMMA 272 +#define TOK_GROUP_START 273 +#define TOK_GROUP_END 274 +#define TOK_SEMICOLON 275 +#define TOK_GARBAGE 276 +#define TOK_ERROR 277 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 1676 of yacc.c */ +#line 85 "grammar.y" + + int ival; + long long llval; + double fval; + char *sval; + + + +/* Line 1676 of yacc.c */ +#line 105 "grammar.h" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + + + diff --git a/src/3rdparty/libconfig/libconfig.c b/src/3rdparty/libconfig/libconfig.c new file mode 100644 index 0000000..f301c8c --- /dev/null +++ b/src/3rdparty/libconfig/libconfig.c @@ -0,0 +1,1616 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifdef HAVE_CONFIG_H +#include "ac_config.h" +#endif + +#include "libconfig.h" +#include "grammar.h" +#include "scanner.h" +#include "scanctx.h" +#include "parsectx.h" +#include "wincompat.h" + +#include + +#ifdef HAVE_XLOCALE_H +#include +#endif + +#include +#include +#include + +#define PATH_TOKENS ":./" +#define CHUNK_SIZE 16 +#define FLOAT_PRECISION 10 + +#define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */ +#define _delete(P) free((void *)(P)) + +/* ------------------------------------------------------------------------- */ + +#ifndef LIBCONFIG_STATIC +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return(TRUE); +} + +#endif /* WIN32 */ +#endif /* LIBCONFIG_STATIC */ + +/* ------------------------------------------------------------------------- */ + +static const char *__io_error = "file I/O error"; + +static void __config_list_destroy(config_list_t *list); +static void __config_write_setting(const config_setting_t *setting, + FILE *stream, int depth, + unsigned short tab_width); + +extern int libconfig_yyparse(void *scanner, struct parse_context *ctx, + struct scan_context *scan_ctx); +extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx, + yyscan_t *scanner); + +/* ------------------------------------------------------------------------- */ + +static void __config_locale_override(void) +{ +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ + && ! defined(__MINGW32__) + + _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); + setlocale(LC_NUMERIC, "C"); + +#elif defined(__APPLE__) + + locale_t loc = newlocale(LC_NUMERIC_MASK, "C", NULL); + uselocale(loc); + +#elif ((defined HAVE_NEWLOCALE) && (defined HAVE_USELOCALE)) + + locale_t loc = newlocale(LC_NUMERIC, "C", NULL); + uselocale(loc); + +#else + +#warning "No way to modify calling thread's locale!" + +#endif +} + +/* ------------------------------------------------------------------------- */ + +static void __config_locale_restore(void) +{ +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ + && ! defined(__MINGW32__) + + _configthreadlocale(_DISABLE_PER_THREAD_LOCALE); + +#elif ((defined HAVE_USELOCALE) && (defined HAVE_FREELOCALE)) + + locale_t loc = uselocale(LC_GLOBAL_LOCALE); + freelocale(loc); + +#else + +#warning "No way to modify calling thread's locale!" + +#endif +} + +/* ------------------------------------------------------------------------- */ + +static int __config_name_compare(const char *a, const char *b) +{ + const char *p, *q; + + for(p = a, q = b; ; p++, q++) + { + int pd = ((! *p) || strchr(PATH_TOKENS, *p)); + int qd = ((! *q) || strchr(PATH_TOKENS, *q)); + + if(pd && qd) + break; + else if(pd) + return(-1); + else if(qd) + return(1); + else if(*p < *q) + return(-1); + else if(*p > *q) + return(1); + } + + return(0); +} + +/* ------------------------------------------------------------------------- */ + +static void __config_indent(FILE *stream, int depth, unsigned short w) +{ + if(w) + fprintf(stream, "%*s", (depth - 1) * w, " "); + else + { + int i; + for(i = 0; i < (depth - 1); ++i) + fputc('\t', stream); + } +} + +/* ------------------------------------------------------------------------- */ + +static void __config_write_value(const config_value_t *value, int type, + int format, int depth, + unsigned short tab_width, FILE *stream) +{ + char fbuf[64]; + + switch(type) + { + /* boolean */ + case CONFIG_TYPE_BOOL: + fputs(value->ival ? "true" : "false", stream); + break; + + /* int */ + case CONFIG_TYPE_INT: + switch(format) + { + case CONFIG_FORMAT_HEX: + fprintf(stream, "0x%X", value->ival); + break; + + case CONFIG_FORMAT_DEFAULT: + default: + fprintf(stream, "%d", value->ival); + break; + } + break; + + /* 64-bit int */ + case CONFIG_TYPE_INT64: + switch(format) + { + case CONFIG_FORMAT_HEX: + fprintf(stream, "0x" INT64_HEX_FMT "L", value->llval); + break; + + case CONFIG_FORMAT_DEFAULT: + default: + fprintf(stream, INT64_FMT "L", value->llval); + break; + } + break; + + /* float */ + case CONFIG_TYPE_FLOAT: + { + char *q; + + snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval); + + /* check for exponent */ + q = strchr(fbuf, 'e'); + if(! q) + { + /* no exponent */ + if(! strchr(fbuf, '.')) /* no decimal point */ + strcat(fbuf, ".0"); + else + { + /* has decimal point */ + char *p; + + for(p = fbuf + strlen(fbuf) - 1; p > fbuf; --p) + { + if(*p != '0') + { + *(++p) = '\0'; + break; + } + } + } + } + + fputs(fbuf, stream); + break; + } + + /* string */ + case CONFIG_TYPE_STRING: + { + char *p; + + fputc('\"', stream); + + if(value->sval) + { + for(p = value->sval; *p; p++) + { + int c = (int)*p & 0xFF; + switch(c) + { + case '\"': + case '\\': + fputc('\\', stream); + fputc(c, stream); + break; + + case '\n': + fputs("\\n", stream); + break; + + case '\r': + fputs("\\r", stream); + break; + + case '\f': + fputs("\\f", stream); + break; + + case '\t': + fputs("\\t", stream); + break; + + default: + if(c >= ' ') + fputc(c, stream); + else + fprintf(stream, "\\x%02X", c); + } + } + } + fputc('\"', stream); + break; + } + + /* list */ + case CONFIG_TYPE_LIST: + { + config_list_t *list = value->list; + + fprintf(stream, "( "); + + if(list) + { + int len = list->length; + config_setting_t **s; + + for(s = list->elements; len--; s++) + { + __config_write_value(&((*s)->value), (*s)->type, + config_setting_get_format(*s), + depth + 1, tab_width, stream); + + if(len) + fputc(',', stream); + + fputc(' ', stream); + } + } + + fputc(')', stream); + break; + } + + /* array */ + case CONFIG_TYPE_ARRAY: + { + config_list_t *list = value->list; + + fprintf(stream, "[ "); + + if(list) + { + int len = list->length; + config_setting_t **s; + + for(s = list->elements; len--; s++) + { + __config_write_value(&((*s)->value), (*s)->type, + config_setting_get_format(*s), + depth + 1, tab_width, stream); + + if(len) + fputc(',', stream); + + fputc(' ', stream); + } + } + + fputc(']', stream); + break; + } + + /* group */ + case CONFIG_TYPE_GROUP: + { + config_list_t *list = value->list; + + if(depth > 0) + { +#ifdef K_AND_R_STYLE /* Horrendous, but many people like it. */ + fputc(' ', stream); +#else + fputc('\n', stream); + + if(depth > 1) + __config_indent(stream, depth, tab_width); +#endif + fprintf(stream, "{\n"); + } + + if(list) + { + int len = list->length; + config_setting_t **s; + + for(s = list->elements; len--; s++) + __config_write_setting(*s, stream, depth + 1, tab_width); + } + + if(depth > 1) + __config_indent(stream, depth, tab_width); + + if(depth > 0) + fputc('}', stream); + + break; + } + + default: + /* this shouldn't happen, but handle it gracefully... */ + fputs("???", stream); + break; + } +} + +/* ------------------------------------------------------------------------- */ + +static void __config_list_add(config_list_t *list, config_setting_t *setting) +{ + if((list->length % CHUNK_SIZE) == 0) + { + list->elements = (config_setting_t **)realloc( + list->elements, + (list->length + CHUNK_SIZE) * sizeof(config_setting_t *)); + } + + list->elements[list->length] = setting; + list->length++; +} + +/* ------------------------------------------------------------------------- */ + +static config_setting_t *__config_list_search(config_list_t *list, + const char *name, + unsigned int *idx) +{ + config_setting_t **found = NULL; + unsigned int i; + + if(! list) + return(NULL); + + for(i = 0, found = list->elements; i < list->length; i++, found++) + { + if(! (*found)->name) + continue; + + if(! __config_name_compare(name, (*found)->name)) + { + if(idx) + *idx = i; + + return(*found); + } + } + + return(NULL); +} + +/* ------------------------------------------------------------------------- */ + +static config_setting_t *__config_list_remove(config_list_t *list, int idx) +{ + config_setting_t *removed = *(list->elements + idx); + int offset = (idx * sizeof(config_setting_t *)); + int len = list->length - 1 - idx; + char *base = (char *)list->elements + offset; + + memmove(base, base + sizeof(config_setting_t *), + len * sizeof(config_setting_t *)); + + list->length--; + + /* possibly realloc smaller? */ + + return(removed); +} + +/* ------------------------------------------------------------------------- */ + +static void __config_setting_destroy(config_setting_t *setting) +{ + if(setting) + { + if(setting->name) + _delete(setting->name); + + if(setting->type == CONFIG_TYPE_STRING) + _delete(setting->value.sval); + + else if((setting->type == CONFIG_TYPE_GROUP) + || (setting->type == CONFIG_TYPE_ARRAY) + || (setting->type == CONFIG_TYPE_LIST)) + { + if(setting->value.list) + __config_list_destroy(setting->value.list); + } + + if(setting->hook && setting->config->destructor) + setting->config->destructor(setting->hook); + + _delete(setting); + } +} + +/* ------------------------------------------------------------------------- */ + +static void __config_list_destroy(config_list_t *list) +{ + config_setting_t **p; + unsigned int i; + + if(! list) + return; + + if(list->elements) + { + for(p = list->elements, i = 0; i < list->length; p++, i++) + __config_setting_destroy(*p); + + _delete(list->elements); + } + + _delete(list); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_vector_checktype(const config_setting_t *vector, int type) +{ + /* if the array is empty, then it has no type yet */ + + if(! vector->value.list) + return(CONFIG_TRUE); + + if(vector->value.list->length == 0) + return(CONFIG_TRUE); + + /* if it's a list, any type is allowed */ + + if(vector->type == CONFIG_TYPE_LIST) + return(CONFIG_TRUE); + + /* otherwise the first element added determines the type of the array */ + + return((vector->value.list->elements[0]->type == type) + ? CONFIG_TRUE : CONFIG_FALSE); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_validate_name(const char *name) +{ + const char *p = name; + + if(*p == '\0') + return(CONFIG_FALSE); + + if(! isalpha(*p) && (*p != '*')) + return(CONFIG_FALSE); + + for(++p; *p; ++p) + { + if(! (isalpha(*p) || isdigit(*p) || strchr("*_-", (int)*p))) + return(CONFIG_FALSE); + } + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_read(config_t *config, FILE *stream, const char *filename, + const char *str) +{ + yyscan_t scanner; + struct scan_context scan_ctx; + struct parse_context parse_ctx; + YY_BUFFER_STATE buffer = NULL; + int r; + + /* Reinitialize the config */ + void (*destructor)(void *) = config->destructor; + const char *include_dir = config->include_dir; + unsigned short tab_width = config->tab_width; + unsigned short flags = config->flags; + + config->include_dir = NULL; + config_destroy(config); + config_init(config); + + config->destructor = destructor; + config->include_dir = include_dir; + config->tab_width = tab_width; + config->flags = flags; + + parsectx_init(&parse_ctx); + parse_ctx.config = config; + parse_ctx.parent = config->root; + parse_ctx.setting = config->root; + + __config_locale_override(); + + scanctx_init(&scan_ctx, filename); + scan_ctx.config = config; + libconfig_yylex_init_extra(&scan_ctx, &scanner); + + if(stream) + libconfig_yyrestart(stream, scanner); + else /* read from string */ + buffer = libconfig_yy_scan_string(str, scanner); + + libconfig_yyset_lineno(1, scanner); + r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx); + + if(r != 0) + { + YY_BUFFER_STATE buf; + + config->error_file = scanctx_current_filename(&scan_ctx); + config->error_type = CONFIG_ERR_PARSE; + + /* Unwind the include stack, freeing the buffers and closing the files. */ + while((buf = (YY_BUFFER_STATE)scanctx_pop_include(&scan_ctx)) != NULL) + libconfig_yy_delete_buffer(buf, scanner); + } + + libconfig_yylex_destroy(scanner); + config->filenames = scanctx_cleanup(&scan_ctx, &(config->num_filenames)); + parsectx_cleanup(&parse_ctx); + + __config_locale_restore(); + + return(r == 0 ? CONFIG_TRUE : CONFIG_FALSE); +} + +/* ------------------------------------------------------------------------- */ + +int config_read(config_t *config, FILE *stream) +{ + return(__config_read(config, stream, NULL, NULL)); +} + +/* ------------------------------------------------------------------------- */ + +int config_read_string(config_t *config, const char *str) +{ + return(__config_read(config, NULL, NULL, str)); +} + +/* ------------------------------------------------------------------------- */ + +static void __config_write_setting(const config_setting_t *setting, + FILE *stream, int depth, + unsigned short tab_width) +{ + if(depth > 1) + __config_indent(stream, depth, tab_width); + + if(setting->name) + { + fputs(setting->name, stream); + fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '=')); + } + + __config_write_value(&(setting->value), setting->type, + config_setting_get_format(setting), + depth, tab_width, stream); + + if(depth > 0) + { + fputc(';', stream); + fputc('\n', stream); + } +} + +/* ------------------------------------------------------------------------- */ + +void config_write(const config_t *config, FILE *stream) +{ + __config_locale_override(); + + __config_write_setting(config->root, stream, 0, config->tab_width); + + __config_locale_restore(); +} + +/* ------------------------------------------------------------------------- */ + +int config_read_file(config_t *config, const char *filename) +{ + int ret; + FILE *stream = fopen(filename, "rt"); + if(! stream) + { + config->error_text = __io_error; + config->error_type = CONFIG_ERR_FILE_IO; + return(CONFIG_FALSE); + } + + ret = __config_read(config, stream, filename, NULL); + fclose(stream); + + return(ret); +} + +/* ------------------------------------------------------------------------- */ + +int config_write_file(config_t *config, const char *filename) +{ + FILE *f = fopen(filename, "wt"); + if(! f) + { + config->error_text = __io_error; + config->error_type = CONFIG_ERR_FILE_IO; + return(CONFIG_FALSE); + } + + config_write(config, f); + fclose(f); + config->error_type = CONFIG_ERR_NONE; + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +void config_destroy(config_t *config) +{ + unsigned int count = config->num_filenames; + const char **f; + + __config_setting_destroy(config->root); + + for(f = config->filenames; count > 0; ++f, --count) + _delete(*f); + + _delete(config->filenames); + _delete(config->include_dir); + + memset((void *)config, 0, sizeof(config_t)); +} + +/* ------------------------------------------------------------------------- */ + +void config_init(config_t *config) +{ + memset((void *)config, 0, sizeof(config_t)); + + config->root = _new(config_setting_t); + config->root->type = CONFIG_TYPE_GROUP; + config->root->config = config; + config->tab_width = 2; +} + +/* ------------------------------------------------------------------------- */ + +void config_set_auto_convert(config_t *config, int flag) +{ + if(flag) + config->flags |= CONFIG_OPTION_AUTOCONVERT; + else + config->flags &= ~CONFIG_OPTION_AUTOCONVERT; +} + +/* ------------------------------------------------------------------------- */ + +int config_get_auto_convert(const config_t *config) +{ + return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0); +} + +/* ------------------------------------------------------------------------- */ + +static config_setting_t *config_setting_create(config_setting_t *parent, + const char *name, int type) +{ + config_setting_t *setting; + config_list_t *list; + + if((parent->type != CONFIG_TYPE_GROUP) + && (parent->type != CONFIG_TYPE_ARRAY) + && (parent->type != CONFIG_TYPE_LIST)) + return(NULL); + + setting = _new(config_setting_t); + setting->parent = parent; + setting->name = (name == NULL) ? NULL : strdup(name); + setting->type = type; + setting->config = parent->config; + setting->hook = NULL; + setting->line = 0; + + list = parent->value.list; + + if(! list) + list = parent->value.list = _new(config_list_t); + + __config_list_add(list, setting); + + return(setting); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_int(const config_setting_t *setting, + int *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_INT: + *value = setting->value.ival; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT64: + if((setting->value.llval > INT32_MAX) + || (setting->value.llval < INT32_MIN)) + *value = 0; + else + *value = (int)(setting->value.llval); + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + *value = (int)(setting->value.fval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_int(const config_setting_t *setting) +{ + int value = 0; + __config_setting_get_int(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_int64(const config_setting_t *setting, + long long *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_INT64: + *value = setting->value.llval; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + *value = (long long)(setting->value.ival); + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + *value = (long long)(setting->value.fval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +long long config_setting_get_int64(const config_setting_t *setting) +{ + long long value = 0; + __config_setting_get_int64(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_int(const config_setting_t *setting, + const char *name, int *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + return(__config_setting_get_int(member, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_int64(const config_setting_t *setting, + const char *name, long long *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + return(__config_setting_get_int64(member, value)); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_float(const config_setting_t *setting, + double *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_FLOAT: + *value = setting->value.fval; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if(config_get_auto_convert(setting->config)) + { + *value = (double)(setting->value.ival); + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + case CONFIG_TYPE_INT64: + if(config_get_auto_convert(setting->config)) + { + *value = (double)(setting->value.llval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +double config_setting_get_float(const config_setting_t *setting) +{ + double value = 0.0; + __config_setting_get_float(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_float(const config_setting_t *setting, + const char *name, double *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + return(__config_setting_get_float(member, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_string(const config_setting_t *setting, + const char *name, const char **value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + if(config_setting_type(member) != CONFIG_TYPE_STRING) + return(CONFIG_FALSE); + + *value = config_setting_get_string(member); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_bool(const config_setting_t *setting, + const char *name, int *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + if(config_setting_type(member) != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + *value = config_setting_get_bool(member); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_int(config_setting_t *setting, int value) +{ + switch(setting->type) + { + case CONFIG_TYPE_NONE: + setting->type = CONFIG_TYPE_INT; + /* fall through */ + + case CONFIG_TYPE_INT: + setting->value.ival = value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if(config_get_auto_convert(setting->config)) + { + setting->value.fval = (float)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_int64(config_setting_t *setting, long long value) +{ + switch(setting->type) + { + case CONFIG_TYPE_NONE: + setting->type = CONFIG_TYPE_INT64; + /* fall through */ + + case CONFIG_TYPE_INT64: + setting->value.llval = value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if((value > INT32_MAX) || (value < INT32_MIN)) + setting->value.ival = 0; + else + setting->value.ival = (int)value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if(config_get_auto_convert(setting->config)) + { + setting->value.fval = (float)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_float(config_setting_t *setting, double value) +{ + switch(setting->type) + { + case CONFIG_TYPE_NONE: + setting->type = CONFIG_TYPE_FLOAT; + /* fall through */ + + case CONFIG_TYPE_FLOAT: + setting->value.fval = value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + setting->value.ival = (int)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + case CONFIG_TYPE_INT64: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + setting->value.llval = (long long)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_bool(const config_setting_t *setting) +{ + return((setting->type == CONFIG_TYPE_BOOL) ? setting->value.ival : 0); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_bool(config_setting_t *setting, int value) +{ + if(setting->type == CONFIG_TYPE_NONE) + setting->type = CONFIG_TYPE_BOOL; + else if(setting->type != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + setting->value.ival = value; + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +const char *config_setting_get_string(const config_setting_t *setting) +{ + return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_string(config_setting_t *setting, const char *value) +{ + if(setting->type == CONFIG_TYPE_NONE) + setting->type = CONFIG_TYPE_STRING; + else if(setting->type != CONFIG_TYPE_STRING) + return(CONFIG_FALSE); + + if(setting->value.sval) + _delete(setting->value.sval); + + setting->value.sval = (value == NULL) ? NULL : strdup(value); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_format(config_setting_t *setting, short format) +{ + if(((setting->type != CONFIG_TYPE_INT) + && (setting->type != CONFIG_TYPE_INT64)) + || ((format != CONFIG_FORMAT_DEFAULT) && (format != CONFIG_FORMAT_HEX))) + return(CONFIG_FALSE); + + setting->format = format; + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +short config_setting_get_format(const config_setting_t *setting) +{ + return(setting->format != 0 ? setting->format + : setting->config->default_format); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_lookup_from(config_setting_t *setting, + const char *path) +{ + const char *p = path; + config_setting_t *found; + + for(;;) + { + while(*p && strchr(PATH_TOKENS, *p)) + p++; + + if(! *p) + break; + + if(*p == '[') + found = config_setting_get_elem(setting, atoi(++p)); + else + found = config_setting_get_member(setting, p); + + if(! found) + break; + + setting = found; + + while(! strchr(PATH_TOKENS, *p)) + p++; + } + + return(*p ? NULL : setting); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_lookup(const config_t *config, const char *path) +{ + return(config_lookup_from(config->root, path)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_string(const config_t *config, const char *path, + const char **value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + if(config_setting_type(s) != CONFIG_TYPE_STRING) + return(CONFIG_FALSE); + + *value = config_setting_get_string(s); + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_int(const config_t *config, const char *path, + int *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + return(__config_setting_get_int(s, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_int64(const config_t *config, const char *path, + long long *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + return(__config_setting_get_int64(s, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_float(const config_t *config, const char *path, + double *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + return(__config_setting_get_float(s, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_bool(const config_t *config, const char *path, int *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + if(config_setting_type(s) != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + *value = config_setting_get_bool(s); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_int_elem(const config_setting_t *vector, int idx) +{ + const config_setting_t *element = config_setting_get_elem(vector, idx); + + return(element ? config_setting_get_int(element) : 0); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_int_elem(config_setting_t *vector, + int idx, int value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_INT)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_INT); + } + else + { + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + } + + if(! config_setting_set_int(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +long long config_setting_get_int64_elem(const config_setting_t *vector, + int idx) +{ + const config_setting_t *element = config_setting_get_elem(vector, idx); + + return(element ? config_setting_get_int64(element) : 0); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_int64_elem(config_setting_t *vector, + int idx, long long value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_INT64)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_INT64); + } + else + { + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + } + + if(! config_setting_set_int64(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +double config_setting_get_float_elem(const config_setting_t *vector, int idx) +{ + config_setting_t *element = config_setting_get_elem(vector, idx); + + return(element ? config_setting_get_float(element) : 0.0); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_float_elem(config_setting_t *vector, + int idx, double value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_FLOAT)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_FLOAT); + } + else + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(! config_setting_set_float(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_bool_elem(const config_setting_t *vector, int idx) +{ + config_setting_t *element = config_setting_get_elem(vector, idx); + + if(! element) + return(CONFIG_FALSE); + + if(element->type != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + return(element->value.ival); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_bool_elem(config_setting_t *vector, + int idx, int value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_BOOL)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_BOOL); + } + else + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(! config_setting_set_bool(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +const char *config_setting_get_string_elem(const config_setting_t *vector, + int idx) +{ + config_setting_t *element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(element->type != CONFIG_TYPE_STRING) + return(NULL); + + return(element->value.sval); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_string_elem(config_setting_t *vector, + int idx, const char *value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_STRING)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_STRING); + } + else + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(! config_setting_set_string(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_get_elem(const config_setting_t *vector, + unsigned int idx) +{ + config_list_t *list = vector->value.list; + + if(((vector->type != CONFIG_TYPE_ARRAY) + && (vector->type != CONFIG_TYPE_LIST) + && (vector->type != CONFIG_TYPE_GROUP)) || ! list) + return(NULL); + + if(idx >= list->length) + return(NULL); + + return(list->elements[idx]); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_get_member(const config_setting_t *setting, + const char *name) +{ + if(setting->type != CONFIG_TYPE_GROUP) + return(NULL); + + return(__config_list_search(setting->value.list, name, NULL)); +} + +/* ------------------------------------------------------------------------- */ + +void config_set_destructor(config_t *config, void (*destructor)(void *)) +{ + config->destructor = destructor; +} + +/* ------------------------------------------------------------------------- */ + +void config_set_include_dir(config_t *config, const char *include_dir) +{ + _delete(config->include_dir); + config->include_dir = strdup(include_dir); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_length(const config_setting_t *setting) +{ + if((setting->type != CONFIG_TYPE_GROUP) + && (setting->type != CONFIG_TYPE_ARRAY) + && (setting->type != CONFIG_TYPE_LIST)) + return(0); + + if(! setting->value.list) + return(0); + + return(setting->value.list->length); +} + +/* ------------------------------------------------------------------------- */ + +void config_setting_set_hook(config_setting_t *setting, void *hook) +{ + setting->hook = hook; +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_add(config_setting_t *parent, + const char *name, int type) +{ + if((type < CONFIG_TYPE_NONE) || (type > CONFIG_TYPE_LIST)) + return(NULL); + + if(! parent) + return(NULL); + + if((parent->type == CONFIG_TYPE_ARRAY) || (parent->type == CONFIG_TYPE_LIST)) + name = NULL; + + if(name) + { + if(! __config_validate_name(name)) + return(NULL); + } + + if(config_setting_get_member(parent, name) != NULL) + return(NULL); /* already exists */ + + return(config_setting_create(parent, name, type)); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_remove(config_setting_t *parent, const char *name) +{ + unsigned int idx; + config_setting_t *setting; + + if(! parent) + return(CONFIG_FALSE); + + if(parent->type != CONFIG_TYPE_GROUP) + return(CONFIG_FALSE); + + if(! (setting = __config_list_search(parent->value.list, name, &idx))) + return(CONFIG_FALSE); + + __config_list_remove(parent->value.list, idx); + __config_setting_destroy(setting); + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_remove_elem(config_setting_t *parent, unsigned int idx) +{ + config_list_t *list; + config_setting_t *removed = NULL; + + if(! parent) + return(CONFIG_FALSE); + + list = parent->value.list; + + if(((parent->type != CONFIG_TYPE_ARRAY) + && (parent->type != CONFIG_TYPE_LIST) + && (parent->type != CONFIG_TYPE_GROUP)) || ! list) + return(CONFIG_FALSE); + + if(idx >= list->length) + return(CONFIG_FALSE); + + removed = __config_list_remove(list, idx); + __config_setting_destroy(removed); + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_index(const config_setting_t *setting) +{ + config_setting_t **found = NULL; + config_list_t *list; + int i; + + if(! setting->parent) + return(-1); + + list = setting->parent->value.list; + + for(i = 0, found = list->elements; i < (int)list->length; ++i, ++found) + { + if(*found == setting) + return(i); + } + + return(-1); +} + +/* ------------------------------------------------------------------------- */ +/* eof */ diff --git a/src/3rdparty/libconfig/libconfig.h b/src/3rdparty/libconfig/libconfig.h new file mode 100644 index 0000000..cc079db --- /dev/null +++ b/src/3rdparty/libconfig/libconfig.h @@ -0,0 +1,321 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_h +#define __libconfig_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#if defined(LIBCONFIG_STATIC) +#define LIBCONFIG_API +#elif defined(LIBCONFIG_EXPORTS) +#define LIBCONFIG_API __declspec(dllexport) +#else /* ! LIBCONFIG_EXPORTS */ +#define LIBCONFIG_API __declspec(dllimport) +#endif /* LIBCONFIG_STATIC */ +#else /* ! WIN32 */ +#define LIBCONFIG_API +#endif /* WIN32 */ + +#define LIBCONFIG_VER_MAJOR 1 +#define LIBCONFIG_VER_MINOR 4 +#define LIBCONFIG_VER_REVISION 8 + +#include + +#define CONFIG_TYPE_NONE 0 +#define CONFIG_TYPE_GROUP 1 +#define CONFIG_TYPE_INT 2 +#define CONFIG_TYPE_INT64 3 +#define CONFIG_TYPE_FLOAT 4 +#define CONFIG_TYPE_STRING 5 +#define CONFIG_TYPE_BOOL 6 +#define CONFIG_TYPE_ARRAY 7 +#define CONFIG_TYPE_LIST 8 + +#define CONFIG_FORMAT_DEFAULT 0 +#define CONFIG_FORMAT_HEX 1 + +#define CONFIG_OPTION_AUTOCONVERT 0x01 + +#define CONFIG_TRUE (1) +#define CONFIG_FALSE (0) + +typedef union config_value_t +{ + int ival; + long long llval; + double fval; + char *sval; + struct config_list_t *list; +} config_value_t; + +typedef struct config_setting_t +{ + char *name; + short type; + short format; + config_value_t value; + struct config_setting_t *parent; + struct config_t *config; + void *hook; + unsigned int line; + const char *file; +} config_setting_t; + +typedef enum +{ + CONFIG_ERR_NONE = 0, + CONFIG_ERR_FILE_IO = 1, + CONFIG_ERR_PARSE = 2 +} config_error_t; + +typedef struct config_list_t +{ + unsigned int length; + config_setting_t **elements; +} config_list_t; + +typedef struct config_t +{ + config_setting_t *root; + void (*destructor)(void *); + unsigned short flags; + unsigned short tab_width; + short default_format; + const char *include_dir; + const char *error_text; + const char *error_file; + int error_line; + config_error_t error_type; + const char **filenames; + unsigned int num_filenames; +} config_t; + +extern LIBCONFIG_API int config_read(config_t *config, FILE *stream); +extern LIBCONFIG_API void config_write(const config_t *config, FILE *stream); + +extern LIBCONFIG_API void config_set_default_format(config_t *config, + short format); + +extern LIBCONFIG_API void config_set_auto_convert(config_t *config, int flag); +extern LIBCONFIG_API int config_get_auto_convert(const config_t *config); + +extern LIBCONFIG_API int config_read_string(config_t *config, const char *str); + +extern LIBCONFIG_API int config_read_file(config_t *config, + const char *filename); +extern LIBCONFIG_API int config_write_file(config_t *config, + const char *filename); + +extern LIBCONFIG_API void config_set_destructor(config_t *config, + void (*destructor)(void *)); +extern LIBCONFIG_API void config_set_include_dir(config_t *config, + const char *include_dir); + +extern LIBCONFIG_API void config_init(config_t *config); +extern LIBCONFIG_API void config_destroy(config_t *config); + +extern LIBCONFIG_API int config_setting_get_int( + const config_setting_t *setting); +extern LIBCONFIG_API long long config_setting_get_int64( + const config_setting_t *setting); +extern LIBCONFIG_API double config_setting_get_float( + const config_setting_t *setting); +extern LIBCONFIG_API int config_setting_get_bool( + const config_setting_t *setting); +extern LIBCONFIG_API const char *config_setting_get_string( + const config_setting_t *setting); + +extern LIBCONFIG_API int config_setting_lookup_int( + const config_setting_t *setting, const char *name, int *value); +extern LIBCONFIG_API int config_setting_lookup_int64( + const config_setting_t *setting, const char *name, long long *value); +extern LIBCONFIG_API int config_setting_lookup_float( + const config_setting_t *setting, const char *name, double *value); +extern LIBCONFIG_API int config_setting_lookup_bool( + const config_setting_t *setting, const char *name, int *value); +extern LIBCONFIG_API int config_setting_lookup_string( + const config_setting_t *setting, const char *name, const char **value); + +extern LIBCONFIG_API int config_setting_set_int(config_setting_t *setting, + int value); +extern LIBCONFIG_API int config_setting_set_int64(config_setting_t *setting, + long long value); +extern LIBCONFIG_API int config_setting_set_float(config_setting_t *setting, + double value); +extern LIBCONFIG_API int config_setting_set_bool(config_setting_t *setting, + int value); +extern LIBCONFIG_API int config_setting_set_string(config_setting_t *setting, + const char *value); + +extern LIBCONFIG_API int config_setting_set_format(config_setting_t *setting, + short format); +extern LIBCONFIG_API short config_setting_get_format( + const config_setting_t *setting); + +extern LIBCONFIG_API int config_setting_get_int_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API long long config_setting_get_int64_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API double config_setting_get_float_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API int config_setting_get_bool_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API const char *config_setting_get_string_elem( + const config_setting_t *setting, int idx); + +extern LIBCONFIG_API config_setting_t *config_setting_set_int_elem( + config_setting_t *setting, int idx, int value); +extern LIBCONFIG_API config_setting_t *config_setting_set_int64_elem( + config_setting_t *setting, int idx, long long value); +extern LIBCONFIG_API config_setting_t *config_setting_set_float_elem( + config_setting_t *setting, int idx, double value); +extern LIBCONFIG_API config_setting_t *config_setting_set_bool_elem( + config_setting_t *setting, int idx, int value); +extern LIBCONFIG_API config_setting_t *config_setting_set_string_elem( + config_setting_t *setting, int idx, const char *value); + +#define /* const char * */ config_get_include_dir(/* const config_t * */ C) \ + ((C)->include_dir) + +#define /* int */ config_setting_type(/* const config_setting_t * */ S) \ + ((S)->type) + +#define /* int */ config_setting_is_group(/* const config_setting_t * */ S) \ + ((S)->type == CONFIG_TYPE_GROUP) +#define /* int */ config_setting_is_array(/* const config_setting_t * */ S) \ + ((S)->type == CONFIG_TYPE_ARRAY) +#define /* int */ config_setting_is_list(/* const config_setting_t * */ S) \ + ((S)->type == CONFIG_TYPE_LIST) + +#define /* int */ config_setting_is_aggregate( \ + /* const config_setting_t * */ S) \ + (((S)->type == CONFIG_TYPE_GROUP) || ((S)->type == CONFIG_TYPE_LIST) \ + || ((S)->type == CONFIG_TYPE_ARRAY)) + +#define /* int */ config_setting_is_number(/* const config_setting_t * */ S) \ + (((S)->type == CONFIG_TYPE_INT) \ + || ((S)->type == CONFIG_TYPE_INT64) \ + || ((S)->type == CONFIG_TYPE_FLOAT)) + +#define /* int */ config_setting_is_scalar(/* const config_setting_t * */ S) \ + (((S)->type == CONFIG_TYPE_BOOL) || ((S)->type == CONFIG_TYPE_STRING) \ + || config_setting_is_number(S)) + +#define /* const char * */ config_setting_name( \ + /* const config_setting_t * */ S) \ + ((S)->name) + +#define /* config_setting_t * */ config_setting_parent( \ + /* const config_setting_t * */ S) \ + ((S)->parent) + +#define /* int */ config_setting_is_root( \ + /* const config_setting_t * */ S) \ + ((S)->parent ? CONFIG_FALSE : CONFIG_TRUE) + +extern LIBCONFIG_API int config_setting_index(const config_setting_t *setting); + +extern LIBCONFIG_API int config_setting_length( + const config_setting_t *setting); +extern LIBCONFIG_API config_setting_t *config_setting_get_elem( + const config_setting_t *setting, unsigned int idx); + +extern LIBCONFIG_API config_setting_t *config_setting_get_member( + const config_setting_t *setting, const char *name); + +extern LIBCONFIG_API config_setting_t *config_setting_add( + config_setting_t *parent, const char *name, int type); +extern LIBCONFIG_API int config_setting_remove(config_setting_t *parent, + const char *name); +extern LIBCONFIG_API int config_setting_remove_elem(config_setting_t *parent, + unsigned int idx); +extern LIBCONFIG_API void config_setting_set_hook(config_setting_t *setting, + void *hook); + +#define config_setting_get_hook(S) ((S)->hook) + +extern LIBCONFIG_API config_setting_t *config_lookup(const config_t *config, + const char *path); +extern LIBCONFIG_API config_setting_t *config_lookup_from( + config_setting_t *setting, const char *path); + +extern LIBCONFIG_API int config_lookup_int(const config_t *config, + const char *path, int *value); +extern LIBCONFIG_API int config_lookup_int64(const config_t *config, + const char *path, + long long *value); +extern LIBCONFIG_API int config_lookup_float(const config_t *config, + const char *path, double *value); +extern LIBCONFIG_API int config_lookup_bool(const config_t *config, + const char *path, int *value); +extern LIBCONFIG_API int config_lookup_string(const config_t *config, + const char *path, + const char **value); + +#define /* config_setting_t * */ config_root_setting( \ + /* const config_t * */ C) \ + ((C)->root) + +#define /* void */ config_set_default_format(/* config_t * */ C, \ + /* short */ F) \ + (C)->default_format = (F) + +#define /* short */ config_get_default_format(/* config_t * */ C) \ + ((C)->default_format) + +#define /* void */ config_set_tab_width(/* config_t * */ C, \ + /* unsigned short */ W) \ + (C)->tab_width = ((W) & 0x0F) + +#define /* unsigned char */ config_get_tab_width(/* const config_t * */ C) \ + ((C)->tab_width) + +#define /* unsigned short */ config_setting_source_line( \ + /* const config_setting_t * */ S) \ + ((S)->line) + +#define /* const char */ config_setting_source_file( \ + /* const config_setting_t * */ S) \ + ((S)->file) + +#define /* const char * */ config_error_text(/* const config_t * */ C) \ + ((C)->error_text) + +#define /* const char * */ config_error_file(/* const config_t * */ C) \ + ((C)->error_file) + +#define /* int */ config_error_line(/* const config_t * */ C) \ + ((C)->error_line) + +#define /* config_error_t */ config_error_type(/* const config_t * */ C) \ + ((C)->error_type) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __libconfig_h */ diff --git a/src/3rdparty/libconfig/libconfig.h++ b/src/3rdparty/libconfig/libconfig.h++ new file mode 100644 index 0000000..dfc7939 --- /dev/null +++ b/src/3rdparty/libconfig/libconfig.h++ @@ -0,0 +1,459 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_hpp +#define __libconfig_hpp + +#include +#include +#include + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#if defined(LIBCONFIGXX_STATIC) +#define LIBCONFIGXX_API +#elif defined(LIBCONFIGXX_EXPORTS) +#define LIBCONFIGXX_API __declspec(dllexport) +#else /* ! LIBCONFIGXX_EXPORTS */ +#define LIBCONFIGXX_API __declspec(dllimport) +#endif /* LIBCONFIGXX_STATIC */ +#else /* ! WIN32 */ +#define LIBCONFIGXX_API +#endif /* WIN32 */ + +#define LIBCONFIGXX_VER_MAJOR 1 +#define LIBCONFIGXX_VER_MINOR 4 +#define LIBCONFIGXX_VER_REVISION 8 + +struct config_t; // fwd decl +struct config_setting_t; // fwd decl + +namespace libconfig { + +class LIBCONFIGXX_API ConfigException : public std::exception { }; + +class Setting; // fwd decl + +class LIBCONFIGXX_API SettingException : public ConfigException +{ + friend class Config; + + public: + + SettingException(const SettingException &other); + SettingException& operator=(const SettingException &other); + + virtual ~SettingException() throw(); + + const char *getPath() const; + + virtual const char *what() const throw(); + + protected: + + SettingException(const Setting &setting); + SettingException(const Setting &setting, int idx); + SettingException(const Setting &setting, const char *name); + SettingException(const char *path); + + private: + + char *_path; +}; + +class LIBCONFIGXX_API SettingTypeException : public SettingException +{ + friend class Config; + friend class Setting; + + public: + + const char *what() const throw(); + + private: + + SettingTypeException(const Setting &setting); + SettingTypeException(const Setting &setting, int idx); + SettingTypeException(const Setting &setting, const char *name); +}; + +class LIBCONFIGXX_API SettingNotFoundException : public SettingException +{ + friend class Config; + friend class Setting; + + public: + + const char *what() const throw(); + + private: + + SettingNotFoundException(const Setting &setting, int idx); + SettingNotFoundException(const Setting &setting, const char *name); + SettingNotFoundException(const char *path); +}; + +class LIBCONFIGXX_API SettingNameException : public SettingException +{ + friend class Config; + friend class Setting; + + public: + + const char *what() const throw(); + + private: + + SettingNameException(const Setting &setting, const char *name); +}; + +class LIBCONFIGXX_API FileIOException : public ConfigException +{ + public: + + const char *what() const throw(); +}; + +class LIBCONFIGXX_API ParseException : public ConfigException +{ + friend class Config; + + public: + + ParseException(const ParseException &other); + + virtual ~ParseException() throw(); + + inline const char *getFile() const throw() + { return(_file); } + + inline int getLine() const throw() + { return(_line); } + + inline const char *getError() const throw() + { return(_error); } + + const char *what() const throw(); + + private: + + ParseException(const char *file, int line, const char *error); + + const char *_file; + int _line; + const char *_error; +}; + +class LIBCONFIGXX_API Setting +{ + friend class Config; + + public: + + enum Type + { + TypeNone = 0, + // scalar types + TypeInt, + TypeInt64, + TypeFloat, + TypeString, + TypeBoolean, + // aggregate types + TypeGroup, + TypeArray, + TypeList + }; + + enum Format + { + FormatDefault = 0, + FormatHex = 1 + }; + + private: + + config_setting_t *_setting; + Type _type; + Format _format; + + Setting(config_setting_t *setting); + + void assertType(Type type) const + throw(SettingTypeException); + static Setting & wrapSetting(config_setting_t *setting); + + Setting(const Setting& other); // not supported + Setting& operator=(const Setting& other); // not supported + + public: + + virtual ~Setting() throw(); + + inline Type getType() const throw() { return(_type); } + + inline Format getFormat() const throw() { return(_format); } + void setFormat(Format format) throw(); + + operator bool() const throw(SettingTypeException); + operator int() const throw(SettingTypeException); + operator unsigned int() const throw(SettingTypeException); + operator long() const throw(SettingTypeException); + operator unsigned long() const throw(SettingTypeException); + operator long long() const throw(SettingTypeException); + operator unsigned long long() const throw(SettingTypeException); + operator double() const throw(SettingTypeException); + operator float() const throw(SettingTypeException); + operator const char *() const throw(SettingTypeException); + operator std::string() const throw(SettingTypeException); + + inline const char *c_str() const throw(SettingTypeException) + { return operator const char*(); } + + Setting & operator=(bool value) throw(SettingTypeException); + Setting & operator=(int value) throw(SettingTypeException); + Setting & operator=(long value) throw(SettingTypeException); + Setting & operator=(const long long &value) throw(SettingTypeException); + Setting & operator=(const double &value) throw(SettingTypeException); + Setting & operator=(float value) throw(SettingTypeException); + Setting & operator=(const char *value) throw(SettingTypeException); + Setting & operator=(const std::string &value) throw(SettingTypeException); + + Setting & operator[](const char *key) const + throw(SettingTypeException, SettingNotFoundException); + + inline Setting & operator[](const std::string &key) const + throw(SettingTypeException, SettingNotFoundException) + { return(operator[](key.c_str())); } + + Setting & operator[](int index) const + throw(SettingTypeException, SettingNotFoundException); + + bool lookupValue(const char *name, bool &value) const throw(); + bool lookupValue(const char *name, int &value) const throw(); + bool lookupValue(const char *name, unsigned int &value) const throw(); + bool lookupValue(const char *name, long long &value) const throw(); + bool lookupValue(const char *name, unsigned long long &value) + const throw(); + bool lookupValue(const char *name, double &value) const throw(); + bool lookupValue(const char *name, float &value) const throw(); + bool lookupValue(const char *name, const char *&value) const throw(); + bool lookupValue(const char *name, std::string &value) const throw(); + + inline bool lookupValue(const std::string &name, bool &value) + const throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, int &value) + const throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, unsigned int &value) + const throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, long long &value) + const throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, + unsigned long long &value) const throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, double &value) const + throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, float &value) const + throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, const char *&value) const + throw() + { return(lookupValue(name.c_str(), value)); } + + inline bool lookupValue(const std::string &name, std::string &value) const + throw() + { return(lookupValue(name.c_str(), value)); } + + void remove(const char *name) + throw(SettingTypeException, SettingNotFoundException); + + inline void remove(const std::string & name) + throw(SettingTypeException, SettingNotFoundException) + { remove(name.c_str()); } + + void remove(unsigned int idx) + throw(SettingTypeException, SettingNotFoundException); + + inline Setting & add(const std::string & name, Type type) + throw(SettingNameException, SettingTypeException) + { return(add(name.c_str(), type)); } + + Setting & add(const char *name, Type type) + throw(SettingNameException, SettingTypeException); + + Setting & add(Type type) throw(SettingTypeException); + + inline bool exists(const std::string &name) const throw() + { return(exists(name.c_str())); } + + bool exists(const char *name) const throw(); + + int getLength() const throw(); + const char *getName() const throw(); + std::string getPath() const; + int getIndex() const throw(); + + const Setting & getParent() const throw(SettingNotFoundException); + Setting & getParent() throw(SettingNotFoundException); + + bool isRoot() const throw(); + + inline bool isGroup() const throw() + { return(_type == TypeGroup); } + + inline bool isArray() const throw() + { return(_type == TypeArray); } + + inline bool isList() const throw() + { return(_type == TypeList); } + + inline bool isAggregate() const throw() + { return(_type >= TypeGroup); } + + inline bool isScalar() const throw() + { return((_type > TypeNone) && (_type < TypeGroup)); } + + inline bool isNumber() const throw() + { return((_type == TypeInt) || (_type == TypeInt64) + || (_type == TypeFloat)); } + + unsigned int getSourceLine() const throw(); + const char *getSourceFile() const throw(); +}; + +class LIBCONFIGXX_API Config +{ + private: + + config_t *_config; + + static void ConfigDestructor(void *arg); + Config(const Config& other); // not supported + Config& operator=(const Config& other); // not supported + + public: + + Config(); + virtual ~Config(); + + void setAutoConvert(bool flag); + bool getAutoConvert() const; + + void setDefaultFormat(Setting::Format format); + inline Setting::Format getDefaultFormat() const + { return(_defaultFormat); } + + void setTabWidth(unsigned short width) throw(); + unsigned short getTabWidth() const throw(); + + void setIncludeDir(const char *includeDir) throw(); + const char *getIncludeDir() const throw(); + + void read(FILE *stream) throw(ParseException); + void write(FILE *stream) const; + + void readString(const char *str) throw(ParseException); + inline void readString(const std::string &str) throw(ParseException) + { return(readString(str.c_str())); } + + void readFile(const char *filename) throw(FileIOException, ParseException); + void writeFile(const char *filename) throw(FileIOException); + + inline Setting & lookup(const std::string &path) const + throw(SettingNotFoundException) + { return(lookup(path.c_str())); } + + Setting & lookup(const char *path) const throw(SettingNotFoundException); + + inline bool exists(const std::string & path) const throw() + { return(exists(path.c_str())); } + + bool exists(const char *path) const throw(); + + bool lookupValue(const char *path, bool &value) const throw(); + bool lookupValue(const char *path, int &value) const throw(); + bool lookupValue(const char *path, unsigned int &value) const throw(); + bool lookupValue(const char *path, long long &value) const throw(); + bool lookupValue(const char *path, unsigned long long &value) + const throw(); + bool lookupValue(const char *path, double &value) const throw(); + bool lookupValue(const char *path, float &value) const throw(); + bool lookupValue(const char *path, const char *&value) const throw(); + bool lookupValue(const char *path, std::string &value) const throw(); + + inline bool lookupValue(const std::string &path, bool &value) const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, int &value) const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, unsigned int &value) + const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, long long &value) + const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, + unsigned long long &value) const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, double &value) + const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, float &value) + const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, const char *&value) + const throw() + { return(lookupValue(path.c_str(), value)); } + + inline bool lookupValue(const std::string &path, std::string &value) + const throw() + { return(lookupValue(path.c_str(), value)); } + + Setting & getRoot() const; + + private: + + Setting::Format _defaultFormat; + + void handleError() const; +}; + +} // namespace libconfig + +#endif // __libconfig_hpp diff --git a/src/3rdparty/libconfig/libconfig.hh b/src/3rdparty/libconfig/libconfig.hh new file mode 100644 index 0000000..6883a31 --- /dev/null +++ b/src/3rdparty/libconfig/libconfig.hh @@ -0,0 +1,23 @@ +/* ---------------------------------------------------------------------------- + libconfig - A structured configuration file parsing library + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ---------------------------------------------------------------------------- +*/ + +#include diff --git a/src/3rdparty/libconfig/libconfigcpp.c++ b/src/3rdparty/libconfig/libconfigcpp.c++ new file mode 100644 index 0000000..846c067 --- /dev/null +++ b/src/3rdparty/libconfig/libconfigcpp.c++ @@ -0,0 +1,1167 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#include "libconfig.h++" + +#ifdef _MSC_VER +#pragma warning (disable: 4996) +#endif + +#include "wincompat.h" +#include "libconfig.h" + +#include +#include +#include + +namespace libconfig { + +// --------------------------------------------------------------------------- + +ParseException::ParseException(const char *file, int line, const char *error) + : _file(file ? ::strdup(file) : NULL), _line(line), _error(error) +{ +} + +// --------------------------------------------------------------------------- + +ParseException::ParseException(const ParseException &other) + : _file(other._file ? ::strdup(other._file) : NULL), + _line(other._line), + _error(other._error) +{ +} + +// --------------------------------------------------------------------------- + +ParseException::~ParseException() throw() +{ + ::free((void *)_file); +} + +// --------------------------------------------------------------------------- + +const char *ParseException::what() const throw() +{ + return("ParseException"); +} + +// --------------------------------------------------------------------------- + +static int __toTypeCode(Setting::Type type) +{ + int typecode; + + switch(type) + { + case Setting::TypeGroup: + typecode = CONFIG_TYPE_GROUP; + break; + + case Setting::TypeInt: + typecode = CONFIG_TYPE_INT; + break; + + case Setting::TypeInt64: + typecode = CONFIG_TYPE_INT64; + break; + + case Setting::TypeFloat: + typecode = CONFIG_TYPE_FLOAT; + break; + + case Setting::TypeString: + typecode = CONFIG_TYPE_STRING; + break; + + case Setting::TypeBoolean: + typecode = CONFIG_TYPE_BOOL; + break; + + case Setting::TypeArray: + typecode = CONFIG_TYPE_ARRAY; + break; + + case Setting::TypeList: + typecode = CONFIG_TYPE_LIST; + break; + + default: + typecode = CONFIG_TYPE_NONE; + } + + return(typecode); +} + +// --------------------------------------------------------------------------- + +static void __constructPath(const Setting &setting, + std::stringstream &path) +{ + // head recursion to print path from root to target + + if(! setting.isRoot()) + { + __constructPath(setting.getParent(), path); + if(path.tellp() > 0) + path << '.'; + + const char *name = setting.getName(); + if(name) + path << name; + else + path << '[' << setting.getIndex() << ']'; + } +} + +// --------------------------------------------------------------------------- + +SettingException::SettingException(const Setting &setting) +{ + std::stringstream sstr; + __constructPath(setting, sstr); + + _path = ::strdup(sstr.str().c_str()); +} + +// --------------------------------------------------------------------------- + +SettingException::SettingException(const Setting &setting, int idx) +{ + std::stringstream sstr; + __constructPath(setting, sstr); + sstr << ".[" << idx << "]"; + + _path = ::strdup(sstr.str().c_str()); +} + +// --------------------------------------------------------------------------- + +SettingException::SettingException(const Setting &setting, const char *name) +{ + std::stringstream sstr; + __constructPath(setting, sstr); + sstr << '.' << name; + + _path = ::strdup(sstr.str().c_str()); +} + +// --------------------------------------------------------------------------- + +SettingException::SettingException(const char *path) +{ + _path = ::strdup(path); +} + +// --------------------------------------------------------------------------- + +const char *SettingException::getPath() const +{ + return(_path); +} + +// --------------------------------------------------------------------------- + +SettingException::SettingException(const SettingException &other) +{ + _path = ::strdup(other._path); +} + +// --------------------------------------------------------------------------- + +SettingException &SettingException::operator=(const SettingException &other) +{ + ::free(_path); + _path = ::strdup(other._path); + + return(*this); +} + +// --------------------------------------------------------------------------- + +const char *SettingException::what() const throw() +{ + return("SettingException"); +} + +// --------------------------------------------------------------------------- + +SettingException::~SettingException() throw() +{ + ::free(_path); +} + +// --------------------------------------------------------------------------- + +SettingTypeException::SettingTypeException(const Setting &setting) + : SettingException(setting) +{ +} + +// --------------------------------------------------------------------------- + +SettingTypeException::SettingTypeException(const Setting &setting, int idx) + : SettingException(setting, idx) +{ +} + +// --------------------------------------------------------------------------- + +SettingTypeException::SettingTypeException(const Setting &setting, + const char *name) + : SettingException(setting, name) +{ +} + +// --------------------------------------------------------------------------- + +const char *SettingTypeException::what() const throw() +{ + return("SettingTypeException"); +} + +// --------------------------------------------------------------------------- + +SettingNotFoundException::SettingNotFoundException(const Setting &setting, + int idx) + : SettingException(setting, idx) +{ +} + +// --------------------------------------------------------------------------- + +SettingNotFoundException::SettingNotFoundException(const Setting &setting, + const char *name) + : SettingException(setting, name) +{ +} + +// --------------------------------------------------------------------------- + +SettingNotFoundException::SettingNotFoundException(const char *path) + : SettingException(path) +{ +} + +// --------------------------------------------------------------------------- + +const char *SettingNotFoundException::what() const throw() +{ + return("SettingNotFoundException"); +} + +// --------------------------------------------------------------------------- + +SettingNameException::SettingNameException(const Setting &setting, + const char *name) + : SettingException(setting, name) +{ +} + +// --------------------------------------------------------------------------- + +const char *SettingNameException::what() const throw() +{ + return("SettingNameException"); +} + +// --------------------------------------------------------------------------- + +const char *FileIOException::what() const throw() +{ + return("FileIOException"); +} + +// --------------------------------------------------------------------------- + +void Config::ConfigDestructor(void *arg) +{ + delete reinterpret_cast(arg); +} + +// --------------------------------------------------------------------------- + +Config::Config() + : _defaultFormat(Setting::FormatDefault) +{ + _config = new config_t; + config_init(_config); + config_set_destructor(_config, ConfigDestructor); +} + +// --------------------------------------------------------------------------- + +Config::~Config() +{ + config_destroy(_config); + delete _config; +} + +// --------------------------------------------------------------------------- + +void Config::setAutoConvert(bool flag) +{ + config_set_auto_convert(_config, (flag ? CONFIG_TRUE : CONFIG_FALSE)); +} + +// --------------------------------------------------------------------------- + +bool Config::getAutoConvert() const +{ + return(config_get_auto_convert(_config) != CONFIG_FALSE); +} + +// --------------------------------------------------------------------------- + +void Config::setDefaultFormat(Setting::Format format) +{ + if(format == Setting::FormatHex) + _defaultFormat = Setting::FormatHex; + else + _defaultFormat = Setting::FormatDefault; + + config_set_default_format(_config, static_cast(_defaultFormat)); +} + +// --------------------------------------------------------------------------- + +void Config::setTabWidth(unsigned short width) throw() +{ + config_set_tab_width(_config, width); +} + +// --------------------------------------------------------------------------- + +unsigned short Config::getTabWidth() const throw() +{ + return(config_get_tab_width(_config)); +} + +// --------------------------------------------------------------------------- + +void Config::setIncludeDir(const char *includeDir) throw() +{ + config_set_include_dir(_config, includeDir); +} + +// --------------------------------------------------------------------------- + +const char *Config::getIncludeDir() const throw() +{ + return(config_get_include_dir(_config)); +} + +// --------------------------------------------------------------------------- + +void Config::handleError() const +{ + switch(config_error_type(_config)) + { + case CONFIG_ERR_NONE: + break; + + case CONFIG_ERR_PARSE: + throw ParseException(config_error_file(_config), + config_error_line(_config), + config_error_text(_config)); + break; + + case CONFIG_ERR_FILE_IO: + default: + throw FileIOException(); + } +} + +// --------------------------------------------------------------------------- + +void Config::read(FILE *stream) throw(ParseException) +{ + if(! config_read(_config, stream)) + handleError(); +} + +// --------------------------------------------------------------------------- + +void Config::readString(const char *str) throw(ParseException) +{ + if(! config_read_string(_config, str)) + handleError(); +} + +// --------------------------------------------------------------------------- + +void Config::write(FILE *stream) const +{ + config_write(_config, stream); +} + +// --------------------------------------------------------------------------- + +void Config::readFile(const char *filename) throw(FileIOException, + ParseException) +{ + if(! config_read_file(_config, filename)) + handleError(); +} + +// --------------------------------------------------------------------------- + +void Config::writeFile(const char *filename) throw(FileIOException) +{ + if(! config_write_file(_config, filename)) + handleError(); +} + +// --------------------------------------------------------------------------- + +Setting & Config::lookup(const char *path) const + throw(SettingNotFoundException) +{ + config_setting_t *s = config_lookup(_config, path); + if(! s) + throw SettingNotFoundException(path); + + return(Setting::wrapSetting(s)); +} + +// --------------------------------------------------------------------------- + +bool Config::exists(const char *path) const throw() +{ + config_setting_t *s = config_lookup(_config, path); + + return(s != NULL); +} + +// --------------------------------------------------------------------------- + +#define CONFIG_LOOKUP_NO_EXCEPTIONS(P, T, V) \ + try \ + { \ + Setting &s = lookup(P); \ + V = (T)s; \ + return(true); \ + } \ + catch(ConfigException) \ + { \ + return(false); \ + } + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, bool &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, bool, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, int &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, int, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, unsigned int &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, unsigned int, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, long long &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, long long, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, unsigned long long &value) + const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, unsigned long long, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, double &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, double, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, float &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, float, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, const char *&value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, const char *, value); +} + +// --------------------------------------------------------------------------- + +bool Config::lookupValue(const char *path, std::string &value) const throw() +{ + CONFIG_LOOKUP_NO_EXCEPTIONS(path, const char *, value); +} + +// --------------------------------------------------------------------------- + +Setting & Config::getRoot() const +{ + return(Setting::wrapSetting(config_root_setting(_config))); +} + +// --------------------------------------------------------------------------- + +Setting::Setting(config_setting_t *setting) + : _setting(setting) +{ + switch(config_setting_type(setting)) + { + case CONFIG_TYPE_GROUP: + _type = TypeGroup; + break; + + case CONFIG_TYPE_INT: + _type = TypeInt; + break; + + case CONFIG_TYPE_INT64: + _type = TypeInt64; + break; + + case CONFIG_TYPE_FLOAT: + _type = TypeFloat; + break; + + case CONFIG_TYPE_STRING: + _type = TypeString; + break; + + case CONFIG_TYPE_BOOL: + _type = TypeBoolean; + break; + + case CONFIG_TYPE_ARRAY: + _type = TypeArray; + break; + + case CONFIG_TYPE_LIST: + _type = TypeList; + break; + + case CONFIG_TYPE_NONE: + default: + _type = TypeNone; + break; + } + + switch(config_setting_get_format(setting)) + { + case CONFIG_FORMAT_HEX: + _format = FormatHex; + break; + + case CONFIG_FORMAT_DEFAULT: + default: + _format = FormatDefault; + break; + } +} + +// --------------------------------------------------------------------------- + +Setting::~Setting() throw() +{ + _setting = NULL; +} + +// --------------------------------------------------------------------------- + +void Setting::setFormat(Format format) throw() +{ + if((_type == TypeInt) || (_type == TypeInt64)) + { + if(format == FormatHex) + _format = FormatHex; + else + _format = FormatDefault; + } + else + _format = FormatDefault; + + config_setting_set_format(_setting, static_cast(_format)); +} + +// --------------------------------------------------------------------------- + +Setting::operator bool() const throw(SettingTypeException) +{ + assertType(TypeBoolean); + + return(config_setting_get_bool(_setting) ? true : false); +} + +// --------------------------------------------------------------------------- + +Setting::operator int() const throw(SettingTypeException) +{ + assertType(TypeInt); + + return(config_setting_get_int(_setting)); +} + +// --------------------------------------------------------------------------- + +Setting::operator unsigned int() const throw(SettingTypeException) +{ + assertType(TypeInt); + + int v = config_setting_get_int(_setting); + + if(v < 0) + v = 0; + + return(static_cast(v)); +} + +// --------------------------------------------------------------------------- + +Setting::operator long() const throw(SettingTypeException) +{ + if(sizeof(long) == sizeof(long long)) + return operator long long(); + else + return operator int(); +} + +// --------------------------------------------------------------------------- + +Setting::operator unsigned long() const throw(SettingTypeException) +{ + if(sizeof(long) == sizeof(long long)) + return operator unsigned long long(); + else + return operator unsigned int(); +} + +// --------------------------------------------------------------------------- + +Setting::operator long long() const throw(SettingTypeException) +{ + assertType(TypeInt64); + + return(config_setting_get_int64(_setting)); +} + +// --------------------------------------------------------------------------- + +Setting::operator unsigned long long() const throw(SettingTypeException) +{ + assertType(TypeInt64); + + long long v = config_setting_get_int64(_setting); + + if(v < INT64_CONST(0)) + v = INT64_CONST(0); + + return(static_cast(v)); +} + +// --------------------------------------------------------------------------- + +Setting::operator double() const throw(SettingTypeException) +{ + assertType(TypeFloat); + + return(config_setting_get_float(_setting)); +} + +// --------------------------------------------------------------------------- + +Setting::operator float() const throw(SettingTypeException) +{ + assertType(TypeFloat); + + // may cause loss of precision: + return(static_cast(config_setting_get_float(_setting))); +} + +// --------------------------------------------------------------------------- + +Setting::operator const char *() const throw(SettingTypeException) +{ + assertType(TypeString); + + return(config_setting_get_string(_setting)); +} + +// --------------------------------------------------------------------------- + +Setting::operator std::string() const throw(SettingTypeException) +{ + assertType(TypeString); + + const char *s = config_setting_get_string(_setting); + + std::string str; + if(s) + str = s; + + return(str); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(bool value) throw(SettingTypeException) +{ + assertType(TypeBoolean); + + config_setting_set_bool(_setting, value); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(int value) throw(SettingTypeException) +{ + assertType(TypeInt); + + config_setting_set_int(_setting, value); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(long value) throw(SettingTypeException) +{ + if(sizeof(long) == sizeof(long long)) + return(operator=(static_cast(value))); + else + return(operator=(static_cast(value))); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(const long long &value) + throw(SettingTypeException) +{ + assertType(TypeInt64); + + config_setting_set_int64(_setting, value); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(const double &value) throw(SettingTypeException) +{ + assertType(TypeFloat); + + config_setting_set_float(_setting, value); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(float value) throw(SettingTypeException) +{ + assertType(TypeFloat); + + double cvalue = static_cast(value); + + config_setting_set_float(_setting, cvalue); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(const char *value) throw(SettingTypeException) +{ + assertType(TypeString); + + config_setting_set_string(_setting, value); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator=(const std::string &value) + throw(SettingTypeException) +{ + assertType(TypeString); + + config_setting_set_string(_setting, value.c_str()); + + return(*this); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator[](int i) const + throw(SettingTypeException, SettingNotFoundException) +{ + if((_type != TypeArray) && (_type != TypeGroup) && (_type != TypeList)) + throw SettingTypeException(*this, i); + + config_setting_t *setting = config_setting_get_elem(_setting, i); + + if(! setting) + throw SettingNotFoundException(*this, i); + + return(wrapSetting(setting)); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::operator[](const char *key) const + throw(SettingTypeException, SettingNotFoundException) +{ + assertType(TypeGroup); + + config_setting_t *setting = config_setting_get_member(_setting, key); + + if(! setting) + throw SettingNotFoundException(*this, key); + + return(wrapSetting(setting)); +} + +// --------------------------------------------------------------------------- + +#define SETTING_LOOKUP_NO_EXCEPTIONS(K, T, V) \ + try \ + { \ + Setting &s = operator[](K); \ + V = (T)s; \ + return(true); \ + } \ + catch(ConfigException) \ + { \ + return(false); \ + } + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, bool &value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, bool, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, int &value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, int, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, unsigned int &value) + const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, unsigned int, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, long long &value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, long long, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, unsigned long long &value) + const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, unsigned long long, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, double &value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, double, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, float &value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, float, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, const char *&value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, const char *, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::lookupValue(const char *name, std::string &value) const throw() +{ + SETTING_LOOKUP_NO_EXCEPTIONS(name, const char *, value); +} + +// --------------------------------------------------------------------------- + +bool Setting::exists(const char *name) const throw() +{ + if(_type != TypeGroup) + return(false); + + config_setting_t *setting = config_setting_get_member(_setting, name); + + return(setting != NULL); +} + +// --------------------------------------------------------------------------- + +int Setting::getLength() const throw() +{ + return(config_setting_length(_setting)); +} + +// --------------------------------------------------------------------------- + +const char * Setting::getName() const throw() +{ + return(config_setting_name(_setting)); +} + +// --------------------------------------------------------------------------- + +std::string Setting::getPath() const +{ + std::stringstream path; + + __constructPath(*this, path); + + return(path.str()); +} + +// --------------------------------------------------------------------------- + +const Setting & Setting::getParent() const throw(SettingNotFoundException) +{ + config_setting_t *setting = config_setting_parent(_setting); + + if(! setting) + throw SettingNotFoundException(NULL); + + return(wrapSetting(setting)); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::getParent() throw(SettingNotFoundException) +{ + config_setting_t *setting = config_setting_parent(_setting); + + if(! setting) + throw SettingNotFoundException(NULL); + + return(wrapSetting(setting)); +} + +// --------------------------------------------------------------------------- + +unsigned int Setting::getSourceLine() const throw() +{ + return(config_setting_source_line(_setting)); +} + +// --------------------------------------------------------------------------- + +const char *Setting::getSourceFile() const throw() +{ + return(config_setting_source_file(_setting)); +} + +// --------------------------------------------------------------------------- + +bool Setting::isRoot() const throw() +{ + return(config_setting_is_root(_setting)); +} + +// --------------------------------------------------------------------------- + +int Setting::getIndex() const throw() +{ + return(config_setting_index(_setting)); +} + +// --------------------------------------------------------------------------- + +void Setting::remove(const char *name) + throw(SettingTypeException, SettingNotFoundException) +{ + assertType(TypeGroup); + + if(! config_setting_remove(_setting, name)) + throw SettingNotFoundException(*this, name); +} + +// --------------------------------------------------------------------------- + +void Setting::remove(unsigned int idx) + throw(SettingTypeException, SettingNotFoundException) +{ + if((_type != TypeArray) && (_type != TypeGroup) && (_type != TypeList)) + throw SettingTypeException(*this, idx); + + if(! config_setting_remove_elem(_setting, idx)) + throw SettingNotFoundException(*this, idx); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::add(const char *name, Setting::Type type) + throw(SettingNameException, SettingTypeException) +{ + assertType(TypeGroup); + + int typecode = __toTypeCode(type); + + if(typecode == CONFIG_TYPE_NONE) + throw SettingTypeException(*this, name); + + config_setting_t *setting = config_setting_add(_setting, name, typecode); + + if(! setting) + throw SettingNameException(*this, name); + + return(wrapSetting(setting)); +} + +// --------------------------------------------------------------------------- + +Setting & Setting::add(Setting::Type type) throw(SettingTypeException) +{ + if((_type != TypeArray) && (_type != TypeList)) + throw SettingTypeException(*this); + + if(_type == TypeArray) + { + int idx = getLength(); + + if(idx > 0) + { + Setting::Type atype = operator[](0).getType(); + if(type != atype) + throw SettingTypeException(*this, idx); + } + else + { + if((type != TypeInt) && (type != TypeInt64) && (type != TypeFloat) + && (type != TypeString) && (type != TypeBoolean)) + throw SettingTypeException(*this, idx); + } + } + + int typecode = __toTypeCode(type); + config_setting_t *s = config_setting_add(_setting, NULL, typecode); + + Setting &ns = wrapSetting(s); + + switch(type) + { + case TypeInt: + ns = 0; + break; + + case TypeInt64: + ns = INT64_CONST(0); + break; + + case TypeFloat: + ns = 0.0; + break; + + case TypeString: + ns = (char *)NULL; + break; + + case TypeBoolean: + ns = false; + break; + + default: + // won't happen + break; + } + + return(ns); +} + +// --------------------------------------------------------------------------- + +void Setting::assertType(Setting::Type type) const throw(SettingTypeException) +{ + if(type != _type) + { + if(!(isNumber() && config_get_auto_convert(_setting->config) + && ((type == TypeInt) || (type == TypeInt64) || (type == TypeFloat)))) + throw SettingTypeException(*this); + } +} + +// --------------------------------------------------------------------------- + +Setting & Setting::wrapSetting(config_setting_t *s) +{ + Setting *setting = NULL; + + void *hook = config_setting_get_hook(s); + if(! hook) + { + setting = new Setting(s); + config_setting_set_hook(s, reinterpret_cast(setting)); + } + else + setting = reinterpret_cast(hook); + + return(*setting); +} + +// --------------------------------------------------------------------------- + +}; // namespace libconfig + +// eof diff --git a/src/3rdparty/libconfig/libconfigcpp.cc b/src/3rdparty/libconfig/libconfigcpp.cc new file mode 100644 index 0000000..9431146 --- /dev/null +++ b/src/3rdparty/libconfig/libconfigcpp.cc @@ -0,0 +1,23 @@ +/* ---------------------------------------------------------------------------- + libconfig - A structured configuration file parsing library + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ---------------------------------------------------------------------------- +*/ + +#include "libconfigcpp.c++" diff --git a/src/3rdparty/libconfig/parsectx.h b/src/3rdparty/libconfig/parsectx.h new file mode 100644 index 0000000..af09b56 --- /dev/null +++ b/src/3rdparty/libconfig/parsectx.h @@ -0,0 +1,48 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_parsectx_h +#define __libconfig_parsectx_h + +#include "libconfig.h" +#include "strbuf.h" + +struct parse_context +{ + config_t *config; + config_setting_t *parent; + config_setting_t *setting; + char *name; + strbuf_t string; +}; + +#define parsectx_init(C) \ + memset((C), 0, sizeof(struct parse_context)) +#define parsectx_cleanup(C) \ + free((void *)(strbuf_release(&((C)->string)))) + +#define parsectx_append_string(C, S) \ + strbuf_append(&((C)->string), (S)) +#define parsectx_take_string(C) \ + strbuf_release(&((C)->string)) + +#endif /* __libconfig_parsectx_h */ diff --git a/src/3rdparty/libconfig/scanctx.c b/src/3rdparty/libconfig/scanctx.c new file mode 100644 index 0000000..f287fdf --- /dev/null +++ b/src/3rdparty/libconfig/scanctx.c @@ -0,0 +1,171 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#include "scanctx.h" +#include "wincompat.h" + +#include +#include +#include + +#define STRING_BLOCK_SIZE 64 +#define CHUNK_SIZE 32 + +/* ------------------------------------------------------------------------- */ + +static const char *err_bad_include = "cannot open include file"; +static const char *err_include_too_deep = "include file nesting too deep"; + +/* ------------------------------------------------------------------------- */ + +static const char *__scanctx_add_filename(struct scan_context *ctx, + const char *filename) +{ + unsigned int count = ctx->num_filenames; + const char **f; + + for(f = ctx->filenames; count > 0; ++f, --count) + { + if(!strcmp(*f, filename)) + { + free((void *)filename); + return(*f); /* already in list */ + } + } + + if((ctx->num_filenames % CHUNK_SIZE) == 0) + { + ctx->filenames = (const char **)realloc( + (void *)ctx->filenames, + (ctx->num_filenames + CHUNK_SIZE) * sizeof(const char *)); + } + + ctx->filenames[ctx->num_filenames] = filename; + ++ctx->num_filenames; + return(filename); +} + +/* ------------------------------------------------------------------------- */ + +void scanctx_init(struct scan_context *ctx, const char *top_filename) +{ + memset(ctx, 0, sizeof(struct scan_context)); + if(top_filename) + ctx->top_filename = __scanctx_add_filename(ctx, strdup(top_filename)); +} + +/* ------------------------------------------------------------------------- */ + +const char **scanctx_cleanup(struct scan_context *ctx, + unsigned int *num_filenames) +{ + int i; + + for(i = 0; i < ctx->depth; ++i) + fclose(ctx->streams[i]); + + free((void *)(strbuf_release(&(ctx->string)))); + + *num_filenames = ctx->num_filenames; + return(ctx->filenames); +} + +/* ------------------------------------------------------------------------- */ + +FILE *scanctx_push_include(struct scan_context *ctx, void *buffer, + const char **error) +{ + FILE *fp = NULL; + const char *file; + char *full_file = NULL; + + *error = NULL; + + if(ctx->depth == MAX_INCLUDE_DEPTH) + { + *error = err_include_too_deep; + return(NULL); + } + + file = scanctx_take_string(ctx); + if(ctx->config->include_dir) + { + full_file = (char *)malloc(strlen(ctx->config->include_dir) + strlen(file) + + 2); + strcpy(full_file, ctx->config->include_dir); + strcat(full_file, FILE_SEPARATOR); + strcat(full_file, file); + } + + fp = fopen(full_file ? full_file : file, "rt"); + free((void *)full_file); + + if(fp) + { + ctx->streams[ctx->depth] = fp; + ctx->files[ctx->depth] = __scanctx_add_filename(ctx, file); + ctx->buffers[ctx->depth] = buffer; + ++(ctx->depth); + } + else + { + free((void *)file); + *error = err_bad_include; + } + + return(fp); +} + +/* ------------------------------------------------------------------------- */ + +void *scanctx_pop_include(struct scan_context *ctx) +{ + void *buffer; + + if(ctx->depth == 0) + return(NULL); /* stack underflow */ + + --(ctx->depth); + buffer = ctx->buffers[ctx->depth]; + fclose(ctx->streams[ctx->depth]); + + return(buffer); +} + +/* ------------------------------------------------------------------------- */ + +char *scanctx_take_string(struct scan_context *ctx) +{ + char *r = strbuf_release(&(ctx->string)); + + return(r ? r : strdup("")); +} + +/* ------------------------------------------------------------------------- */ + +const char *scanctx_current_filename(struct scan_context *ctx) +{ + return((ctx->depth == 0) ? ctx->top_filename : ctx->files[ctx->depth - 1]); +} + +/* ------------------------------------------------------------------------- */ +/* eof */ diff --git a/src/3rdparty/libconfig/scanctx.h b/src/3rdparty/libconfig/scanctx.h new file mode 100644 index 0000000..8ff934e --- /dev/null +++ b/src/3rdparty/libconfig/scanctx.h @@ -0,0 +1,62 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_scanctx_h +#define __libconfig_scanctx_h + +#include "libconfig.h" +#include "strbuf.h" + +#include +#include + +#define MAX_INCLUDE_DEPTH 10 + +struct scan_context +{ + config_t *config; + const char *top_filename; + const char *files[MAX_INCLUDE_DEPTH]; + void *buffers[MAX_INCLUDE_DEPTH]; + FILE *streams[MAX_INCLUDE_DEPTH]; + int depth; + strbuf_t string; + const char **filenames; + unsigned int num_filenames; +}; + +extern void scanctx_init(struct scan_context *ctx, const char *top_filename); +extern const char **scanctx_cleanup(struct scan_context *ctx, + unsigned int *num_filenames); + +extern FILE *scanctx_push_include(struct scan_context *ctx, void *prev_buffer, + const char **error); +extern void *scanctx_pop_include(struct scan_context *ctx); + +#define scanctx_append_string(C, S) \ + strbuf_append(&((C)->string), (S)) + +extern char *scanctx_take_string(struct scan_context *ctx); + +extern const char *scanctx_current_filename(struct scan_context *ctx); + +#endif /* __libconfig_scanctx_h */ diff --git a/src/3rdparty/libconfig/scanner.c b/src/3rdparty/libconfig/scanner.c new file mode 100644 index 0000000..c2eb7d1 --- /dev/null +++ b/src/3rdparty/libconfig/scanner.c @@ -0,0 +1,2362 @@ +#line 2 "scanner.c" + +#line 4 "scanner.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE libconfig_yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE libconfig_yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ + #define YY_LESS_LINENO(n) \ + do { \ + int yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via libconfig_yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void libconfig_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void libconfig_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void libconfig_yypop_buffer_state (yyscan_t yyscanner ); + +static void libconfig_yyensure_buffer_stack (yyscan_t yyscanner ); +static void libconfig_yy_load_buffer_state (yyscan_t yyscanner ); +static void libconfig_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER libconfig_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE libconfig_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *libconfig_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *libconfig_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void libconfig_yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer libconfig_yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + libconfig_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + libconfig_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +#define libconfig_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 41 +#define YY_END_OF_BUFFER 42 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[103] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 42, 40, + 21, 20, 20, 5, 40, 36, 37, 28, 40, 23, + 29, 40, 30, 30, 22, 38, 28, 28, 34, 35, + 24, 25, 21, 40, 3, 4, 3, 6, 14, 41, + 16, 19, 41, 21, 0, 39, 28, 29, 30, 29, + 0, 1, 0, 29, 0, 31, 0, 28, 28, 21, + 0, 0, 2, 6, 12, 0, 11, 10, 7, 8, + 9, 16, 18, 17, 0, 29, 29, 0, 0, 29, + 31, 32, 28, 28, 0, 0, 0, 29, 33, 28, + 26, 0, 13, 33, 27, 0, 0, 0, 0, 0, + + 15, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 4, 5, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 6, 7, 1, 1, 1, 1, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 18, 19, 1, + 20, 1, 1, 21, 22, 23, 23, 23, 24, 25, + 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, + 26, 28, 29, 30, 31, 26, 26, 32, 26, 26, + 33, 34, 35, 1, 36, 1, 22, 23, 37, 38, + + 39, 40, 26, 26, 41, 26, 26, 42, 26, 43, + 26, 26, 26, 44, 29, 45, 46, 26, 26, 32, + 26, 26, 47, 1, 48, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[49] = + { 0, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 3, + 1, 1, 3, 1, 1, 4, 4, 1, 1, 1, + 1, 4, 4, 4, 4, 3, 3, 3, 3, 3, + 3, 3, 1, 2, 1, 3, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[113] = + { 0, + 0, 47, 47, 48, 46, 47, 48, 49, 203, 204, + 200, 204, 204, 204, 198, 204, 204, 0, 45, 204, + 47, 50, 60, 74, 204, 204, 178, 28, 204, 204, + 204, 204, 64, 158, 204, 204, 183, 0, 204, 63, + 0, 204, 83, 195, 193, 204, 0, 88, 102, 98, + 62, 204, 190, 104, 119, 162, 0, 67, 65, 121, + 127, 124, 204, 0, 204, 0, 204, 204, 204, 204, + 204, 0, 204, 204, 108, 117, 122, 134, 132, 136, + 204, 139, 136, 116, 126, 0, 140, 142, 135, 130, + 0, 102, 204, 204, 0, 85, 72, 63, 98, 158, + + 204, 204, 169, 173, 177, 181, 183, 187, 191, 89, + 66, 63 + } ; + +static yyconst flex_int16_t yy_def[113] = + { 0, + 102, 1, 103, 103, 104, 104, 105, 105, 102, 102, + 102, 102, 102, 102, 106, 102, 102, 107, 102, 102, + 102, 102, 102, 102, 102, 102, 107, 107, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 108, 102, 102, + 109, 102, 102, 102, 106, 102, 107, 102, 102, 102, + 102, 102, 106, 102, 102, 102, 110, 107, 107, 102, + 102, 102, 102, 108, 102, 111, 102, 102, 102, 102, + 102, 109, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 110, 107, 107, 102, 112, 102, 102, 102, 107, + 107, 102, 102, 102, 107, 102, 102, 102, 102, 102, + + 102, 0, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102 + } ; + +static yyconst flex_int16_t yy_nxt[253] = + { 0, + 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, + 19, 20, 19, 21, 22, 23, 24, 25, 26, 25, + 10, 18, 18, 18, 27, 18, 18, 18, 18, 28, + 18, 18, 29, 10, 30, 10, 18, 18, 18, 27, + 18, 18, 18, 18, 28, 18, 31, 32, 33, 36, + 36, 39, 39, 42, 42, 59, 37, 37, 48, 52, + 49, 49, 50, 50, 53, 60, 93, 34, 65, 86, + 51, 59, 75, 54, 75, 49, 49, 76, 76, 40, + 40, 43, 43, 55, 61, 51, 56, 54, 73, 49, + 49, 57, 82, 83, 66, 84, 67, 55, 55, 100, + + 56, 99, 68, 50, 50, 69, 70, 71, 83, 98, + 84, 51, 55, 50, 50, 54, 74, 49, 49, 77, + 77, 51, 60, 76, 76, 55, 51, 78, 56, 79, + 97, 79, 76, 76, 80, 80, 51, 77, 77, 91, + 55, 61, 78, 96, 87, 78, 87, 80, 80, 88, + 88, 80, 80, 95, 91, 88, 88, 88, 88, 100, + 78, 94, 92, 101, 90, 89, 85, 62, 95, 35, + 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, + 41, 45, 45, 45, 45, 47, 47, 64, 81, 64, + 64, 72, 46, 72, 72, 46, 44, 63, 62, 58, + + 46, 44, 102, 9, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102 + } ; + +static yyconst flex_int16_t yy_chk[253] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 4, 5, 6, 7, 8, 28, 3, 4, 19, 22, + 19, 19, 21, 21, 22, 33, 112, 2, 40, 111, + 21, 28, 51, 23, 51, 23, 23, 51, 51, 5, + 6, 7, 8, 23, 33, 21, 23, 24, 43, 24, + 24, 23, 110, 58, 40, 59, 40, 24, 23, 99, + + 24, 98, 40, 48, 48, 40, 40, 40, 58, 97, + 59, 48, 24, 50, 50, 49, 43, 49, 49, 54, + 54, 50, 60, 75, 75, 49, 48, 54, 49, 55, + 96, 55, 76, 76, 55, 55, 50, 77, 77, 84, + 49, 60, 54, 92, 78, 77, 78, 79, 79, 78, + 78, 80, 80, 90, 84, 87, 87, 88, 88, 100, + 77, 89, 85, 100, 83, 82, 62, 61, 90, 103, + 103, 103, 103, 104, 104, 104, 104, 105, 105, 105, + 105, 106, 106, 106, 106, 107, 107, 108, 56, 108, + 108, 109, 53, 109, 109, 45, 44, 37, 34, 27, + + 15, 11, 9, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102 + } ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[42] = + { 0, +0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, }; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "scanner.l" +/* -*- mode: C -*- */ +/* -------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ +#define YY_NO_UNISTD_H 1 +#line 35 "scanner.l" + +#ifdef _MSC_VER +#pragma warning (disable: 4996) +#endif + +#include +#include +#include +#include "grammar.h" +#include "wincompat.h" +#include "parsectx.h" +#include "scanctx.h" + +#define YY_NO_INPUT // Suppress generation of useless input() function + +static unsigned long long fromhex(const char *s) +{ +#ifdef __MINGW32__ + + /* MinGW's strtoull() seems to be broken; it only returns the lower + * 32 bits... + */ + + const char *p = s; + unsigned long long val = 0; + + if(*p != '0') + return(0); + + ++p; + + if(*p != 'x' && *p != 'X') + return(0); + + for(++p; isxdigit(*p); ++p) + { + val <<= 4; + val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7))); + } + + return(val); + +#else /* ! __MINGW32__ */ + + return(strtoull(s, NULL, 16)); + +#endif /* __MINGW32__ */ +} + + +#line 626 "scanner.c" + +#define INITIAL 0 +#define COMMENT 1 +#define STRING 2 +#define INCLUDE 3 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#define YY_EXTRA_TYPE struct scan_context * + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + }; /* end struct yyguts_t */ + +static int yy_init_globals (yyscan_t yyscanner ); + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + +int libconfig_yylex_init (yyscan_t* scanner); + +int libconfig_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int libconfig_yylex_destroy (yyscan_t yyscanner ); + +int libconfig_yyget_debug (yyscan_t yyscanner ); + +void libconfig_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner ); + +void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_in (yyscan_t yyscanner ); + +void libconfig_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_out (yyscan_t yyscanner ); + +void libconfig_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int libconfig_yyget_leng (yyscan_t yyscanner ); + +char *libconfig_yyget_text (yyscan_t yyscanner ); + +int libconfig_yyget_lineno (yyscan_t yyscanner ); + +void libconfig_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner ); + +void libconfig_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int libconfig_yywrap (yyscan_t yyscanner ); +#else +extern int libconfig_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int libconfig_yylex \ + (YYSTYPE * yylval_param ,yyscan_t yyscanner); + +#define YY_DECL int libconfig_yylex \ + (YYSTYPE * yylval_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 100 "scanner.l" + + +#line 869 "scanner.c" + + yylval = yylval_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + libconfig_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + libconfig_yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 103 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 204 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { + int yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + } + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 102 "scanner.l" +{ BEGIN COMMENT; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 103 "scanner.l" +{ BEGIN INITIAL; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 104 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 4: +/* rule 4 can match eol */ +YY_RULE_SETUP +#line 105 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 107 "scanner.l" +{ BEGIN STRING; } + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +#line 108 "scanner.l" +{ scanctx_append_string(yyextra, yytext); } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 109 "scanner.l" +{ scanctx_append_string(yyextra, "\n"); } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 110 "scanner.l" +{ scanctx_append_string(yyextra, "\r"); } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 111 "scanner.l" +{ scanctx_append_string(yyextra, "\t"); } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 112 "scanner.l" +{ scanctx_append_string(yyextra, "\f"); } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 113 "scanner.l" +{ scanctx_append_string(yyextra, "\\"); } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 114 "scanner.l" +{ scanctx_append_string(yyextra, "\""); } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 115 "scanner.l" +{ + char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF), + 0 }; + scanctx_append_string(yyextra, c); + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 120 "scanner.l" +{ + yylval->sval = scanctx_take_string(yyextra); + BEGIN INITIAL; + return(TOK_STRING); + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 126 "scanner.l" +{ BEGIN INCLUDE; } + YY_BREAK +case 16: +/* rule 16 can match eol */ +YY_RULE_SETUP +#line 127 "scanner.l" +{ scanctx_append_string(yyextra, yytext); } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 128 "scanner.l" +{ scanctx_append_string(yyextra, "\\"); } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 129 "scanner.l" +{ scanctx_append_string(yyextra, "\""); } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 130 "scanner.l" +{ + const char *error; + FILE *fp = scanctx_push_include(yyextra, + (void *)YY_CURRENT_BUFFER, + &error); + if(fp) + { + yyin = fp; + libconfig_yy_switch_to_buffer(libconfig_yy_create_buffer(yyin,YY_BUF_SIZE,yyscanner),yyscanner); + } + else + { + yyextra->config->error_text = error; + yyextra->config->error_file = scanctx_current_filename( + yyextra); + yyextra->config->error_line = libconfig_yyget_lineno( + yyscanner); + return TOK_ERROR; + } + BEGIN INITIAL; + } + YY_BREAK +case 20: +/* rule 20 can match eol */ +YY_RULE_SETUP +#line 154 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 155 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 157 "scanner.l" +{ return(TOK_EQUALS); } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 158 "scanner.l" +{ return(TOK_COMMA); } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 159 "scanner.l" +{ return(TOK_GROUP_START); } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 160 "scanner.l" +{ return(TOK_GROUP_END); } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 161 "scanner.l" +{ yylval->ival = 1; return(TOK_BOOLEAN); } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 162 "scanner.l" +{ yylval->ival = 0; return(TOK_BOOLEAN); } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 163 "scanner.l" +{ yylval->sval = yytext; return(TOK_NAME); } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 164 "scanner.l" +{ yylval->fval = atof(yytext); return(TOK_FLOAT); } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 165 "scanner.l" +{ yylval->ival = atoi(yytext); return(TOK_INTEGER); } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 166 "scanner.l" +{ yylval->llval = atoll(yytext); return(TOK_INTEGER64); } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 167 "scanner.l" +{ + yylval->ival = strtoul(yytext, NULL, 16); + return(TOK_HEX); + } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 171 "scanner.l" +{ yylval->llval = fromhex(yytext); return(TOK_HEX64); } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 172 "scanner.l" +{ return(TOK_ARRAY_START); } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 173 "scanner.l" +{ return(TOK_ARRAY_END); } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 174 "scanner.l" +{ return(TOK_LIST_START); } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 175 "scanner.l" +{ return(TOK_LIST_END); } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 176 "scanner.l" +{ return(TOK_SEMICOLON); } + YY_BREAK +case 39: +*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ +yyg->yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 177 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 178 "scanner.l" +{ return(TOK_GARBAGE); } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): +case YY_STATE_EOF(STRING): +case YY_STATE_EOF(INCLUDE): +#line 180 "scanner.l" +{ + YY_BUFFER_STATE buf = (YY_BUFFER_STATE)scanctx_pop_include( + yyextra); + if(buf) + { + libconfig_yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner); + libconfig_yy_switch_to_buffer(buf,yyscanner); + } + else + yyterminate(); + } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 191 "scanner.l" +ECHO; + YY_BREAK +#line 1227 "scanner.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * libconfig_yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( libconfig_yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of libconfig_yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + libconfig_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + libconfig_yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) libconfig_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 103 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 103 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 102); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + libconfig_yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( libconfig_yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); + if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void libconfig_yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + libconfig_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + libconfig_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + libconfig_yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * libconfig_yypop_buffer_state(); + * libconfig_yypush_buffer_state(new_buffer); + */ + libconfig_yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + libconfig_yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (libconfig_yywrap()) processing, but the only time this flag + * is looked at is after libconfig_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void libconfig_yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE libconfig_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) libconfig_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) libconfig_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + libconfig_yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with libconfig_yy_create_buffer() + * @param yyscanner The scanner object. + */ + void libconfig_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + libconfig_yyfree((void *) b->yy_ch_buf ,yyscanner ); + + libconfig_yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a libconfig_yyrestart() or at EOF. + */ + static void libconfig_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + libconfig_yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then libconfig_yy_init_buffer was _probably_ + * called from libconfig_yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void libconfig_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + libconfig_yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + libconfig_yyensure_buffer_stack(yyscanner); + + /* This block is copied from libconfig_yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from libconfig_yy_switch_to_buffer. */ + libconfig_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void libconfig_yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + libconfig_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + libconfig_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void libconfig_yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)libconfig_yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)libconfig_yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE libconfig_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) libconfig_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + libconfig_yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to libconfig_yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * libconfig_yy_scan_bytes() instead. + */ +YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +{ + + return libconfig_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to libconfig_yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) libconfig_yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = libconfig_yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in libconfig_yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int libconfig_yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int libconfig_yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *libconfig_yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *libconfig_yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int libconfig_yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *libconfig_yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void libconfig_yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "libconfig_yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void libconfig_yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "libconfig_yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see libconfig_yy_switch_to_buffer + */ +void libconfig_yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void libconfig_yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int libconfig_yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void libconfig_yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void libconfig_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +/* User-visible API */ + +/* libconfig_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int libconfig_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) libconfig_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* libconfig_yylex_init_extra has the same functionality as libconfig_yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to libconfig_yyalloc in + * the yyextra field. + */ + +int libconfig_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + libconfig_yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) libconfig_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + libconfig_yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from libconfig_yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * libconfig_yylex_init() + */ + return 0; +} + +/* libconfig_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int libconfig_yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + libconfig_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + libconfig_yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + libconfig_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + libconfig_yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * libconfig_yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + libconfig_yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *libconfig_yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + return (void *) malloc( size ); +} + +void *libconfig_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void libconfig_yyfree (void * ptr , yyscan_t yyscanner) +{ + free( (char *) ptr ); /* see libconfig_yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 191 "scanner.l" diff --git a/src/3rdparty/libconfig/scanner.h b/src/3rdparty/libconfig/scanner.h new file mode 100644 index 0000000..baa6f77 --- /dev/null +++ b/src/3rdparty/libconfig/scanner.h @@ -0,0 +1,326 @@ +#ifndef libconfig_yyHEADER_H +#define libconfig_yyHEADER_H 1 +#define libconfig_yyIN_HEADER 1 + +#line 6 "scanner.h" + +#line 8 "scanner.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 33 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +int libconfig_yylex_init (yyscan_t* scanner); + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void libconfig_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void libconfig_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void libconfig_yypop_buffer_state (yyscan_t yyscanner ); + +YY_BUFFER_STATE libconfig_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *libconfig_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *libconfig_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void libconfig_yyfree (void * ,yyscan_t yyscanner ); + +#define libconfig_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define COMMENT 1 + +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int libconfig_yylex_destroy (yyscan_t yyscanner ); + +int libconfig_yyget_debug (yyscan_t yyscanner ); + +void libconfig_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner ); + +void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_in (yyscan_t yyscanner ); + +void libconfig_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_out (yyscan_t yyscanner ); + +void libconfig_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int libconfig_yyget_leng (yyscan_t yyscanner ); + +char *libconfig_yyget_text (yyscan_t yyscanner ); + +int libconfig_yyget_lineno (yyscan_t yyscanner ); + +void libconfig_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner ); + +void libconfig_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int libconfig_yywrap (yyscan_t yyscanner ); +#else +extern int libconfig_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int libconfig_yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner); + +#define YY_DECL int libconfig_yylex (YYSTYPE * yylval_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#line 130 "scanner.l" + +#line 325 "scanner.h" +#undef libconfig_yyIN_HEADER +#endif /* libconfig_yyHEADER_H */ diff --git a/src/3rdparty/libconfig/strbuf.c b/src/3rdparty/libconfig/strbuf.c new file mode 100644 index 0000000..f7f48d3 --- /dev/null +++ b/src/3rdparty/libconfig/strbuf.c @@ -0,0 +1,58 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#include "strbuf.h" + +#include +#include + +#define STRING_BLOCK_SIZE 64 + +/* ------------------------------------------------------------------------- */ + +char *strbuf_release(strbuf_t *buf) +{ + char *r = buf->string; + memset(buf, 0, sizeof(strbuf_t)); + return(r); +} + +/* ------------------------------------------------------------------------- */ + +void strbuf_append(strbuf_t *buf, const char *text) +{ + static const size_t mask = ~(STRING_BLOCK_SIZE - 1); + size_t len = strlen(text); + size_t newlen = buf->length + len + 1; /* add 1 for NUL */ + + if(newlen > buf->capacity) + { + buf->capacity = (newlen + (STRING_BLOCK_SIZE - 1)) & mask; + buf->string = (char *)realloc(buf->string, buf->capacity); + } + + strcpy(buf->string + buf->length, text); + buf->length += len; +} + +/* ------------------------------------------------------------------------- */ +/* eof */ diff --git a/src/3rdparty/libconfig/strbuf.h b/src/3rdparty/libconfig/strbuf.h new file mode 100644 index 0000000..62cd782 --- /dev/null +++ b/src/3rdparty/libconfig/strbuf.h @@ -0,0 +1,40 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_strbuf_h +#define __libconfig_strbuf_h + +#include +#include + +typedef struct +{ + char *string; + size_t length; + size_t capacity; +} strbuf_t; + +char *strbuf_release(strbuf_t *buf); + +void strbuf_append(strbuf_t *buf, const char *text); + +#endif /* __libconfig_strbuf_h */ diff --git a/src/3rdparty/libconfig/wincompat.h b/src/3rdparty/libconfig/wincompat.h new file mode 100644 index 0000000..23d7379 --- /dev/null +++ b/src/3rdparty/libconfig/wincompat.h @@ -0,0 +1,90 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + . + ---------------------------------------------------------------------------- +*/ + +#ifndef __wincompat_h +#define __wincompat_h + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +#ifdef _MSC_VER +#pragma warning (disable: 4996) +#endif + +#define WIN32_LEAN_AND_MEAN +#include + +#define snprintf _snprintf + +#ifndef __MINGW32__ +#define atoll _atoi64 +#define strtoull _strtoui64 +#endif /* __MINGW32__ */ + +#endif + +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(__MINGW32__)) + +/* Why does gcc on MinGW use the Visual C++ style format directives + * for 64-bit integers? Inquiring minds want to know.... + */ + +#define INT64_FMT "%I64d" +#define UINT64_FMT "%I64u" + +#define INT64_HEX_FMT "%I64X" + +#define FILE_SEPARATOR "\\" + +#else /* defined(WIN32) || defined(__MINGW32__) */ + +#define INT64_FMT "%lld" +#define UINT64_FMT "%llu" + +#define INT64_HEX_FMT "%llX" + +#define FILE_SEPARATOR "/" + +#endif /* defined(WIN32) || defined(__MINGW32__) */ + +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ + && ! defined(__MINGW32__) + +#define INT64_CONST(I) (I ## i64) +#define UINT64_CONST(I) (I ## Ui64) + +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif + +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif + +#else /* defined(WIN32) && ! defined(__MINGW32__) */ + +#define INT64_CONST(I) (I ## LL) +#define UINT64_CONST(I) (I ## ULL) + +#endif /* defined(WIN32) && ! defined(__MINGW32__) */ + +#endif /* __wincompat_h */ diff --git a/src/libopentld/CMakeLists.txt b/src/libopentld/CMakeLists.txt new file mode 100644 index 0000000..ecddce3 --- /dev/null +++ b/src/libopentld/CMakeLists.txt @@ -0,0 +1,33 @@ +include_directories(imacq + tld + ${CF_HEADER_DIRS} + ${OpenCV_INCLUDE_DIRS}) + +link_directories(${OpenCV_LIB_DIR}) + +add_library(libopentld + ${CF_SOURCES} + imacq/ImAcq.cpp + tld/Clustering.cpp + tld/DetectionResult.cpp + tld/DetectorCascade.cpp + tld/EnsembleClassifier.cpp + tld/NNClassifier.cpp + tld/TLD.cpp + tld/TLDUtil.cpp + tld/VarianceFilter.cpp + imacq/ImAcq.h + tld/Clustering.h + tld/DetectionResult.h + tld/DetectorCascade.h + tld/EnsembleClassifier.h + tld/IntegralImage.h + tld/NNClassifier.h + tld/NormalizedPatch.h + tld/TLD.h + tld/TLDUtil.h + tld/VarianceFilter.h) + +target_link_libraries(libopentld ${OpenCV_LIBS}) + +set_target_properties(libopentld PROPERTIES OUTPUT_NAME opentld) diff --git a/src/libopentld/CMakeLists2.txt b/src/libopentld/CMakeLists2.txt new file mode 100644 index 0000000..73b0a9e --- /dev/null +++ b/src/libopentld/CMakeLists2.txt @@ -0,0 +1,30 @@ +include_directories(imacq + tld + ${CF_HEADER_DIRS} + ${OpenCV_INCLUDE_DIRS}) + +link_directories(${OpenCV_LIB_DIR}) + +add_library(libopentld + ${CF_SOURCES} + tld/Clustering.cpp + tld/DetectionResult.cpp + tld/DetectorCascade.cpp + tld/EnsembleClassifier.cpp + tld/NNClassifier.cpp + tld/TLD.cpp + tld/TLDUtil.cpp + tld/VarianceFilter.cpp + tld/Clustering.h + tld/DetectionResult.h + tld/DetectorCascade.h + tld/EnsembleClassifier.h + tld/IntegralImage.h + tld/NNClassifier.h + tld/NormalizedPatch.h + tld/TLD.h + tld/TLDUtil.h + tld/VarianceFilter.h) + +target_link_libraries(libopentld ${OpenCV_LIBS}) + diff --git a/src/libopentld/imacq/ImAcq.cpp b/src/libopentld/imacq/ImAcq.cpp new file mode 100644 index 0000000..29c9596 --- /dev/null +++ b/src/libopentld/imacq/ImAcq.cpp @@ -0,0 +1,279 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#include "ImAcq.h" + +#include + +#include +#include + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) +#include +#else +#include +#endif + +static void msleep(int milliseconds) +{ +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) + Sleep(milliseconds); +#else + usleep(static_cast(milliseconds)*1000); +#endif +} + +ImAcq *imAcqAlloc() +{ + ImAcq *imAcq = (ImAcq *)malloc(sizeof(ImAcq)); + imAcq->method = IMACQ_CAM; + imAcq->currentFrame = 1; + imAcq->lastFrame = 0; + imAcq->camNo = 0; + imAcq->fps = 24; + return imAcq; +} + +void imAcqInit(ImAcq *imAcq) +{ + if (imAcq->method == IMACQ_CAM) + { + imAcq->capture = cvCaptureFromCAM(imAcq->camNo); + + if (imAcq->capture == NULL) + { + printf("Error: Unable to initialize camera\n"); + exit(0); + } + } + else if (imAcq->method == IMACQ_VID) + { + imAcq->capture = cvCaptureFromAVI(imAcq->imgPath); + + if (imAcq->capture == NULL) + { + printf("Error: Unable to open video\n"); + exit(0); + } + + // take all frames + if (imAcq->lastFrame == 0) + imAcq->lastFrame = imAcqVidGetNumberOfFrames(imAcq); //This sometimes returns garbage + + // lastFrame out of bounds + if (imAcq->lastFrame > imAcqVidGetNumberOfFrames(imAcq)) + { + printf("Error: video has only %d frames you selected %d as last frame.\n", + imAcqVidGetNumberOfFrames(imAcq), imAcq->lastFrame); + exit(1); + } + + // something is wrong with startFrame and/or lastFrame + if ((imAcq->lastFrame < 1) || (imAcq->currentFrame < 1) || ((imAcq->currentFrame > imAcq->lastFrame))) + { + printf("Error: something is wrong with the start and last frame number. startFrame: %d lastFrame: %d\n", + imAcq->currentFrame, imAcq->lastFrame); + exit(1); + } + + // set the video position to the correct frame + //This produces strange results on some videos and is deactivated for now. + //imAcqVidSetNextFrameNumber(imAcq, imAcq->currentFrame); + } + else if (imAcq->method == IMACQ_STREAM) + { + imAcq->capture = cvCaptureFromFile(imAcq->imgPath); + + if (imAcq->capture == NULL) + { + printf("Error: Unable to open video\n"); + exit(0); + } + } + + imAcq->startFrame = imAcq->currentFrame; + imAcq->startTime = cvGetTickCount(); +} + +void imAcqFree(ImAcq *imAcq) +{ + if ((imAcq->method == IMACQ_CAM) || (imAcq->method == IMACQ_VID) || (imAcq->method == IMACQ_STREAM)) + { + cvReleaseCapture(&imAcq->capture); + } + + free(imAcq); +} + +IplImage *imAcqLoadImg(ImAcq *imAcq, char *path) +{ + IplImage *image = cvLoadImage(path); + + if (image == NULL) + { + printf("Error: %s does not exist or is not an image.\n", path); + } + + return image; +} + +IplImage *imAcqLoadFrame(ImAcq *imAcq, int fNo) +{ + char path[255]; + sprintf(path, imAcq->imgPath, fNo); + + return cvLoadImage(path); +} + +IplImage *imAcqLoadCurrentFrame(ImAcq *imAcq) +{ + return imAcqLoadFrame(imAcq, imAcq->currentFrame); +} + +IplImage *imAcqGetImgByCurrentTime(ImAcq *imAcq) +{ + //Calculate current image number + if ((imAcq->method == IMACQ_CAM) || (imAcq->method == IMACQ_STREAM)) + { + //printf("grabbing image from sensor"); + return imAcqGrab(imAcq->capture); + } + + float secondsPassed = static_cast((cvGetTickCount() - imAcq->startTime) / cvGetTickFrequency()); + secondsPassed = secondsPassed / 1000000; + + int framesPassed = static_cast(secondsPassed * imAcq->fps); + + int currentFrame = imAcq->startFrame + framesPassed; + + if (imAcq->lastFrame > 0 && currentFrame > imAcq->lastFrame) return NULL; + + return imAcqLoadFrame(imAcq, currentFrame); +} + +IplImage *imAcqGetImg(ImAcq *imAcq) +{ + IplImage *img = NULL; + + if (imAcq->method == IMACQ_CAM || imAcq->method == IMACQ_VID) + { + img = imAcqGrab(imAcq->capture); + } + + if (imAcq->method == IMACQ_IMGS) + { + img = imAcqLoadCurrentFrame(imAcq); + } + + if ((imAcq->method == IMACQ_LIVESIM) || (imAcq->method == IMACQ_STREAM)) + { + img = imAcqGetImgByCurrentTime(imAcq); + } + + imAcqAdvance(imAcq); + + return img; +} + +IplImage *imAcqGrab(CvCapture *capture) +{ + IplImage *frame; + + frame = cvQueryFrame(capture); + + if (frame == NULL) + { + // Sometimes the camera driver needs some time to start + // sleep 100ms and try again + for (int i = 0; i < 5; ++i) + { + printf("Error: Unable to grab image... retry\n"); + msleep(100); + frame = cvQueryFrame(capture); + if (frame != NULL) + { + break; + } + } + if (frame == NULL) + { + exit(-1); + } + } + + return cvCloneImage(frame); +} + +IplImage *imAcqGetImgByFrame(ImAcq *imAcq, int fNo) +{ + int oldFNo = imAcq->currentFrame; + imAcq->currentFrame = fNo; + + IplImage *img = imAcqGetImg(imAcq); + + imAcq->currentFrame = oldFNo; + + return img; +} + +IplImage *imAcqGetImgAndAdvance(ImAcq *imAcq) +{ + IplImage *img = imAcqGetImg(imAcq); + imAcq->currentFrame++; + + return img; +} + +void imAcqAdvance(ImAcq *imAcq) +{ + imAcq->currentFrame++; +} + +int imAcqHasMoreFrames(ImAcq *imAcq) +{ + if (imAcq->lastFrame < 1) return 1; + + if (imAcq->currentFrame > imAcq->lastFrame) + { + return 0; + } + else + { + return 1; + } +} + +int imAcqVidGetNextFrameNumber(ImAcq *imAcq) +{ + // OpenCV index starts with 0 + // maybe a OpenCV bug: cvGetCaptureProperty with CV_CAP_PROP_POS_FRAMES returns the LAST + // frame number to be encoded not the NEXT + return ((int)cvGetCaptureProperty(imAcq->capture, CV_CAP_PROP_POS_FRAMES)) + 2; +} + +void imAcqVidSetNextFrameNumber(ImAcq *imAcq, int nFrame) +{ + // OpenCV index starts with 0 + cvSetCaptureProperty(imAcq->capture, CV_CAP_PROP_POS_FRAMES, nFrame - 2.0); +} + +int imAcqVidGetNumberOfFrames(ImAcq *imAcq) +{ + return ((int)cvGetCaptureProperty(imAcq->capture, CV_CAP_PROP_FRAME_COUNT)); +} diff --git a/src/libopentld/imacq/ImAcq.h b/src/libopentld/imacq/ImAcq.h new file mode 100644 index 0000000..6939afc --- /dev/null +++ b/src/libopentld/imacq/ImAcq.h @@ -0,0 +1,80 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * imAcq.h + * + * Created on: 18 May 2011 + * Author: Georg Nebehaiy + * Modified on: 26th May 2013 + * By: Jonathan Senecal + */ + +#ifndef IMACQ_IMPL_H_ +#define IMACQ_IMPL_H_ + +#include + +/** + * Capturing method + */ +enum ImacqMethod +{ + IMACQ_IMGS, //!< Images + IMACQ_CAM, //!< Camera + IMACQ_VID, //!< Video + IMACQ_LIVESIM, //!< Livesim + IMACQ_STREAM //!< Stream +}; + +typedef struct +{ + int method; + const char *imgPath; + CvCapture *capture; + int lastFrame; + int currentFrame; + int startFrame; + int camNo; + int64 startTime; + float fps; +} ImAcq; + +ImAcq *imAcqAlloc(); + +void imAcqInit(ImAcq *imAcq); + +void imAcqRelease(ImAcq *imAcq); + +void imAcqVidSetNextFrameNumber(ImAcq *imAcq, int nFrame); +int imAcqVidGetNextFrameNumber(ImAcq *imAcq); +int imAcqVidGetNumberOfFrames(ImAcq *imAcq); +int imAcqHasMoreFrames(ImAcq *imAcq); +IplImage *imAcqGetImgAndAdvance(ImAcq *imAcq); +IplImage *imAcqGetImg(ImAcq *imAcq); +IplImage *imAcqGetImgByFrame(ImAcq *imAcq, int fNo); +IplImage *imAcqGetImgByCurrentTime(ImAcq *imAcq); +IplImage *imAcqLoadImg(ImAcq *imAcq, char *path); +IplImage *imAcqLoadCurrentFrame(ImAcq *imAcq); +IplImage *imAcqLoadVidFrame(CvCapture *capture); +IplImage *imAcqGrab(CvCapture *capture); +void imAcqAdvance(ImAcq *imAcq); +void imAcqFree(ImAcq *); + +#endif /* IMACQ_H_ */ diff --git a/src/libopentld/tld/Clustering.cpp b/src/libopentld/tld/Clustering.cpp new file mode 100644 index 0000000..c9fe348 --- /dev/null +++ b/src/libopentld/tld/Clustering.cpp @@ -0,0 +1,257 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * Clustering.cpp + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#include "Clustering.h" + +#include "TLDUtil.h" +#include "DetectorCascade.h" + +using namespace cv; + +namespace tld +{ + Clustering::Clustering() : + cutoff(0.5f), + windows(NULL), + numWindows(0) + { + } + + Clustering::~Clustering() + { + } + + void Clustering::release() + { + windows = NULL; + numWindows = 0; + } + + void Clustering::calcMeanRect(std::vector * indices) + { + float x, y, w, h; + x = y = w = h = 0; + + size_t numIndices = indices->size(); + + for (int i = 0; i < numIndices; i++) + { + int *bb = &windows[TLD_WINDOW_SIZE * indices->at(i)]; + x += bb[0]; + y += bb[1]; + w += bb[2]; + h += bb[3]; + } + + x /= numIndices; + y /= numIndices; + w /= numIndices; + h /= numIndices; + + Rect *rect = new Rect(); + detectionResult->detectorBB = rect; + rect->x = static_cast(floor(x + 0.5)); + rect->y = static_cast(floor(y + 0.5)); + rect->width = static_cast(floor(w + 0.5)); + rect->height = static_cast(floor(h + 0.5)); + } + + //distances must be of size n*(n+1)/2 + void Clustering::calcDistances(float *distances) + { + float *distances_tmp = distances; + + std::vector confidentIndices = *detectionResult->confidentIndices; + + size_t indices_size = confidentIndices.size(); + + for (size_t i = 0; i < confidentIndices.size(); i++) + { + int firstIndex = confidentIndices.at(0); + confidentIndices.erase(confidentIndices.begin()); + tldOverlapOne(windows, firstIndex, &confidentIndices, distances_tmp); + distances_tmp += indices_size - i - 1; + } + + for (size_t i = 0; i < indices_size * (indices_size - 1) / 2; i++) + { + distances[i] = 1 - distances[i]; + } + } + + void Clustering::clusterConfidentIndices() + { + size_t numConfidentIndices = detectionResult->confidentIndices->size(); + size_t numDistances = numConfidentIndices * (numConfidentIndices - 1) / 2; + float *distances = new float[numDistances]{}; + + calcDistances(distances); + cluster(distances); + + if (detectionResult->numClusters == 1) + { + calcMeanRect(detectionResult->confidentIndices); + //TODO: Take the maximum confidence as the result confidence. + } + + delete[]distances; + distances = NULL; + } + + void Clustering::cluster(float *distances) + { + size_t numConfidentIndices = detectionResult->confidentIndices->size(); + + int *clusterIndices = new int[numConfidentIndices]; + + for (int i = 0; i < numConfidentIndices; i++) + clusterIndices[i] = -1; + + if (numConfidentIndices == 1) + { + clusterIndices[0] = 0; + detectionResult->numClusters = 1; + return; + } + + size_t numDistances = numConfidentIndices * (numConfidentIndices - 1) / 2; + + //Now: Cluster distances + int *distUsed = new int[numDistances]{}; + int newClusterIndex = 0; + int numClusters = 0; + + while (true) + { + //Search for the shortest distance + float shortestDist = -1.f; + int shortestDistIndex = -1; + int i1 = 0; + int i2 = 0; + int distIndex = 0; + + for (int i = 0; i < numConfidentIndices; i++) //Row index + { + for (int j = i + 1; j < numConfidentIndices; j++) //Start from i+1 + { + CV_Assert(distIndex < numDistances); + if (!distUsed[distIndex] && (shortestDistIndex == -1 || distances[distIndex] < shortestDist)) + { + shortestDist = distances[distIndex]; + shortestDistIndex = distIndex; + i1 = i; + i2 = j; + } + + distIndex++; + } + } + + if (shortestDistIndex == -1) + { + break; // We are done + } + + distUsed[shortestDistIndex] = 1; + + //Now: Compare the cluster indices + //If both have no cluster and distance is low, put them both to a new cluster + if (clusterIndices[i1] == -1 && clusterIndices[i2] == -1) + { + //If distance is short, put them to the same cluster + if (shortestDist < cutoff) + { + clusterIndices[i1] = clusterIndices[i2] = newClusterIndex; + newClusterIndex++; + numClusters++; + } + else //If distance is long, put them to different clusters + { + clusterIndices[i1] = newClusterIndex; + newClusterIndex++; + numClusters++; + clusterIndices[i2] = newClusterIndex; + newClusterIndex++; + numClusters++; + } + + //Second point is in cluster already + } + else if (clusterIndices[i1] == -1 && clusterIndices[i2] != -1) + { + if (shortestDist < cutoff) + { + clusterIndices[i1] = clusterIndices[i2]; + } + else //If distance is long, put them to different clusters + { + clusterIndices[i1] = newClusterIndex; + newClusterIndex++; + numClusters++; + } + } + else if (clusterIndices[i1] != -1 && clusterIndices[i2] == -1) + { + if (shortestDist < cutoff) + { + clusterIndices[i2] = clusterIndices[i1]; + } + else //If distance is long, put them to different clusters + { + clusterIndices[i2] = newClusterIndex; + newClusterIndex++; + numClusters++; + } + } + else //Both indices are in clusters already + { + if (clusterIndices[i1] != clusterIndices[i2] && shortestDist < cutoff) + { + //Merge clusters + + int oldClusterIndex = clusterIndices[i2]; + + for (int i = 0; i < numConfidentIndices; i++) + { + if (clusterIndices[i] == oldClusterIndex) + { + clusterIndices[i] = clusterIndices[i1]; + } + } + + numClusters--; + } + } + } + + detectionResult->numClusters = numClusters; + + delete[]distUsed; + distUsed = NULL; + delete[]clusterIndices; + clusterIndices = NULL; + } +} /* namespace tld */ diff --git a/src/libopentld/tld/Clustering.h b/src/libopentld/tld/Clustering.h new file mode 100644 index 0000000..24656dc --- /dev/null +++ b/src/libopentld/tld/Clustering.h @@ -0,0 +1,57 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * Clustering.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef CLUSTERING_H_ +#define CLUSTERING_H_ + +#include + +#include + +#include "DetectionResult.h" + +namespace tld +{ + class Clustering + { + void calcMeanRect(std::vector * indices); + void calcDistances(float *distances); + void cluster(float *distances); + public: + int *windows; + int numWindows; + + DetectionResult *detectionResult; + + //Configurable members + float cutoff; + + Clustering(); + virtual ~Clustering(); + void release(); + void clusterConfidentIndices(); + }; +} /* namespace tld */ +#endif /* CLUSTERING_H_ */ diff --git a/src/libopentld/tld/DetectionResult.cpp b/src/libopentld/tld/DetectionResult.cpp new file mode 100644 index 0000000..73ed2b5 --- /dev/null +++ b/src/libopentld/tld/DetectionResult.cpp @@ -0,0 +1,93 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * DetectionResult.cpp + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#include "DetectionResult.h" + +#include "TLDUtil.h" + +using namespace cv; +using namespace std; + +namespace tld +{ + DetectionResult::DetectionResult() + { + containsValidData = false; + fgList = new vector(); + confidentIndices = new vector(); + numClusters = 0; + detectorBB = NULL; + + variances = NULL; + posteriors = NULL; + featureVectors = NULL; + } + + DetectionResult::~DetectionResult() + { + release(); + delete fgList; + fgList = NULL; + } + + void DetectionResult::init(int numWindows, int numTrees) + { + variances = new float[numWindows]; + posteriors = new float[numWindows]; + featureVectors = new int[numWindows * numTrees]{}; + delete confidentIndices; + confidentIndices = new vector(); + } + + void DetectionResult::reset() + { + containsValidData = false; + + if (fgList != NULL) fgList->clear(); + + if (confidentIndices != NULL) confidentIndices->clear(); + + numClusters = 0; + delete detectorBB; + detectorBB = NULL; + } + + void DetectionResult::release() + { + fgList->clear(); + delete[] variances; + variances = NULL; + delete[] posteriors; + posteriors = NULL; + delete[] featureVectors; + featureVectors = NULL; + delete confidentIndices; + confidentIndices = NULL; + delete detectorBB; + detectorBB = NULL; + containsValidData = false; + } +} /* namespace tld */ diff --git a/src/libopentld/tld/DetectionResult.h b/src/libopentld/tld/DetectionResult.h new file mode 100644 index 0000000..1339e30 --- /dev/null +++ b/src/libopentld/tld/DetectionResult.h @@ -0,0 +1,57 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * DetectionResult.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef DETECTIONRESULT_H_ +#define DETECTIONRESULT_H_ + +#include + +#include + +namespace tld +{ + class DetectionResult + { + public: + bool containsValidData; + std::vector* fgList; + float *posteriors; /* Contains the posteriors for each slding window. Is of size numWindows. Allocated by tldInitClassifier. */ + std::vector* confidentIndices; + int *featureVectors; + float *variances; + int numClusters; + cv::Rect *detectorBB; //Contains a valid result only if numClusters = 1 + + DetectionResult(); + virtual ~DetectionResult(); + + void init(int numWindows, int numTrees); + + void reset(); + void release(); + }; +} /* namespace tld */ +#endif /* DETECTIONRESULT_H_ */ diff --git a/src/libopentld/tld/DetectorCascade.cpp b/src/libopentld/tld/DetectorCascade.cpp new file mode 100644 index 0000000..be7aada --- /dev/null +++ b/src/libopentld/tld/DetectorCascade.cpp @@ -0,0 +1,305 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * DetectorCascade.cpp + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#include "DetectorCascade.h" + +#include + +#include "TLDUtil.h" + +using namespace cv; + +namespace tld +{ + //TODO: Convert this to a function +#define sub2idx(x,y,imgWidthStep) ((int) (floor((x)+0.5) + floor((y)+0.5)*(imgWidthStep))) + + DetectorCascade::DetectorCascade() + { + objWidth = -1; //MUST be set before calling init + objHeight = -1; //MUST be set before calling init + useShift = 1; + imgHeight = -1; + imgWidth = -1; + + shift = 0.1f; + minScale = -10; + maxScale = 10; + minSize = 25; + imgWidthStep = -1; + + numTrees = 10; + numFeatures = 13; + + initialised = false; + + varianceFilter = new VarianceFilter(); + ensembleClassifier = new EnsembleClassifier(); + nnClassifier = new NNClassifier(); + clustering = new Clustering(); + + detectionResult = new DetectionResult(); + } + + DetectorCascade::~DetectorCascade() + { + release(); + + delete varianceFilter; + delete ensembleClassifier; + delete nnClassifier; + delete detectionResult; + delete clustering; + } + + void DetectorCascade::init(std::shared_ptr rng) + { + if (imgWidth == -1 || imgHeight == -1 || imgWidthStep == -1 || objWidth == -1 || objHeight == -1) + { + //printf("Error: Window dimensions not set\n"); //TODO: Convert this to exception + } + + initWindowsAndScales(); + initWindowOffsets(); + + propagateMembers(); + + ensembleClassifier->init(rng); + + initialised = true; + } + + //TODO: This is error-prone. Better give components a reference to DetectorCascade? + void DetectorCascade::propagateMembers() + { + detectionResult->init(numWindows, numTrees); + + varianceFilter->windowOffsets = windowOffsets; + ensembleClassifier->windowOffsets = windowOffsets; + ensembleClassifier->imgWidthStep = imgWidthStep; + ensembleClassifier->numScales = numScales; + ensembleClassifier->scales = scales; + ensembleClassifier->numFeatures = numFeatures; + ensembleClassifier->numTrees = numTrees; + nnClassifier->windows = windows; + clustering->windows = windows; + clustering->numWindows = numWindows; + + varianceFilter->detectionResult = detectionResult; + ensembleClassifier->detectionResult = detectionResult; + nnClassifier->detectionResult = detectionResult; + clustering->detectionResult = detectionResult; + } + + void DetectorCascade::release() + { + if (!initialised) + { + return; //Do nothing + } + + initialised = false; + + ensembleClassifier->release(); + nnClassifier->release(); + + clustering->release(); + + numWindows = 0; + numScales = 0; + + delete[] scales; + scales = NULL; + delete[] windows; + windows = NULL; + delete[] windowOffsets; + windowOffsets = NULL; + + objWidth = -1; + objHeight = -1; + + detectionResult->release(); + } + + void DetectorCascade::cleanPreviousData() + { + detectionResult->reset(); + } + + /* returns number of bounding boxes, bounding boxes, number of scales, scales + * bounding boxes are stored in an array of size 5*numBBs using the format + * scales are stored using the format + * + */ + void DetectorCascade::initWindowsAndScales() + { + int scanAreaX = 1; // It is important to start with 1/1, because the integral images aren't defined at pos(-1,-1) due to speed reasons + int scanAreaY = 1; + int scanAreaW = imgWidth - 1; + int scanAreaH = imgHeight - 1; + + int windowIndex = 0; + + scales = new Size[maxScale - minScale + 1]{}; + + numWindows = 0; + + int scaleIndex = 0; + + for (int i = minScale; i <= maxScale; i++) + { + float scale = pow(1.2f, i); + int w = static_cast(objWidth * scale); + int h = static_cast(objHeight * scale); + int ssw, ssh; + + if (useShift) + { + ssw = static_cast(max(1, w * shift)); + ssh = static_cast(max(1, h * shift)); + } + else + { + ssw = 1; + ssh = 1; + } + + if (w < minSize || h < minSize || w > scanAreaW + || h > scanAreaH) + continue; + + scales[scaleIndex].width = w; + scales[scaleIndex].height = h; + + scaleIndex++; + + numWindows += static_cast(floor((float)(scanAreaW - w + ssw) / ssw) * floor((float)(scanAreaH - h + ssh) / ssh)); + } + + numScales = scaleIndex; + + windows = new int[TLD_WINDOW_SIZE * numWindows]{}; + + for (scaleIndex = 0; scaleIndex < numScales; scaleIndex++) + { + int w = scales[scaleIndex].width; + int h = scales[scaleIndex].height; + + int ssw, ssh; + + if (useShift) + { + ssw = static_cast(max(1, w * shift)); + ssh = static_cast(max(1, h * shift)); + } + else + { + ssw = 1; + ssh = 1; + } + + for (int y = scanAreaY; y + h <= scanAreaY + scanAreaH; y += ssh) + { + for (int x = scanAreaX; x + w <= scanAreaX + scanAreaW; x += ssw) + { + int *bb = &windows[TLD_WINDOW_SIZE * windowIndex]; + tldCopyBoundaryToArray(x, y, w, h, bb); + bb[4] = scaleIndex; + + windowIndex++; + } + } + } + + assert(windowIndex == numWindows); + } + + //Creates offsets that can be added to bounding boxes + //offsets are contained in the form delta11, delta12,... (combined index of dw and dh) + //Order: scale->tree->feature + void DetectorCascade::initWindowOffsets() + { + windowOffsets = new int[TLD_WINDOW_OFFSET_SIZE * numWindows]{}; + int *off = windowOffsets; + + int windowSize = TLD_WINDOW_SIZE; + + for (int i = 0; i < numWindows; i++) + { + int *window = windows + windowSize * i; + *off++ = sub2idx(window[0] - 1, window[1] - 1, imgWidthStep); // x1-1,y1-1 + *off++ = sub2idx(window[0] - 1, window[1] + window[3] - 1, imgWidthStep); // x1-1,y2 + *off++ = sub2idx(window[0] + window[2] - 1, window[1] - 1, imgWidthStep); // x2,y1-1 + *off++ = sub2idx(window[0] + window[2] - 1, window[1] + window[3] - 1, imgWidthStep); // x2,y2 + *off++ = window[4] * 2 * numFeatures * numTrees; // pointer to features for this scale + *off++ = window[2] * window[3]; //Area of bounding box + } + } + + void DetectorCascade::detect(const Mat &img) + { + //For every bounding box, the output is confidence, pattern, variance + + detectionResult->reset(); + + if (!initialised) + { + return; + } + + //Prepare components + varianceFilter->nextIteration(img); //Calculates integral images + ensembleClassifier->nextIteration(img); + +#pragma omp parallel for + for (int i = 0; i < numWindows; ++i) + { + if (!varianceFilter->filter(i)) + { + detectionResult->posteriors[i] = 0; + continue; + } + + if (!ensembleClassifier->filter(i)) + { + continue; + } + + if (!nnClassifier->filter(img, i)) + { + continue; + } + +#pragma omp critical + detectionResult->confidentIndices->push_back(i); + } + + //Cluster + clustering->clusterConfidentIndices(); + + detectionResult->containsValidData = true; + } +} /* namespace tld */ diff --git a/src/libopentld/tld/DetectorCascade.h b/src/libopentld/tld/DetectorCascade.h new file mode 100644 index 0000000..9a19ce7 --- /dev/null +++ b/src/libopentld/tld/DetectorCascade.h @@ -0,0 +1,93 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * DetectorCascade.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef DETECTORCASCADE_H_ +#define DETECTORCASCADE_H_ + +#include "DetectionResult.h" +#include "VarianceFilter.h" +#include "EnsembleClassifier.h" +#include "Clustering.h" +#include "NNClassifier.h" + +namespace tld +{ + //Constants + static const int TLD_WINDOW_SIZE = 5; + static const int TLD_WINDOW_OFFSET_SIZE = 6; + + class DetectorCascade + { + //Working data + int numScales; + cv::Size *scales; + public: + //Configurable members + int minScale; + int maxScale; + bool useShift; + float shift; + int minSize; + int numFeatures; + int numTrees; + + //Needed for init + int imgWidth; + int imgHeight; + int imgWidthStep; + int objWidth; + int objHeight; + + int numWindows; + int *windows; + int *windowOffsets; + + //State data + bool initialised; + + //Components of Detector Cascade + VarianceFilter *varianceFilter; + EnsembleClassifier *ensembleClassifier; + Clustering *clustering; + NNClassifier *nnClassifier; + + DetectionResult *detectionResult; + + void propagateMembers(); + + DetectorCascade(); + ~DetectorCascade(); + + void init(std::shared_ptr rng); + + void initWindowOffsets(); + void initWindowsAndScales(); + + void release(); + void cleanPreviousData(); + void detect(const cv::Mat &img); + }; +} /* namespace tld */ +#endif /* DETECTORCASCADE_H_ */ diff --git a/src/libopentld/tld/EnsembleClassifier.cpp b/src/libopentld/tld/EnsembleClassifier.cpp new file mode 100644 index 0000000..82174cb --- /dev/null +++ b/src/libopentld/tld/EnsembleClassifier.cpp @@ -0,0 +1,246 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * EnsembleClassifier.cpp + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#include "DetectorCascade.h" + +#include +#include +#include + +#include "EnsembleClassifier.h" + +using namespace std; +using namespace cv; + +namespace tld +{ + //TODO: Convert this to a function +#define sub2idx(x,y,widthstep) ((int) (floor((x)+0.5) + floor((y)+0.5)*(widthstep))) + + EnsembleClassifier::EnsembleClassifier() : + features(NULL), + featureOffsets(NULL), + posteriors(NULL), + positives(NULL), + negatives(NULL) + { + numTrees = 10; + numFeatures = 13; + enabled = true; + } + + EnsembleClassifier::~EnsembleClassifier() + { + release(); + } + + void EnsembleClassifier::init(std::shared_ptr rng) + { + numIndices = static_cast(pow(2.0f, numFeatures)); + + initFeatureLocations(rng); + initFeatureOffsets(); + initPosteriors(); + } + + void EnsembleClassifier::release() + { + if (features != NULL) + { + delete[] features; + features = NULL; + } + + if (featureOffsets != NULL) + { + delete[] featureOffsets; + featureOffsets = NULL; + } + + if (posteriors != NULL) + { + delete[] posteriors; + posteriors = NULL; + } + + if (positives != NULL) + { + delete[] positives; + positives = NULL; + } + + if (negatives != NULL) + { + delete[] negatives; + negatives = NULL; + } + } + + /* + * Generates random measurements in the format + */ + void EnsembleClassifier::initFeatureLocations(std::shared_ptr rng) + { + int size = 2 * 2 * numFeatures * numTrees; + std::uniform_real_distribution dist(0, 1); + features = new float[size]; + + for (int i = 0; i < size; i++) + { + features[i] = dist(*rng); + } + } + + //Creates offsets that can be added to bounding boxes + //offsets are contained in the form delta11, delta12,... (combined index of dw and dh) + //Order: scale.tree->feature + void EnsembleClassifier::initFeatureOffsets() + { + featureOffsets = new int[numScales * numTrees * numFeatures * 2]{}; + int *off = featureOffsets; + + for (int k = 0; k < numScales; k++) + { + Size scale = scales[k]; + + for (int i = 0; i < numTrees; i++) + { + for (int j = 0; j < numFeatures; j++) + { + float *currentFeature = features + (4 * numFeatures) * i + 4 * j; + *off++ = sub2idx((scale.width - 1) * currentFeature[0] + 1, (scale.height - 1) * currentFeature[1] + 1, imgWidthStep); //We add +1 because the index of the bounding box points to x-1, y-1 + *off++ = sub2idx((scale.width - 1) * currentFeature[2] + 1, (scale.height - 1) * currentFeature[3] + 1, imgWidthStep); + } + } + } + } + + void EnsembleClassifier::initPosteriors() + { + posteriors = new float[numTrees * numIndices]{}; + positives = new int[numTrees * numIndices]{}; + negatives = new int[numTrees * numIndices]{}; + } + + void EnsembleClassifier::nextIteration(const Mat &img) + { + if (!enabled) return; + + this->img = (const unsigned char *)img.data; + } + + //Classical fern algorithm + int EnsembleClassifier::calcFernFeature(int windowIdx, int treeIdx) + { + int index = 0; + int *bbox = windowOffsets + windowIdx * TLD_WINDOW_OFFSET_SIZE; + int *off = featureOffsets + bbox[4] + treeIdx * 2 * numFeatures; //bbox[4] is pointer to features for the current scale + + for (int i = 0; i < numFeatures; i++) + { + index <<= 1; + + int fp0 = img[bbox[0] + off[0]]; + int fp1 = img[bbox[0] + off[1]]; + + if (fp0 > fp1) + { + index |= 1; + } + + off += 2; + } + + return index; + } + + void EnsembleClassifier::calcFeatureVector(int windowIdx, int *featureVector) + { + for (int i = 0; i < numTrees; i++) + { + featureVector[i] = calcFernFeature(windowIdx, i); + } + } + + float EnsembleClassifier::calcConfidence(int *featureVector) + { + float conf = 0.0; + + for (int i = 0; i < numTrees; i++) + { + conf += posteriors[i * numIndices + featureVector[i]]; + } + + return conf; + } + + void EnsembleClassifier::classifyWindow(int windowIdx) + { + int *featureVector = detectionResult->featureVectors + numTrees * windowIdx; + calcFeatureVector(windowIdx, featureVector); + + detectionResult->posteriors[windowIdx] = calcConfidence(featureVector); + } + + bool EnsembleClassifier::filter(int i) + { + if (!enabled) return true; + + classifyWindow(i); + + if (detectionResult->posteriors[i] < 0.5) return false; + + return true; + } + + void EnsembleClassifier::updatePosterior(int treeIdx, int idx, int positive, int amount) + { + int arrayIndex = treeIdx * numIndices + idx; + (positive) ? positives[arrayIndex] += amount : negatives[arrayIndex] += amount; + posteriors[arrayIndex] = ((float)positives[arrayIndex]) / (positives[arrayIndex] + negatives[arrayIndex]) / (float)numTrees; + } + + void EnsembleClassifier::updatePosteriors(int *featureVector, int positive, int amount) + { + for (int i = 0; i < numTrees; i++) + { + int idx = featureVector[i]; + updatePosterior(i, idx, positive, amount); + } + } + + void EnsembleClassifier::learn(int *boundary, int positive, int *featureVector) + { + if (!enabled) return; + + float conf = calcConfidence(featureVector); + + //Update if positive patch and confidence < 0.5 or negative and conf > 0.5 + if ((positive && conf < 0.5) || (!positive && conf > 0.5)) + { + updatePosteriors(featureVector, positive, 1); + } + } +} /* namespace tld */ diff --git a/src/libopentld/tld/EnsembleClassifier.h b/src/libopentld/tld/EnsembleClassifier.h new file mode 100644 index 0000000..2d6b31d --- /dev/null +++ b/src/libopentld/tld/EnsembleClassifier.h @@ -0,0 +1,80 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * EnsembleClassifier.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef ENSEMBLECLASSIFIER_H_ +#define ENSEMBLECLASSIFIER_H_ + +#include +#include +#include + +namespace tld +{ + class EnsembleClassifier + { + const unsigned char *img; + + float calcConfidence(int *featureVector); + int calcFernFeature(int windowIdx, int treeIdx); + void calcFeatureVector(int windowIdx, int *featureVector); + void updatePosteriors(int *featureVector, int positive, int amount); + public: + bool enabled; + + //Configurable members + int numTrees; + int numFeatures; + + int imgWidthStep; + int numScales; + cv::Size *scales; + + int *windowOffsets; + int *featureOffsets; + float *features; + + int numIndices; + + float *posteriors; + int *positives; + int *negatives; + + DetectionResult *detectionResult; + + EnsembleClassifier(); + virtual ~EnsembleClassifier(); + void init(std::shared_ptr rng); + void initFeatureLocations(std::shared_ptr rng); + void initFeatureOffsets(); + void initPosteriors(); + void release(); + void nextIteration(const cv::Mat &img); + void classifyWindow(int windowIdx); + void updatePosterior(int treeIdx, int idx, int positive, int amount); + void learn(int *boundary, int positive, int *featureVector); + bool filter(int i); + }; +} /* namespace tld */ +#endif /* ENSEMBLECLASSIFIER_H_ */ diff --git a/src/libopentld/tld/IntegralImage.h b/src/libopentld/tld/IntegralImage.h new file mode 100644 index 0000000..a3a3b2c --- /dev/null +++ b/src/libopentld/tld/IntegralImage.h @@ -0,0 +1,78 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * IntegralImage.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef INTEGRALIMAGE_H_ +#define INTEGRALIMAGE_H_ + +#include + +namespace tld +{ + template + class IntegralImage + { + public: + T *data; /* Array containg the entries for the integral image in row-first manner. Of size width*height. Allocated by tldAllocIntImg */ + /* width, height: Dimensions of integral image.*/ + int width; + int height; + + IntegralImage(cv::Size size) + { + data = new T[size.width * size.height]; + } + + virtual ~IntegralImage() + { + delete[] data; + } + + void calcIntImg(const cv::Mat &img, bool squared = false) + { + const unsigned char *input = (const unsigned char *)(img.data); + T *output = data; + + for (int i = 0; i < img.cols; i++) + { + for (int j = 0; j < img.rows; j++) + { + T A = (i > 0) ? output[img.cols * j + i - 1] : 0; + T B = (j > 0) ? output[img.cols * (j - 1) + i] : 0; + T C = (j > 0 && i > 0) ? output[img.cols * (j - 1) + i - 1] : 0; + T value = input[img.step * j + i]; + + if (squared) + { + value = value * value; + } + + output[img.cols * j + i] = A + B - C + value; + } + } + } + }; +} /* namespace tld */ +#endif /* INTEGRALIMAGE_H_ */ diff --git a/src/libopentld/tld/NNClassifier.cpp b/src/libopentld/tld/NNClassifier.cpp new file mode 100644 index 0000000..9b8ee5d --- /dev/null +++ b/src/libopentld/tld/NNClassifier.cpp @@ -0,0 +1,190 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * NNClassifier.cpp + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#include "NNClassifier.h" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "DetectorCascade.h" +#include "TLDUtil.h" + +using namespace std; +using namespace cv; + +namespace tld +{ + NNClassifier::NNClassifier() + { + thetaFP = .5f; + thetaTP = .55f; + + truePositives = new vector(); + falsePositives = new vector(); + } + + NNClassifier::~NNClassifier() + { + release(); + + delete truePositives; + delete falsePositives; + } + + void NNClassifier::release() + { + falsePositives->clear(); + truePositives->clear(); + } + + float NNClassifier::ncc(float *f1, float *f2) + { + double corr = 0; + double norm1 = 0; + double norm2 = 0; + + int size = TLD_PATCH_SIZE * TLD_PATCH_SIZE; + + for (int i = 0; i < size; i++) + { + corr += f1[i] * f2[i]; + norm1 += f1[i] * f1[i]; + norm2 += f2[i] * f2[i]; + } + + // normalization to <0,1> + + return static_cast((corr / sqrt(norm1 * norm2) + 1) / 2.0); + } + + float NNClassifier::classifyPatch(NormalizedPatch *patch) + { + if (truePositives->empty()) + { + return 0; + } + + if (falsePositives->empty()) + { + return 1; + } + + float ccorr_max_p = 0; + + //Compare patch to positive patches + for (size_t i = 0; i < truePositives->size(); i++) + { + float ccorr = ncc(truePositives->at(i).values, patch->values); + + if (ccorr > ccorr_max_p) + { + ccorr_max_p = ccorr; + } + } + + float ccorr_max_n = 0; + + //Compare patch to negative patches + for (size_t i = 0; i < falsePositives->size(); i++) + { + float ccorr = ncc(falsePositives->at(i).values, patch->values); + + if (ccorr > ccorr_max_n) + { + ccorr_max_n = ccorr; + } + } + + float dN = 1 - ccorr_max_n; + float dP = 1 - ccorr_max_p; + + float distance = dN / (dN + dP); + return distance; + } + + float NNClassifier::classifyBB(const Mat &img, Rect *bb) + { + NormalizedPatch patch; + + tldExtractNormalizedPatchRect(img, bb, patch.values); + return classifyPatch(&patch); + } + + float NNClassifier::classifyWindow(const Mat &img, int windowIdx) + { + NormalizedPatch patch; + + int *bbox = &windows[TLD_WINDOW_SIZE * windowIdx]; + tldExtractNormalizedPatchBB(img, bbox, patch.values); + + return classifyPatch(&patch); + } + + void NNClassifier::showWindow(const Mat &img, int windowIdx) + { + NormalizedPatch patch; + + int *bbox = &windows[TLD_WINDOW_SIZE * windowIdx]; + tldExtractNormalizedPatchBB(img, bbox, patch.values); + Mat temp(TLD_PATCH_SIZE, TLD_PATCH_SIZE, CV_32F, patch.values); + normalize(temp, temp, 0, 1, cv::NORM_MINMAX); + resize(temp, temp, Size(0, 0), 5.0, 5.0); + imshow("NN positive detection", temp); + } + + bool NNClassifier::filter(const Mat &img, int windowIdx) + { + if (!enabled) return true; + + float conf = classifyWindow(img, windowIdx); + + if (conf < thetaTP) + { + return false; + } + //std::cout << "NN conf: " << conf << std::endl; + //showWindow(img, windowIdx); + return true; + } + + void NNClassifier::learn(vector patches) + { + //TODO: Randomization might be a good idea here + for (size_t i = 0; i < patches.size(); i++) + { + NormalizedPatch patch = patches[i]; + + float conf = classifyPatch(&patch); + + if (patch.positive && conf <= thetaTP) + { + truePositives->push_back(patch); + } + + if (!patch.positive && conf >= thetaFP) + { + falsePositives->push_back(patch); + } + } + } +} /* namespace tld */ diff --git a/src/libopentld/tld/NNClassifier.h b/src/libopentld/tld/NNClassifier.h new file mode 100644 index 0000000..e8f8807 --- /dev/null +++ b/src/libopentld/tld/NNClassifier.h @@ -0,0 +1,63 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * NNClassifier.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef NNCLASSIFIER_H_ +#define NNCLASSIFIER_H_ + +#include + +#include + +#include "NormalizedPatch.h" +#include "DetectionResult.h" + +namespace tld +{ + class NNClassifier + { + float ncc(float *f1, float *f2); + void showWindow(const cv::Mat &img, int windowIdx); + public: + bool enabled; + + int *windows; + float thetaFP; + float thetaTP; + DetectionResult *detectionResult; + std::vector* falsePositives; + std::vector* truePositives; + + NNClassifier(); + virtual ~NNClassifier(); + + void release(); + float classifyPatch(NormalizedPatch *patch); + float classifyBB(const cv::Mat &img, cv::Rect *bb); + float classifyWindow(const cv::Mat &img, int windowIdx); + void learn(std::vector patches); + bool filter(const cv::Mat &img, int windowIdx); + }; +} /* namespace tld */ +#endif /* NNCLASSIFIER_H_ */ diff --git a/src/libopentld/tld/NormalizedPatch.h b/src/libopentld/tld/NormalizedPatch.h new file mode 100644 index 0000000..7b926c4 --- /dev/null +++ b/src/libopentld/tld/NormalizedPatch.h @@ -0,0 +1,40 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * NormalizedPatch.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef NORMALIZEDPATCH_H_ +#define NORMALIZEDPATCH_H_ + +#define TLD_PATCH_SIZE 15 + +namespace tld +{ + class NormalizedPatch + { + public: + float values[TLD_PATCH_SIZE *TLD_PATCH_SIZE]; + bool positive; + }; +} /* namespace tld */ +#endif /* NORMALIZEDPATCH_H_ */ diff --git a/src/libopentld/tld/TLD.cpp b/src/libopentld/tld/TLD.cpp new file mode 100644 index 0000000..cb45474 --- /dev/null +++ b/src/libopentld/tld/TLD.cpp @@ -0,0 +1,418 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * TLD.cpp + * + * Created on: Nov 17, 2011 + * Author: Georg Nebehay + + * + Author: Klaus Haag + * * Replace Median Flow tracker with KCFcpp or DSSTcpp + * * Change to self-learning approach instead of semi-supervised + */ + +#include "TLD.h" +#include "opencv2/highgui/highgui.hpp" +#include +#include +#include "kcf_tracker.hpp" +#include "dsst_tracker.hpp" + +#include "NNClassifier.h" +#include "TLDUtil.h" + +using namespace std; +using namespace cv; +using namespace cf_tracking; + +namespace tld +{ + TLD::TLD() : + hasImageDimensions(false), + isTrackerValid(false), + runTracker(true), + tracker(0) + { + trackerEnabled = true; + detectorEnabled = true; + learningEnabled = true; + alternating = false; + valid = false; + learning = false; + currBB = NULL; + seed = 0; + detectorCascade = new DetectorCascade(); + nnClassifier = detectorCascade->nnClassifier; + } + + void TLD::init(bool useDsstTracker) + { + if (!tracker) + { + if (useDsstTracker) + { + DsstParameters dsstParameters; + dsstParameters.enableTrackingLossDetection = true; + tracker.reset(new DsstTracker(dsstParameters)); + } + else + { + KcfParameters kcfParameters; + kcfParameters.enableTrackingLossDetection = true; + tracker.reset(new KcfTracker(kcfParameters)); + } + } + + std::cout << "\n\n\n-----------CF_TLD---------------\n"; + std::cout << "---------- " << tracker->getId() << " --------------" << "\n\n\n"; + } + + TLD::~TLD() + { + storeCurrentData(); + deleteCurrentBB(); + + if (detectorCascade) + { + delete detectorCascade; + detectorCascade = NULL; + } + } + + void TLD::release() + { + detectorCascade->release(); + deleteCurrentBB(); + } + + void TLD::storeCurrentData() + { + isTrackerValid = false; + detectorCascade->cleanPreviousData(); //Reset detector results + } + + void TLD::selectObject(const Mat &img, Rect *bb) + { + if (!tracker) + return; + + if (!rng) + { + std::random_device rd; + std::shared_ptr g(new std::mt19937(rd())); + g->seed((unsigned long)seed); + rng = g; + } + + rng->seed((unsigned long)seed); + + Mat grayFrame; + cvtColor(img, grayFrame, CV_BGR2GRAY); + + // initialize the image dimensions once + if (!hasImageDimensions) + { + detectorCascade->imgWidth = grayFrame.cols; + detectorCascade->imgHeight = grayFrame.rows; + detectorCascade->imgWidthStep = static_cast(grayFrame.step); + } + + runTracker = true; + //Delete old object + detectorCascade->release(); + + detectorCascade->objWidth = bb->width; + detectorCascade->objHeight = bb->height; + + if (bb->height < detectorCascade->minSize) + detectorCascade->minSize = bb->height; + + if (bb->width < detectorCascade->minSize) + detectorCascade->minSize = bb->width; + + //Init detector cascade + detectorCascade->init(rng); + tracker->reinit(img, *bb); + + currImg = grayFrame; + deleteCurrentBB(); + currBB = tldCopyRect(bb); + currConf = 1; + valid = true; + + initialLearning(); + } + + void TLD::processImage(cv::Mat &img) + { + if (!tracker) + return; + + storeCurrentData(); + + Mat grayFrame; + cvtColor(img, grayFrame, CV_BGR2GRAY); + currImg = grayFrame; // Store new image , right after storeCurrentData(); + + if (trackerEnabled && runTracker) + { + isTrackerValid = tracker->update(img, trackerBB); + + if (!isTrackerValid) + runTracker = false; + } + + if (detectorEnabled && (!alternating || !isTrackerValid)) + detectorCascade->detect(grayFrame); + + fuseHypotheses(img); + + learn(); + } + + void TLD::fuseHypotheses(const Mat& colorImg) + { + int numClusters = detectorCascade->detectionResult->numClusters; + Rect *detectorBB = detectorCascade->detectionResult->detectorBB; + deleteCurrentBB(); + + currConf = 0; + valid = false; + + if (!detectorEnabled) + { + if (!isTrackerValid) + return; + + currBB = tldCopyRect(&trackerBB); + valid = true; + return; + } + + float confDetector = 0; + + if (numClusters == 1) + confDetector = nnClassifier->classifyBB(currImg, detectorBB); + + if (isTrackerValid) + { + float confTracker = nnClassifier->classifyBB(currImg, &trackerBB); + currBB = tldCopyRect(&trackerBB); + valid = true; + currConf = confTracker; + } + else if (numClusters == 1) + { + // reinit tracker + if (trackerEnabled) + { + if (tracker->updateAt(colorImg, *detectorBB)) + { + currConf = nnClassifier->classifyBB(currImg, detectorBB); + currBB = tldCopyRect(detectorBB); + valid = true; + runTracker = true; + } + else + { + deleteCurrentBB(); + currConf = 0; + valid = false; + } + } + } + } + + void TLD::initialLearning() + { + learning = true; //This is just for display purposes + + DetectionResult *detectionResult = detectorCascade->detectionResult; + + detectorCascade->detect(currImg); + + //This is the positive patch + NormalizedPatch initPatch; + tldExtractNormalizedPatchRect(currImg, currBB, initPatch.values); + initPatch.positive = 1; + + float initVar = tldCalcVariance(initPatch.values, TLD_PATCH_SIZE * TLD_PATCH_SIZE); + detectorCascade->varianceFilter->minVar = initVar / 2; + + float *overlap = new float[detectorCascade->numWindows]{}; + tldOverlapRect(detectorCascade->windows, detectorCascade->numWindows, currBB, overlap); + + //Add all bounding boxes with high overlap + vector< pair > positiveIndices; + vector negativeIndices; + + //First: Find overlapping positive and negative patches + for (int i = 0; i < detectorCascade->numWindows; i++) + { + if (overlap[i] > 0.7) + { + positiveIndices.push_back(pair(i, overlap[i])); + } + + if (overlap[i] < 0.2) + { + float variance = detectionResult->variances[i]; + + if (!detectorCascade->varianceFilter->enabled || variance > detectorCascade->varianceFilter->minVar) //TODO: This check is unnecessary if minVar would be set before calling detect. + { + negativeIndices.push_back(i); + } + } + } + + sort(positiveIndices.begin(), positiveIndices.end(), tldSortByOverlapDesc); + + vector patches; + + patches.push_back(initPatch); //Add first patch to patch list + + size_t numIterations = std::min(positiveIndices.size(), 10); //Take at most 10 bounding boxes (sorted by overlap) + + for (int i = 0; i < numIterations; i++) + { + int idx = positiveIndices.at(i).first; + //Learn this bounding box + //TODO: Somewhere here image warping might be possible + detectorCascade->ensembleClassifier->learn(&detectorCascade->windows[TLD_WINDOW_SIZE * idx], true, &detectionResult->featureVectors[detectorCascade->numTrees * idx]); + } + + std::shuffle(negativeIndices.begin(), negativeIndices.end(), *rng); + + //Choose 100 random patches for negative examples + for (size_t i = 0; i < std::min(100, negativeIndices.size()); i++) + { + int idx = negativeIndices.at(i); + + NormalizedPatch patch; + tldExtractNormalizedPatchBB(currImg, &detectorCascade->windows[TLD_WINDOW_SIZE * idx], patch.values); + patch.positive = 0; + patches.push_back(patch); + } + + detectorCascade->nnClassifier->learn(patches); + delete[] overlap; + } + + //Do this when current trajectory is valid + void TLD::learn() + { + if (!learningEnabled || !valid || !detectorEnabled) + { + learning = false; + return; + } + + learning = true; + + DetectionResult *detectionResult = detectorCascade->detectionResult; + + if (!detectionResult->containsValidData) + detectorCascade->detect(currImg); + + //This is the positive patch + NormalizedPatch patch; + tldExtractNormalizedPatchRect(currImg, currBB, patch.values); + + float *overlap = new float[detectorCascade->numWindows]{}; + tldOverlapRect(detectorCascade->windows, detectorCascade->numWindows, currBB, overlap); + + //Add all bounding boxes with high overlap + vector > positiveIndices; + vector negativeIndices; + vector negativeIndicesForNN; + + //First: Find overlapping positive and negative patches + + for (int i = 0; i < detectorCascade->numWindows; i++) + { + if (overlap[i] > 0.7) + { + positiveIndices.push_back(pair(i, overlap[i])); + } + + if (overlap[i] < 0.2) + { + if (!detectorCascade->ensembleClassifier->enabled || detectionResult->posteriors[i] > 0.5) //Should be 0.5 according to the paper + { + negativeIndices.push_back(i); + } + + if (!detectorCascade->ensembleClassifier->enabled || detectionResult->posteriors[i] > 0.5) + { + negativeIndicesForNN.push_back(i); + } + } + } + + sort(positiveIndices.begin(), positiveIndices.end(), tldSortByOverlapDesc); + + vector patches; + + patch.positive = 1; + patches.push_back(patch); + //TODO: Flip + + size_t numIterations = std::min(positiveIndices.size(), 10); //Take at most 10 bounding boxes (sorted by overlap) + + for (size_t i = 0; i < negativeIndices.size(); i++) + { + int idx = negativeIndices.at(i); + //TODO: Somewhere here image warping might be possible + detectorCascade->ensembleClassifier->learn(&detectorCascade->windows[TLD_WINDOW_SIZE * idx], false, &detectionResult->featureVectors[detectorCascade->numTrees * idx]); + } + + //TODO: Randomization might be a good idea + for (int i = 0; i < numIterations; i++) + { + int idx = positiveIndices.at(i).first; + //TODO: Somewhere here image warping might be possible + detectorCascade->ensembleClassifier->learn(&detectorCascade->windows[TLD_WINDOW_SIZE * idx], true, &detectionResult->featureVectors[detectorCascade->numTrees * idx]); + } + + for (size_t i = 0; i < negativeIndicesForNN.size(); i++) + { + int idx = negativeIndicesForNN.at(i); + + NormalizedPatch patch; + tldExtractNormalizedPatchBB(currImg, &detectorCascade->windows[TLD_WINDOW_SIZE * idx], patch.values); + patch.positive = 0; + patches.push_back(patch); + } + + detectorCascade->nnClassifier->learn(patches); + + //cout << "NN has now " << detectorCascade->nnClassifier->truePositives->size() << " positives and " << detectorCascade->nnClassifier->falsePositives->size() << " negatives.\n"; + + delete[] overlap; + } + + inline void TLD::deleteCurrentBB() + { + if (currBB) + { + delete currBB; + currBB = NULL; + } + } +} /* namespace tld */ diff --git a/src/libopentld/tld/TLD.h b/src/libopentld/tld/TLD.h new file mode 100644 index 0000000..1d9d82c --- /dev/null +++ b/src/libopentld/tld/TLD.h @@ -0,0 +1,76 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * TLD.h + * + * Created on: Nov 17, 2011 + * Author: Georg Nebehay + */ + +#ifndef TLD_H_ +#define TLD_H_ + +#include +#include +#include +#include "opencv2/core/core.hpp" +#include "cf_tracker.hpp" +#include "DetectorCascade.h" + +namespace tld +{ + class TLD + { + private: + void storeCurrentData(); + void fuseHypotheses(const cv::Mat& colorImg); + void learn(); + void initialLearning(); + void deleteCurrentBB(); + std::shared_ptr tracker; + public: + DetectorCascade *detectorCascade; + NNClassifier *nnClassifier; + cv::Mat currImg; + cv::Rect *currBB; + cv::Rect trackerBB; + bool valid; + bool isTrackerValid; + bool runTracker; + float currConf; + bool learning; + + bool hasImageDimensions; + bool trackerEnabled; + bool detectorEnabled; + bool learningEnabled; + bool alternating; + std::shared_ptr rng; + int seed; + + TLD(); + virtual ~TLD(); + void init(bool useDsstTracker); + void release(); + void selectObject(const cv::Mat &img, cv::Rect *bb); + void processImage(cv::Mat &img); + }; +} /* namespace tld */ +#endif /* TLD_H_ */ diff --git a/src/libopentld/tld/TLDUtil.cpp b/src/libopentld/tld/TLDUtil.cpp new file mode 100644 index 0000000..c0b5631 --- /dev/null +++ b/src/libopentld/tld/TLDUtil.cpp @@ -0,0 +1,227 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#include "TLDUtil.h" + +#include "NormalizedPatch.h" +#include "DetectorCascade.h" +#include "opencv2/imgproc/imgproc.hpp" + +using namespace std; +using namespace cv; + +namespace tld +{ + void tldRectToPoints(Rect rect, CvPoint *p1, CvPoint *p2) + { + p1->x = rect.x; + p1->y = rect.y; + p2->x = rect.x + rect.width; + p2->y = rect.y + rect.height; + } + + void tldBoundingBoxToPoints(int *bb, CvPoint *p1, CvPoint *p2) + { + p1->x = bb[0]; + p1->y = bb[1]; + p2->x = bb[0] + bb[2]; + p2->y = bb[1] + bb[3]; + } + + //Returns mean-normalized patch, image must be greyscale + void tldNormalizeImg(const Mat &img, float *output) + { + int size = TLD_PATCH_SIZE; + + Mat result; + resize(img, result, cvSize(size, size)); //Default is bilinear + + float mean = 0; + + unsigned char *imgData = (unsigned char *)result.data; + + for (int i = 0; i < 15; i++) + { + for (int j = 0; j < 15; j++) + { + mean += imgData[j * result.step + i]; + } + } + + mean /= size * size; + + for (int i = 0; i < size; i++) + { + for (int j = 0; j < size; j++) + { + output[j * 15 + i] = imgData[j * result.step + i] - mean; + } + } + } + + CvRect tldBoundaryToRect(int *boundary) + { + return Rect(boundary[0], boundary[1], boundary[2], boundary[3]); + } + + void tldExtractSubImage(const Mat &img, Mat &subImage, CvRect rect) + { + subImage = img(rect).clone(); + } + + void tldExtractSubImage(const Mat &img, Mat &subImage, int *boundary) + { + tldExtractSubImage(img, subImage, tldBoundaryToRect(boundary)); + } + + void tldExtractNormalizedPatch(const Mat &img, int x, int y, int w, int h, float *output) + { + Mat subImage; + tldExtractSubImage(img, subImage, Rect(x, y, w, h)); + tldNormalizeImg(subImage, output); + } + + //TODO: Rename + void tldExtractNormalizedPatchBB(const Mat &img, int *boundary, float *output) + { + int x, y, w, h; + tldExtractDimsFromArray(boundary, &x, &y, &w, &h); + tldExtractNormalizedPatch(img, x, y, w, h, output); + } + + void tldExtractNormalizedPatchRect(const Mat &img, Rect *rect, float *output) + { + tldExtractNormalizedPatch(img, rect->x, rect->y, rect->width, rect->height, output); + } + + float CalculateMean(float *value, int n) + { + float sum = 0; + + for (int i = 0; i < n; i++) + sum += value[i]; + + return (sum / n); + } + + float tldCalcVariance(float *value, int n) + { + float mean = CalculateMean(value, n); + float temp = 0; + + for (int i = 0; i < n; i++) + { + temp += (value[i] - mean) * (value[i] - mean); + } + + return temp / n; + } + + float tldBBOverlap(int *bb1, int *bb2) + { + if (bb1[0] > bb2[0] + bb2[2]) + { + return 0.0; + } + + if (bb1[1] > bb2[1] + bb2[3]) + { + return 0.0; + } + + if (bb1[0] + bb1[2] < bb2[0]) + { + return 0.0; + } + + if (bb1[1] + bb1[3] < bb2[1]) + { + return 0.0; + } + + int colInt = min(bb1[0] + bb1[2], bb2[0] + bb2[2]) - max(bb1[0], bb2[0]); + int rowInt = min(bb1[1] + bb1[3], bb2[1] + bb2[3]) - max(bb1[1], bb2[1]); + + int intersection = colInt * rowInt; + int area1 = bb1[2] * bb1[3]; + int area2 = bb2[2] * bb2[3]; + return intersection / (float)(area1 + area2 - intersection); + } + + void tldOverlapOne(int *windows, int index, vector * indices, float *overlap) + { + for (size_t i = 0; i < indices->size(); i++) + { + overlap[i] = tldBBOverlap(&windows[TLD_WINDOW_SIZE * index], &windows[TLD_WINDOW_SIZE * indices->at(i)]); + } + } + + float tldOverlapRectRect(Rect r1, Rect r2) + { + int bb1[4]; + int bb2[4]; + tldRectToArray(r1, bb1); + tldRectToArray(r2, bb2); + return tldBBOverlap(bb1, bb2); + } + + Rect *tldCopyRect(Rect *r) + { + Rect *r2 = new Rect(); + r2->x = r->x; + r2->y = r->y; + r2->width = r->width; + r2->height = r->height; + return r2; + } + + void tldOverlapRect(int *windows, int numWindows, Rect *boundary, float *overlap) + { + int bb[4]; + bb[0] = boundary->x; + bb[1] = boundary->y; + bb[2] = boundary->width; + bb[3] = boundary->height; + + tldOverlap(windows, numWindows, bb, overlap); + } + + void tldOverlap(int *windows, int numWindows, int *boundary, float *overlap) + { + for (int i = 0; i < numWindows; i++) + { + overlap[i] = tldBBOverlap(boundary, &windows[TLD_WINDOW_SIZE * i]); + } + } + + bool tldSortByOverlapDesc(pair bb1, pair bb2) + { + return bb1.second > bb2.second; + } + + //Checks whether bb1 is completely inside bb2 + int tldIsInside(int *bb1, int *bb2) + { + if (bb1[0] > bb2[0] && bb1[1] > bb2[1] && bb1[0] + bb1[2] < bb2[0] + bb2[2] && bb1[1] + bb1[3] < bb2[1] + bb2[3]) + { + return 1; + } + else return 0; + } +} /* End Namespace */ diff --git a/src/libopentld/tld/TLDUtil.h b/src/libopentld/tld/TLDUtil.h new file mode 100644 index 0000000..87a44e9 --- /dev/null +++ b/src/libopentld/tld/TLDUtil.h @@ -0,0 +1,117 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * util.h + * + * Created on: 30.05.2011 + * Author: Georg Nebehay + */ + +#ifndef TLDUTIL_H_ +#define TLDUTIL_H_ + +#include + +#include + +namespace tld +{ + template + void tldConvertBB(T1 *src, T2 *dest) + { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + } + + template + void tldCopyBB(T *src, T *dest) + { + tldConvertBB(src, dest); + } + + template + void tldCopyBoundaryToArray(T x, T y, T width, T height, T *array) + { + array[0] = x; + array[1] = y; + array[2] = width; + array[3] = height; + } + + template + void tldExtractDimsFromArray(T *boundary, T *x, T *y, T *width, T *height) + { + *x = boundary[0]; + *y = boundary[1]; + *width = boundary[2]; + *height = boundary[3]; + } + + template + void tldRectToArray(cv::Rect rect, T *boundary) + { + boundary[0] = rect.x; + boundary[1] = rect.y; + boundary[2] = rect.width; + boundary[3] = rect.height; + } + + template + cv::Rect tldArrayToRect(T *boundary) + { + cv::Rect rect; + rect.x = boundary[0]; + rect.y = boundary[1]; + rect.width = boundary[2]; + rect.height = boundary[3]; + + return rect; + } + + int tldIsInside(int *bb1, int *bb2); + void tldRectToPoints(CvRect rect, CvPoint *p1, CvPoint *p2); + void tldBoundingBoxToPoints(int *bb, CvPoint *p1, CvPoint *p2); + + void tldNormalizeImg(const cv::Mat &img, float *result, int size); + + void tldExtractNormalizedPatch(const cv::Mat &img, int x, int y, int w, int h, float *output); + void tldExtractNormalizedPatchBB(const cv::Mat &img, int *boundary, float *output); + void tldExtractNormalizedPatchRect(const cv::Mat &img, cv::Rect *rect, float *output); + void tldExtractSubImage(const cv::Mat &img, cv::Mat &subImage, int *boundary); + void tldExtractSubImage(const cv::Mat &img, cv::Mat &subImage, int x, int y, int w, int h); + + float tldCalcMean(float *value, int n); + float tldCalcVariance(float *value, int n); + + bool tldSortByOverlapDesc(std::pair bb1, std::pair bb2); + cv::Rect *tldCopyRect(cv::Rect *r); + + //TODO: Change function names + float tldOverlapRectRect(cv::Rect r1, cv::Rect r2); + void tldOverlapOne(int *windows, int index, std::vector * indices, float *overlap); + void tldOverlap(int *windows, int numWindows, int *boundary, float *overlap); + void tldOverlapRect(int *windows, int numWindows, cv::Rect *boundary, float *overlap); + + float tldCalcVariance(float *value, int n); + +#endif /* UTIL_H_ */ +} /* End Namespace */ diff --git a/src/libopentld/tld/VarianceFilter.cpp b/src/libopentld/tld/VarianceFilter.cpp new file mode 100644 index 0000000..3746f6c --- /dev/null +++ b/src/libopentld/tld/VarianceFilter.cpp @@ -0,0 +1,98 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * VarianceFilter.cpp + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#include "VarianceFilter.h" + +#include "IntegralImage.h" +#include "DetectorCascade.h" + +using namespace cv; + +namespace tld +{ + VarianceFilter::VarianceFilter() + { + enabled = true; + minVar = 0; + integralImg = NULL; + integralImg_squared = NULL; + } + + VarianceFilter::~VarianceFilter() + { + release(); + } + + void VarianceFilter::release() + { + if (integralImg != NULL) delete integralImg; + + integralImg = NULL; + + if (integralImg_squared != NULL) delete integralImg_squared; + + integralImg_squared = NULL; + } + + float VarianceFilter::calcVariance(int *off) + { + int *ii1 = integralImg->data; + long long *ii2 = integralImg_squared->data; + + float mX = (ii1[off[3]] - ii1[off[2]] - ii1[off[1]] + ii1[off[0]]) / (float)off[5]; //Sum of Area divided by area + float mX2 = (ii2[off[3]] - ii2[off[2]] - ii2[off[1]] + ii2[off[0]]) / (float)off[5]; + return mX2 - mX * mX; + } + + void VarianceFilter::nextIteration(const Mat &img) + { + if (!enabled) return; + + release(); + + integralImg = new IntegralImage(img.size()); + integralImg->calcIntImg(img); + + integralImg_squared = new IntegralImage(img.size()); + integralImg_squared->calcIntImg(img, true); + } + + bool VarianceFilter::filter(int i) + { + if (!enabled) return true; + + float bboxvar = calcVariance(windowOffsets + TLD_WINDOW_OFFSET_SIZE * i); + + detectionResult->variances[i] = bboxvar; + + if (bboxvar < minVar) + { + return false; + } + + return true; + } +} /* namespace tld */ diff --git a/src/libopentld/tld/VarianceFilter.h b/src/libopentld/tld/VarianceFilter.h new file mode 100644 index 0000000..7d5d9e8 --- /dev/null +++ b/src/libopentld/tld/VarianceFilter.h @@ -0,0 +1,58 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * VarianceFilter.h + * + * Created on: Nov 16, 2011 + * Author: Georg Nebehay + */ + +#ifndef VARIANCEFILTER_H_ +#define VARIANCEFILTER_H_ + +#include + +#include "IntegralImage.h" +#include "DetectionResult.h" + +namespace tld +{ + class VarianceFilter + { + IntegralImage* integralImg; + IntegralImage* integralImg_squared; + + public: + bool enabled; + int *windowOffsets; + + DetectionResult *detectionResult; + + float minVar; + + VarianceFilter(); + virtual ~VarianceFilter(); + + void release(); + void nextIteration(const cv::Mat &img); + bool filter(int idx); + float calcVariance(int *off); + }; +} /* namespace tld */ +#endif /* VARIANCEFILTER_H_ */ diff --git a/src/opentld/CMakeLists.txt b/src/opentld/CMakeLists.txt new file mode 100644 index 0000000..07260ca --- /dev/null +++ b/src/opentld/CMakeLists.txt @@ -0,0 +1,43 @@ + +link_directories(${OpenCV_LIB_DIR}) + +include_directories(main + ../libopentld/imacq + ../libopentld/mftracker + ../libopentld/tld + ${CF_HEADER_DIRS} + ${OpenCV_INCLUDE_DIRS}) + +if(NOT USE_SYSTEM_LIBS) + include_directories(../3rdparty/libconfig) +endif(NOT USE_SYSTEM_LIBS) + +#------------------------------------------------------------------------------- +# main +add_library(main + main/Config.cpp + main/Gui.cpp + main/Main.cpp + main/Settings.cpp + main/Trajectory.cpp + main/Config.h + main/Gui.h + main/Main.h + main/Settings.h + main/Trajectory.h + ../3rdparty/cf_tracking/src/cf_libs/common/cf_tracker.hpp) + +target_link_libraries(main libopentld config++ ${OpenCV_LIBS}) + +#------------------------------------------------------------------------------- +# opentld +add_executable(cftld + OpenTLD.cpp) + +target_link_libraries(cftld main libopentld config++ ${OpenCV_LIBS}) + +install(TARGETS cftld DESTINATION bin) + +#------------------------------------------------------------------------------- + + diff --git a/src/opentld/OpenTLD.cpp b/src/opentld/OpenTLD.cpp new file mode 100644 index 0000000..5026cd6 --- /dev/null +++ b/src/opentld/OpenTLD.cpp @@ -0,0 +1,67 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/** + * @author Georg Nebehay + */ + +#include "Main.h" +#include "Config.h" +#include "ImAcq.h" +#include "Gui.h" +#include + +using tld::Config; +using tld::Gui; +using tld::Settings; + +int main(int argc, char **argv) +{ + Main *main = new Main(); + Config config; + ImAcq *imAcq = imAcqAlloc(); + Gui *gui = new Gui(); + + main->gui = gui; + main->imAcq = imAcq; + + if (config.init(argc, argv) == PROGRAM_EXIT) + { + return EXIT_FAILURE; + } + + config.configure(main); + + main->tld->seed = main->seed; + imAcqInit(imAcq); + + if (main->showOutput) + { + gui->init(); + } + + main->doWork(); + + delete main; + main = NULL; + delete gui; + gui = NULL; + + return EXIT_SUCCESS; +} diff --git a/src/opentld/main/Config.cpp b/src/opentld/main/Config.cpp new file mode 100644 index 0000000..5b09ed4 --- /dev/null +++ b/src/opentld/main/Config.cpp @@ -0,0 +1,527 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#include "Config.h" + +#include "Main.h" + +using namespace std; + +namespace tld +{ + static char help_text[] = + "usage: tld [option arguments] [arguments]\n" + "option arguments:\n" + "[-a ] video starts at the frameNumber \n" + "[-b ] Initial bounding box\n" + "[-c] shows color images instead of greyscale\n" + "[-d ] select input device: =(IMGS|CAM|VID)\n" + " IMGS: capture from images\n" + " CAM: capture from connected camera\n" + " VID: capture from a video\n" + " STREAM: capture from a stream\n" + "[-e ] export model after run to \n" + "[-i ] to the images or to the video\n" + "[-h] shows help\n" + "[-j ] specifies the of the last frames which are considered by the trajectory; 0 disables the trajectory\n" + "[-n ] specifies which camera device to use.\n" + "[-p ] prints results into the file \n" + "[-s] if set, user can select initial bounding box\n" + "[-x] use dsst tracker; otherwise kcf tracker is used" + "[-t ] threshold for determining positive results\n" + "[-z ] video ends at the frameNumber .\n" + " If is 0 or the option argument isn't specified means\n" + " take all frames.\n" + "arguments:\n" + "[] to the config file\n"; + + Config::Config() : + m_selectManuallySet(false), + m_methodSet(false), + m_startFrameSet(false), + m_lastFrameSet(false), + m_trajectorySet(false), + m_showDetectionsSet(false), + m_thetaSet(false), + m_printResultsSet(false), + m_camNoSet(false), + m_imagePathSet(false), + m_initialBBSet(false), + m_showOutputSet(false), + m_useDsstTrackerSet(false) + { + } + + Config::Config(Settings &settings) : + m_settings(settings) + { + } + + Config::~Config() + { + } + + int Config::init(int argc, char **argv) + { + // check cli arguments + int c; + + while ((c = getopt(argc, argv, "a:b:d:e:fhi:j:m:n:Op:qst:z:x")) != -1) + { + switch (c) + { + case 'a': + m_settings.m_startFrame = atoi(optarg); + m_startFrameSet = true; + break; + case 'b': + char *pch; + pch = strtok(optarg, ","); + + while (pch != NULL) + { + m_settings.m_initialBoundingBox.push_back(atoi(pch)); + pch = strtok(NULL, ","); + } + + break; + case 'd': + if (!strcmp(optarg, "CAM")) + { + m_settings.m_method = IMACQ_CAM; + m_methodSet = true; + } + else if (!strcmp(optarg, "VID")) + { + m_settings.m_method = IMACQ_VID; + m_methodSet = true; + } + else if (!strcmp(optarg, "IMGS")) + { + m_settings.m_method = IMACQ_IMGS; + m_methodSet = true; + } + else if (!strcmp(optarg, "STREAM")) + { + m_settings.m_method = IMACQ_STREAM; + m_methodSet = true; + } + + break; + case 'h': + cout << help_text; + return PROGRAM_EXIT; + break; + case 'i': + m_settings.m_imagePath = optarg; + m_imagePathSet = true; + break; + case 'j': + m_settings.m_trajectory = atoi(optarg); + m_trajectorySet = true; + break; + case 'n': + m_settings.m_camNo = atoi(optarg); + m_camNoSet = true; + break; + case 'p': + m_settings.m_printResults = optarg; + m_printResultsSet = true; + break; + case 'O': + m_settings.m_showOutput = false; + m_showOutputSet = true; + break; + case 's': + m_settings.m_selectManually = true; + m_selectManuallySet = true; + break; + case 't': + m_settings.m_threshold = static_cast(atof(optarg)); + m_thetaSet = true; + break; + case 'x': + m_settings.m_useDsstTracker = true; + m_useDsstTrackerSet = true; + break; + case 'z': + m_settings.m_lastFrame = atoi(optarg); + m_lastFrameSet = true; + break; + } + } + + if (!m_imagePathSet && m_methodSet && (m_settings.m_method == IMACQ_VID || m_settings.m_method == IMACQ_IMGS)) + { + cerr << "Error: Must set imagePath and method if capturing from images or a video." << endl; + return PROGRAM_EXIT; + } + + if (argc > optind) + m_configPath = argv[optind]; + + // load config file + if (!m_configPath.empty()) + { + // read config file + try + { + m_cfg.readFile(m_configPath.c_str()); + } + catch (const libconfig::FileIOException &fioex) + { + cerr << "I/O error while reading config file." << endl + << fioex.what() << endl; + return PROGRAM_EXIT; + } + catch (const libconfig::ParseException &pex) + { + cerr << "ConfigFile: Parse error" << endl + << pex.what() << endl; + return PROGRAM_EXIT; + } + + // method + string method; + m_cfg.lookupValue("acq.method", method); + + // imagePath + if (method.compare("IMGS") == 0) + { + m_settings.m_method = IMACQ_IMGS; + + try + { + m_cfg.lookupValue("acq.imgPath", m_settings.m_imagePath); + } + catch (const libconfig::SettingNotFoundException &nfex) + { + cerr << "Error: Unable to read image path." << endl + << nfex.what() << endl; + return PROGRAM_EXIT; + } + } + else if (method.compare("STREAM") == 0) + { + m_settings.m_method = IMACQ_STREAM; + + try + { + m_cfg.lookupValue("acq.imgPath", m_settings.m_imagePath); + } + catch (const libconfig::SettingNotFoundException &nfex) + { + cerr << "Error: Unable to read stream URL." << endl + << nfex.what() << endl; + return PROGRAM_EXIT; + } + } + else if (method.compare("VID") == 0) + { + m_settings.m_method = IMACQ_VID; + + try + { + m_cfg.lookupValue("acq.imgPath", m_settings.m_imagePath); + } + catch (const libconfig::SettingNotFoundException &nfex) + { + cerr << "Error: Unable to read image path." << endl + << nfex.what() << endl; + return PROGRAM_EXIT; + } + } + else if (method.compare("CAM") == 0) + { + m_settings.m_method = IMACQ_CAM; + } + else if (method.compare("LIVESIM") == 0) + { + m_settings.m_method = IMACQ_LIVESIM; + //fps + m_cfg.lookupValue("acq.fps", m_settings.m_fps); + + try + { + m_cfg.lookupValue("acq.imgPath", m_settings.m_imagePath); + } + catch (const libconfig::SettingNotFoundException &nfex) + { + cerr << "Error: Unable to read image path." << endl + << nfex.what() << endl; + return PROGRAM_EXIT; + } + } + + // startFrame + if (!m_startFrameSet) + m_cfg.lookupValue("acq.startFrame", m_settings.m_startFrame); + + // lastFrame + if (!m_lastFrameSet) + m_cfg.lookupValue("acq.lastFrame", m_settings.m_lastFrame); + + // camNo + if (!m_camNoSet) + m_cfg.lookupValue("acq.camNo", m_settings.m_camNo); + + // useProportionalShift + m_cfg.lookupValue("detector.useProportionalShift", m_settings.m_useProportionalShift); + + // proportionalShift + m_cfg.lookupValue("detector.proportionalShift", m_settings.m_proportionalShift); + + // minScale + m_cfg.lookupValue("detector.minScale", m_settings.m_minScale); + + // maxScale + m_cfg.lookupValue("detector.maxScale", m_settings.m_maxScale); + + // minSize + m_cfg.lookupValue("detector.minSize", m_settings.m_minSize); + + // numTrees + m_cfg.lookupValue("detector.numTrees", m_settings.m_numTrees); + + // numFeatures + m_cfg.lookupValue("detector.numFeatures", m_settings.m_numFeatures); + + // numFeatures + m_cfg.lookupValue("detector.thetaP", m_settings.m_thetaP); + m_cfg.lookupValue("detector.thetaN", m_settings.m_thetaN); + + // showOutput + if (!m_showOutputSet) + m_cfg.lookupValue("showOutput", m_settings.m_showOutput); + + // trajectory + if (!m_trajectorySet) + m_cfg.lookupValue("trajectory", m_settings.m_trajectory); + + // printResults + if (!m_printResultsSet) + m_cfg.lookupValue("printResults", m_settings.m_printResults); + + // printTiming + m_cfg.lookupValue("printTiming", m_settings.m_printTiming); + + // learningEnabled + m_cfg.lookupValue("learningEnabled", m_settings.m_learningEnabled); + + // trackerEnabled + m_cfg.lookupValue("trackerEnabled", m_settings.m_trackerEnabled); + + // detectorEnabled + m_cfg.lookupValue("detectorEnabled", m_settings.m_detectorEnabled); + + // varianceFilterEnabled + m_cfg.lookupValue("detector.varianceFilterEnabled", m_settings.m_varianceFilterEnabled); + + // emnsembleClassifierEnabled + m_cfg.lookupValue("detector.ensembleClassifierEnabled", m_settings.m_ensembleClassifierEnabled); + + // nnClassifierEnabled + m_cfg.lookupValue("detector.nnClassifierEnabled", m_settings.m_nnClassifierEnabled); + + if (!m_useDsstTrackerSet) + m_cfg.lookupValue("useDsstTracker", m_settings.m_useDsstTracker); + + // selectManually + if (!m_selectManuallySet) + m_cfg.lookupValue("selectManually", m_settings.m_selectManually); + + // saveDir + m_cfg.lookupValue("saveDir", m_settings.m_outputDir); + + // theta + if (!m_thetaSet) + m_cfg.lookupValue("threshold", m_settings.m_threshold); + + // showNotConfident + m_cfg.lookupValue("showNotConfident", m_settings.m_showNotConfident); + + // showDetections + if (!m_showDetectionsSet) + m_cfg.lookupValue("showDetections", m_settings.m_showDetections); + + // alternating + m_cfg.lookupValue("alternating", m_settings.m_alternating); + + // seed + m_cfg.lookupValue("seed", m_settings.m_seed); + + // initialBoundingBox + try + { + libconfig::Setting &initBB_setting = m_cfg.lookup("initialBoundingBox"); + + for (int i = 0; i < 4; i++) + { + m_settings.m_initialBoundingBox.push_back(initBB_setting[i]); + } + } + catch (const libconfig::SettingNotFoundException &nfex) + { + (void)nfex; // avoid warning + // Ignore + } + } + + return SUCCESS; + } + + int Config::configure(Main *main) + { + ImAcq *imAcq = main->imAcq; + + // imAcq + imAcq->method = m_settings.m_method; + imAcq->imgPath = (m_settings.m_imagePath.empty()) ? NULL : m_settings.m_imagePath.c_str(); + imAcq->lastFrame = m_settings.m_lastFrame; + imAcq->currentFrame = m_settings.m_startFrame; + imAcq->camNo = m_settings.m_camNo; + imAcq->fps = m_settings.m_fps; + + // main + main->tld->trackerEnabled = m_settings.m_trackerEnabled; + main->tld->detectorEnabled = m_settings.m_detectorEnabled; + main->tld->init(m_settings.m_useDsstTracker); + main->showOutput = m_settings.m_showOutput; + main->showTrajectory = (m_settings.m_trajectory) ? true : false; + main->trajectoryLength = m_settings.m_trajectory; + main->printResults = (m_settings.m_printResults.empty()) ? NULL : m_settings.m_printResults.c_str(); + main->saveDir = (m_settings.m_outputDir.empty()) ? NULL : m_settings.m_outputDir.c_str(); + main->threshold = m_settings.m_threshold; + main->showNotConfident = m_settings.m_showNotConfident; + main->tld->alternating = m_settings.m_alternating; + main->tld->learningEnabled = m_settings.m_learningEnabled; + main->selectManually = m_settings.m_selectManually; + main->seed = m_settings.m_seed; + + if (m_settings.m_initialBoundingBox.size() > 0) + { + main->initialBB = new int[4]; + + for (int i = 0; i < 4; i++) + { + main->initialBB[i] = m_settings.m_initialBoundingBox[i]; + } + } + + DetectorCascade *detectorCascade = main->tld->detectorCascade; + detectorCascade->varianceFilter->enabled = m_settings.m_varianceFilterEnabled; + detectorCascade->ensembleClassifier->enabled = m_settings.m_ensembleClassifierEnabled; + detectorCascade->nnClassifier->enabled = m_settings.m_nnClassifierEnabled; + + // classifier + detectorCascade->useShift = m_settings.m_useProportionalShift; + detectorCascade->shift = m_settings.m_proportionalShift; + detectorCascade->minScale = m_settings.m_minScale; + detectorCascade->maxScale = m_settings.m_maxScale; + detectorCascade->minSize = m_settings.m_minSize; + detectorCascade->numTrees = m_settings.m_numTrees; + detectorCascade->numFeatures = m_settings.m_numFeatures; + detectorCascade->nnClassifier->thetaTP = m_settings.m_thetaP; + detectorCascade->nnClassifier->thetaFP = m_settings.m_thetaN; + + return SUCCESS; + } + + /* + POSIX getopt for Windows + + AT&T Public License + + Code given out at the 1985 UNIFORUM conference in Dallas. + */ +#ifndef __GNUC__ + +#define NULL 0 +#define EOF (-1) +#define ERR(s, c) if(opterr){\ + fputs(argv[0], stderr);\ + fputs(s, stderr);\ + fputc(c, stderr);} + + int opterr = 1; + int optind = 1; + int optopt; + char *optarg; + + int getopt(int argc, char **argv, char *opts) + { + static int sp = 1; + register int c; + register char *cp; + + if (sp == 1) + if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') + return (EOF); + else if (strcmp(argv[optind], "--") == NULL) + { + optind++; + return (EOF); + } + + optopt = c = argv[optind][sp]; + + if (c == ':' || (cp = strchr(opts, c)) == NULL) + { + ERR(": illegal option -- ", c); + + if (argv[optind][++sp] == '\0') + { + optind++; + sp = 1; + } + + return ('?'); + } + + if (*++cp == ':') + { + if (argv[optind][sp + 1] != '\0') + optarg = &argv[optind++][sp + 1]; + else if (++optind >= argc) + { + ERR(": option requires an argument -- ", c); + sp = 1; + return ('?'); + } + else + optarg = argv[optind++]; + + sp = 1; + } + else + { + if (argv[optind][++sp] == '\0') + { + sp = 1; + optind++; + } + + optarg = NULL; + } + + return (c); + } + +#endif /* __GNUC__ */ +} diff --git a/src/opentld/main/Config.h b/src/opentld/main/Config.h new file mode 100644 index 0000000..c5d5b44 --- /dev/null +++ b/src/opentld/main/Config.h @@ -0,0 +1,116 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include + +#include + +#include "ImAcq.h" +#include "Settings.h" +#include "Main.h" + +namespace tld +{ + /** + * Config is used to configure the program by cli and/or by a config file + */ + class Config + { + public: + /** + * Constructor + */ + Config(); + + Config(Settings &settings); + + /** + * Destructor + */ + ~Config(); + + /** + * Initializes the Config. + * @param argc number of command line arguments + * @param argv command line arguments + * @return PROGRAM_EXIT when an error occurred, SUCCESS if not + */ + int init(int argc, char **argv); + + /** + * Configures the CamNode, ImAcq and TldClassifier. + * @param node + * @param imAcq + * @param classifier + * @return SUCCESS + */ + int configure(Main *main); + private: + libconfig::Config m_cfg; //!< libconfig++ + std::string m_configPath; //!< path to the config file + Settings m_settings; //!< adjusted settings + ///@{ + /** + * Flags if parameters were set by cli-arguments. + * When the flags are set, the parameters couldn't be + * overwritten by the options in the config file. + * The cli-arguments have a higher priority than the options + * in the config file. + */ + bool m_selectManuallySet; + bool m_methodSet; + bool m_startFrameSet; + bool m_lastFrameSet; + bool m_trajectorySet; + bool m_showDetectionsSet; + bool m_thetaSet; + bool m_printResultsSet; + bool m_camNoSet; + bool m_imagePathSet; + bool m_initialBBSet; + bool m_showOutputSet; + bool m_useDsstTrackerSet; + ///@} + }; + + /* + POSIX getopt for Windows + + AT&T Public License + + Code given out at the 1985 UNIFORUM conference in Dallas. + */ +#ifdef __GNUC__ +# include +#endif + +#ifndef __GNUC__ + extern int opterr; + extern int optind; + extern int optopt; + extern char *optarg; + extern int getopt(int argc, char **argv, char *opts); +#endif /* __GNUC__ */ +} /* End Namespace */ + +#endif /* CONFIG_H */ diff --git a/src/opentld/main/Gui.cpp b/src/opentld/main/Gui.cpp new file mode 100644 index 0000000..ea2f142 --- /dev/null +++ b/src/opentld/main/Gui.cpp @@ -0,0 +1,153 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * gui.cpp + * + * Created on: Oct 18, 2011 + * Author: clemensk + */ + +#include "Gui.h" + +#include "Main.h" + +#include + +using std::string; + +namespace tld +{ + Gui::Gui() : + m_window_name("tld") + { + } + + Gui::~Gui() + { + } + + void Gui::init() + { + cvNamedWindow(m_window_name.c_str(), CV_WINDOW_AUTOSIZE); + cvMoveWindow(m_window_name.c_str(), 100, 100); + } + + void Gui::showImage(IplImage *image) + { + cvShowImage(m_window_name.c_str(), image); + } + + char Gui::getKey() + { + return cvWaitKey(10); + } + + std::string Gui::windowName() + { + return m_window_name; + } + + static string window_name; + static CvFont font; + static IplImage *img0; + static IplImage *img1; + static CvPoint point; + static CvRect *bb; + static int drag = 0; + + static void mouseHandler(int event, int x, int y, int flags, void *param) + { + /* user press left button */ + if (event == CV_EVENT_LBUTTONDOWN && !drag) + { + point = cvPoint(x, y); + drag = 1; + } + + /* user drag the mouse */ + if (event == CV_EVENT_MOUSEMOVE && drag) + { + img1 = (IplImage *)cvClone(img0); + + cvRectangle(img1, point, cvPoint(x, y), CV_RGB(255, 0, 0), 1, 8, 0); + + cvShowImage(window_name.c_str(), img1); + cvReleaseImage(&img1); + } + + /* user release left button */ + if (event == CV_EVENT_LBUTTONUP && drag) + { + *bb = cvRect(point.x, point.y, x - point.x, y - point.y); + drag = 0; + } + } + + // TODO: member of Gui + // --> problem: callback function mouseHandler as member! + int getBBFromUser(IplImage *img, CvRect &rect, Gui *gui) + { + window_name = gui->windowName(); + img0 = (IplImage *)cvClone(img); + rect = cvRect(-1, -1, -1, -1); + bb = ▭ + bool correctBB = false; + cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, 8); + + cvSetMouseCallback(window_name.c_str(), mouseHandler, NULL); + cvPutText(img0, "Draw a bounding box and press Enter", cvPoint(0, 60), + &font, cvScalar(255, 255, 0)); + cvShowImage(window_name.c_str(), img0); + + while (!correctBB) + { + char key = cvWaitKey(0); + + if (tolower(key) == 'q') + { + return PROGRAM_EXIT; + } + + if (((key == '\n') || (key == '\r') || (key == '\r\n')) && (bb->x != -1) && (bb->y != -1)) + { + correctBB = true; + } + } + + if (rect.width < 0) + { + rect.x += rect.width; + rect.width = abs(rect.width); + } + + if (rect.height < 0) + { + rect.y += rect.height; + rect.height = abs(rect.height); + } + + cvSetMouseCallback(window_name.c_str(), NULL, NULL); + + cvReleaseImage(&img0); + cvReleaseImage(&img1); + + return SUCCESS; + } +} diff --git a/src/opentld/main/Gui.h b/src/opentld/main/Gui.h new file mode 100644 index 0000000..8e1a393 --- /dev/null +++ b/src/opentld/main/Gui.h @@ -0,0 +1,53 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#ifndef GUI_H_ +#define GUI_H_ + +#include + +#include + +namespace tld +{ + class Gui + { + public: + Gui(); + ~Gui(); + void init(); + void showImage(IplImage *image); + char getKey(); + std::string windowName(); + + private: + std::string m_window_name; + }; + + /** + * Get a bounding box from the user. + * @param img image to display + * @param rect CvRect containing the coordinates of the bounding box + * @param gui initialized gui + * @return PROGRAM_EXIT if 'q' or 'Q' pressed, SUCCESS if everything went right + */ + int getBBFromUser(IplImage *img, CvRect &rect, Gui *gui); +} + +#endif /* GUI_H_ */ diff --git a/src/opentld/main/Main.cpp b/src/opentld/main/Main.cpp new file mode 100644 index 0000000..a8dbf27 --- /dev/null +++ b/src/opentld/main/Main.cpp @@ -0,0 +1,248 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ +/* + * MainX.cpp + * + * Created on: Nov 17, 2011 + * Author: Georg Nebehay + */ + +#include "Main.h" + +#include "Config.h" +#include "ImAcq.h" +#include "Gui.h" +#include "TLDUtil.h" +#include "Trajectory.h" +#include "opencv2/imgproc/imgproc.hpp" + +using namespace tld; +using namespace cv; + +void Main::doWork() +{ + Trajectory trajectory; + IplImage *img = imAcqGetImg(imAcq); + Mat colorImage = cvarrToMat(img, true); + + if (colorImage.channels() == 1) + cv::cvtColor(colorImage, colorImage, cv::COLOR_GRAY2BGR); + + if (showTrajectory) + { + trajectory.init(trajectoryLength); + } + + if (selectManually) + { + CvRect box; + + if (getBBFromUser(img, box, gui) == PROGRAM_EXIT) + { + return; + } + + if (initialBB == NULL) + { + initialBB = new int[4]; + } + + initialBB[0] = box.x; + initialBB[1] = box.y; + initialBB[2] = box.width; + initialBB[3] = box.height; + } + + FILE *resultsFile = NULL; + + if (printResults != NULL) + { + resultsFile = fopen(printResults, "w"); + if (!resultsFile) + { + fprintf(stderr, "Error: Unable to create results-file \"%s\"\n", printResults); + exit(-1); + } + } + + bool reuseFrameOnce = false; + bool skipProcessingOnce = false; + bool paused = false; + bool step = false; + double tic = 0; + double toc = 0; + + if (initialBB != NULL) + { + Rect bb = tldArrayToRect(initialBB); + + printf("Starting at %d %d %d %d\n", bb.x, bb.y, bb.width, bb.height); + tic = static_cast(getTickCount()); + tld->selectObject(colorImage, &bb); + toc = getTickCount() - tic; + skipProcessingOnce = true; + reuseFrameOnce = true; + } + + while (imAcqHasMoreFrames(imAcq)) + { + if (!reuseFrameOnce && (!paused || step)) + { + cvReleaseImage(&img); + img = imAcqGetImg(imAcq); + colorImage = cvarrToMat(img, true); + + if (colorImage.channels() == 1) + cv::cvtColor(colorImage, colorImage, cv::COLOR_GRAY2BGR); + + if (img == NULL) + { + printf("current image is NULL, assuming end of input.\n"); + break; + } + } + + if (!skipProcessingOnce && (!paused || step)) + { + tic = static_cast(getTickCount()); + tld->processImage(colorImage); + toc = getTickCount() - tic; + } + else + { + skipProcessingOnce = false; + } + + float fps = static_cast(getTickFrequency() / toc); + + if (printResults != NULL) + { + if (tld->currBB != NULL) + { + fprintf(resultsFile, "%d, %.2d, %.2d, %.2d, %.2d, %f, %f\n", imAcq->currentFrame - 1, + tld->currBB->x, tld->currBB->y, tld->currBB->width, tld->currBB->height, tld->currConf, + fps); + } + else + { + fprintf(resultsFile, "%d, NaN, NaN, NaN, NaN, NaN, %f\n", imAcq->currentFrame - 1, fps); + } + } + + if (showOutput || saveDir != NULL) + { + char string[128]; + char learningString[10] = ""; + + if (paused && step) + step = false; + + if (tld->learning) + { + strcpy(learningString, "Learning"); + } + + sprintf(string, "#%d, fps: %.2f, #numwindows:%d, %s", imAcq->currentFrame - 1, + fps, tld->detectorCascade->numWindows, learningString); + CvScalar yellow = CV_RGB(255, 255, 0); + CvScalar blue = CV_RGB(0, 0, 255); + CvScalar black = CV_RGB(0, 0, 0); + CvScalar white = CV_RGB(255, 255, 255); + CvScalar red = CV_RGB(255, 0, 0); + + if (tld->currBB != NULL) + { + CvScalar rectangleColor = red; + cvRectangle(img, tld->currBB->tl(), tld->currBB->br(), rectangleColor, 2, 8, 0); + } + + CvFont font; + cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, .5, .5, 0, 2, 8); + //cvRectangle(img, cvPoint(0, 0), cvPoint(img->width, 50), black, CV_FILLED, 8, 0); + cvPutText(img, string, cvPoint(25, 25), &font, red); + + if (showOutput) + { + gui->showImage(img); + char key = gui->getKey(); + + if (key == 'q') + break; + + if (key == 'p') + paused = !paused; + + if (paused && key == 's') + step = true; + + if (key == 'c') + { + //clear everything + tld->release(); + } + + if (key == 'l') + { + tld->learningEnabled = !tld->learningEnabled; + printf("LearningEnabled: %d\n", tld->learningEnabled); + } + + if (key == 'a') + { + tld->alternating = !tld->alternating; + printf("alternating: %d\n", tld->alternating); + } + + if (key == 'r') + { + CvRect box; + + if (getBBFromUser(img, box, gui) == PROGRAM_EXIT) + { + break; + } + + Rect r = Rect(box); + tld->selectObject(colorImage, &r); + } + } + + if (saveDir != NULL) + { + char fileName[256]; + sprintf(fileName, "%s/%.5d.png", saveDir, imAcq->currentFrame - 1); + + cvSaveImage(fileName, img); + } + } + + if (reuseFrameOnce) + { + reuseFrameOnce = false; + } + } + + cvReleaseImage(&img); + img = NULL; + + if (resultsFile) + { + fclose(resultsFile); + } +} diff --git a/src/opentld/main/Main.h b/src/opentld/main/Main.h new file mode 100644 index 0000000..00c294b --- /dev/null +++ b/src/opentld/main/Main.h @@ -0,0 +1,103 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +/* + * main.h + * + * Created on: Nov 18, 2011 + * Author: Georg Nebehay + */ + +#ifndef MAIN_H_ +#define MAIN_H_ + +#include "TLD.h" +#include "ImAcq.h" +#include "Gui.h" +#include "cf_tracker.hpp" + +enum Retval +{ + PROGRAM_EXIT = 0, + SUCCESS = 1 +}; + +class Main +{ +public: + tld::TLD *tld; + ImAcq *imAcq; + tld::Gui *gui; + bool showOutput; + bool showTrajectory; + int trajectoryLength; + const char *printResults; + const char *saveDir; + double threshold; + bool showForeground; + bool showNotConfident; + bool selectManually; + int *initialBB; + bool reinit; + bool exportModelAfterRun; + bool loadModel; + const char *modelPath; + const char *modelExportFile; + int seed; + + Main() + { + tld = new tld::TLD(); + showOutput = 1; + printResults = NULL; + saveDir = "."; + threshold = 0.5; + showForeground = 0; + + showTrajectory = false; + trajectoryLength = 0; + + selectManually = 0; + + initialBB = NULL; + showNotConfident = true; + + reinit = 0; + + loadModel = false; + + exportModelAfterRun = false; + modelExportFile = "model"; + seed = 0; + + gui = NULL; + modelPath = NULL; + imAcq = NULL; + } + + ~Main() + { + delete tld; + imAcqFree(imAcq); + } + + void doWork(); +}; + +#endif /* MAIN_H_ */ diff --git a/src/opentld/main/Settings.cpp b/src/opentld/main/Settings.cpp new file mode 100644 index 0000000..ff45fc2 --- /dev/null +++ b/src/opentld/main/Settings.cpp @@ -0,0 +1,69 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#include "Settings.h" + +using namespace std; + +/** + * @author Clemens Korner + */ + +namespace tld +{ + Settings::Settings() : + m_useProportionalShift(true), + m_varianceFilterEnabled(true), + m_ensembleClassifierEnabled(true), + m_nnClassifierEnabled(true), + m_trackerEnabled(true), + m_detectorEnabled(true), + m_selectManually(false), + m_learningEnabled(true), + m_showOutput(true), + m_showNotConfident(true), + m_showColorImage(false), + m_showDetections(false), + m_saveOutput(false), + m_alternating(false), + m_useDsstTracker(false), + m_trajectory(0), + m_method(IMACQ_CAM), + m_startFrame(1), + m_lastFrame(0), + m_minScale(-10), + m_maxScale(10), + m_numFeatures(13), + m_numTrees(10), + m_thetaP(0.55f), + m_thetaN(0.5f), + m_minSize(25), + m_camNo(0), + m_fps(24), + m_seed(0), + m_threshold(0.7f), + m_proportionalShift(0.1f), + m_initialBoundingBox(vector()) + { + } + + Settings::~Settings() + { + } +} diff --git a/src/opentld/main/Settings.h b/src/opentld/main/Settings.h new file mode 100644 index 0000000..f377da1 --- /dev/null +++ b/src/opentld/main/Settings.h @@ -0,0 +1,83 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#ifndef SETTINGS_H +#define SETTINGS_H + +#include + +#include "ImAcq.h" + +/** + * @author Clemens Korner + */ + +namespace tld +{ + /** + * In this class all settings are stored. + */ + class Settings + { + public: + /** + * Standard-Constructor + */ + Settings(); + ~Settings(); + bool m_trackerEnabled; + bool m_detectorEnabled; + bool m_varianceFilterEnabled; + bool m_ensembleClassifierEnabled; + bool m_nnClassifierEnabled; + bool m_useProportionalShift; //!< sets scanwindows off by a percentage value of the window dimensions (specified in proportionalShift) rather than 1px. + bool m_selectManually; //!< if true, user can select initial bounding box (which then overrides the setting "initialBoundingBox") + bool m_learningEnabled; //!< enables learning while processing + bool m_showOutput; //!< creates a window displaying results + bool m_showNotConfident; //!< show bounding box also if confidence is low + bool m_showColorImage; //!< shows color images instead of greyscale + bool m_showDetections; //!< shows detections + bool m_saveOutput; //!< specifies whether to save visual output + bool m_alternating; //!< if set to true, detector is disabled while tracker is running. + bool m_useDsstTracker; + int m_trajectory; //!< specifies the number of the last frames which are considered by the trajectory; 0 disables the trajectory + int m_method; //!< method of capturing: IMACQ_CAM, IMACQ_IMGS or IMACQ_VID + int m_startFrame; //!< first frame of capturing + int m_lastFrame; //!< last frame of caputing; 0 means take all frames + int m_minScale; //!< number of scales smaller than initial object size + int m_maxScale; //!< number of scales larger than initial object size + int m_numFeatures; //!< number of features + int m_numTrees; //!< number of trees + float m_thetaP; + float m_thetaN; + int m_seed; + int m_minSize; //!< minimum size of scanWindows + int m_camNo; //!< Which camera to use + float m_fps; //!< Frames per second + float m_threshold; //!< threshold for determining positive results + float m_proportionalShift; //!< proportional shift + std::string m_imagePath; //!< path to the images or the video if m_method is IMACQ_VID or IMACQ_IMGS + std::string m_outputDir; //!< required if saveOutput = true, no default + std::string m_printResults; //!< path to the file were the results should be printed; NULL -> results will not be printed + std::string m_printTiming; //!< path to the file were the timings should be printed; NULL -> results will not be printed + std::vector m_initialBoundingBox; //!< Initial Bounding Box can be specified here + }; +} + +#endif /* SETTINGS_H */ diff --git a/src/opentld/main/Trajectory.cpp b/src/opentld/main/Trajectory.cpp new file mode 100644 index 0000000..4f0641b --- /dev/null +++ b/src/opentld/main/Trajectory.cpp @@ -0,0 +1,90 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#include "Trajectory.h" + +#include + +/** + * @author Clemens Korner + */ + +using namespace std; + +namespace tld +{ + Trajectory::Trajectory() : + m_length(0) + { + } + + Trajectory::~Trajectory() + { + } + + void Trajectory::init(std::size_t length) + { + m_length = length; + m_track_positions = vector(); + m_track_colors = vector(); + } + + void Trajectory::addPoint(CvPoint point, CvScalar color) + { + size_t length = m_track_positions.size(); + + // vectors aren't full + if (length < m_length) + { + m_track_positions.push_back(point); + m_track_colors.push_back(color); + } + else + { + // push element to the end + m_track_positions.push_back(point); + m_track_colors.push_back(color); + + // drop first element + m_track_positions.erase(m_track_positions.begin()); + m_track_colors.erase(m_track_colors.begin()); + } + } + + void Trajectory::drawTrajectory(IplImage * image) + { + CvPoint tempPoint; + bool needSecondPoint = false; + + for (size_t i = 0; i < m_track_positions.size(); i++) + { + // try to find 1. point of the line + if ((!needSecondPoint) && (m_track_positions[i].x != -1)) { + tempPoint = m_track_positions[i]; + needSecondPoint = true; + // try to find 2. point of the line + } + else if (needSecondPoint && (m_track_positions[i].x != -1)) + { + cvLine(image, tempPoint, m_track_positions[i], m_track_colors[i], 2); + tempPoint = m_track_positions[i]; + } + } + } +} diff --git a/src/opentld/main/Trajectory.h b/src/opentld/main/Trajectory.h new file mode 100644 index 0000000..4cf1a63 --- /dev/null +++ b/src/opentld/main/Trajectory.h @@ -0,0 +1,77 @@ +/* Copyright 2011 AIT Austrian Institute of Technology +* +* This file is part of OpenTLD. +* +* OpenTLD 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. +* +* OpenTLD 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 OpenTLD. If not, see . +* +*/ + +#ifndef TRAJECTORY_H_ +#define TRAJECTORY_H_ + +#include +#include + +/** + * @author Clemens Korner + */ + +namespace tld +{ + /** + * Detection trajectory; a line which associates the last detections. + * The data is stored in 2 "shift registers" + */ + class Trajectory + { + public: + /** + * Constructor; don't forget to call init(length) afterwards + */ + Trajectory(); + + /** + * Destructor + */ + ~Trajectory(); + + /** + * Initializes the trajectory. + * @param length specifies the number of the last frames which are + * considered by the trajectory + */ + void init(std::size_t length); + + /** + * Adds a new point to the trajectory. + * If you want to add a "place holder" point just add a cvPoint(-1, -1) + * and cvScalar(-1 , -1, -1) + * @param point point which specifies the location of the point + * @param color defines the color (confidence) of the point + */ + void addPoint(CvPoint point, CvScalar color); + + /** + * Draws the trajectory into an image. + * @param image image to draw + */ + void drawTrajectory(IplImage * image); + private: + std::size_t m_length; ///< number of the last frames which are considered by the trajectory + std::vector m_track_positions; ///< vector containing the locations of the points + std::vector m_track_colors; ///< vector containing the colors of the points + }; +} + +#endif /* TRAJECTORY_H_ */