From 489f3eb093ffc588784d8df75f2183181edc4f77 Mon Sep 17 00:00:00 2001 From: joyyueyi Date: Thu, 28 Dec 2017 09:44:15 +0000 Subject: [PATCH] init version --- AUTHORS | 20 + CMakeLists.txt | 95 + LICENSE | 875 ++++-- OpenTLDConfig.cmake.in | 21 + README.md | 132 + performance_report.pdf | Bin 0 -> 752660 bytes src/3rdparty/cf_tracking/.gitignore | 1 + src/3rdparty/cf_tracking/CMakeLists.txt | 56 + src/3rdparty/cf_tracking/README.md | 128 + .../src/3rdparty/cv_ext/init_box_selector.cpp | 114 + .../src/3rdparty/cv_ext/init_box_selector.hpp | 73 + .../src/3rdparty/cv_ext/math_spectrums.cpp | 278 ++ .../src/3rdparty/cv_ext/math_spectrums.hpp | 198 ++ .../cf_tracking/src/3rdparty/cv_ext/psr.hpp | 85 + .../cf_tracking/src/3rdparty/cv_ext/shift.cpp | 148 ++ .../cf_tracking/src/3rdparty/cv_ext/shift.hpp | 49 + .../src/3rdparty/cv_ext/tracker_run.cpp | 441 +++ .../src/3rdparty/cv_ext/tracker_run.hpp | 118 + .../cf_tracking/src/3rdparty/piotr/README.md | 3 + .../src/3rdparty/piotr/gradientMex.hpp | 340 +++ .../src/3rdparty/piotr/src/gradientMex.cpp | 656 +++++ .../src/3rdparty/piotr/src/sse.hpp | 116 + .../src/3rdparty/piotr/src/sse_to_neon.hpp | 177 ++ .../src/3rdparty/piotr/src/wrappers.hpp | 78 + .../cf_tracking/src/3rdparty/tclap/AUTHORS | 6 + .../cf_tracking/src/3rdparty/tclap/COPYING | 25 + .../cf_tracking/src/3rdparty/tclap/ChangeLog | 1760 ++++++++++++ .../cf_tracking/src/3rdparty/tclap/INSTALL | 182 ++ .../src/3rdparty/tclap/Makefile.am | 1 + .../src/3rdparty/tclap/Makefile.in | 460 ++++ .../cf_tracking/src/3rdparty/tclap/README | 16 + .../src/3rdparty/tclap/tclap/Arg.h | 692 +++++ .../src/3rdparty/tclap/tclap/ArgException.h | 200 ++ .../src/3rdparty/tclap/tclap/ArgTraits.h | 87 + .../src/3rdparty/tclap/tclap/CmdLine.h | 633 +++++ .../3rdparty/tclap/tclap/CmdLineInterface.h | 150 ++ .../src/3rdparty/tclap/tclap/CmdLineOutput.h | 74 + .../src/3rdparty/tclap/tclap/Constraint.h | 68 + .../src/3rdparty/tclap/tclap/DocBookOutput.h | 299 +++ .../src/3rdparty/tclap/tclap/HelpVisitor.h | 76 + .../3rdparty/tclap/tclap/IgnoreRestVisitor.h | 52 + .../src/3rdparty/tclap/tclap/Makefile.am | 28 + .../src/3rdparty/tclap/tclap/Makefile.in | 403 +++ .../src/3rdparty/tclap/tclap/MultiArg.h | 433 +++ .../src/3rdparty/tclap/tclap/MultiSwitchArg.h | 216 ++ .../tclap/tclap/OptionalUnlabeledTracker.h | 62 + .../src/3rdparty/tclap/tclap/StandardTraits.h | 208 ++ .../src/3rdparty/tclap/tclap/StdOutput.h | 298 +++ .../src/3rdparty/tclap/tclap/SwitchArg.h | 266 ++ .../3rdparty/tclap/tclap/UnlabeledMultiArg.h | 301 +++ .../3rdparty/tclap/tclap/UnlabeledValueArg.h | 340 +++ .../src/3rdparty/tclap/tclap/ValueArg.h | 425 +++ .../3rdparty/tclap/tclap/ValuesConstraint.h | 148 ++ .../src/3rdparty/tclap/tclap/VersionVisitor.h | 81 + .../src/3rdparty/tclap/tclap/Visitor.h | 53 + .../src/3rdparty/tclap/tclap/XorHandler.h | 166 ++ .../tclap/tclap/ZshCompletionOutput.h | 323 +++ .../src/cf_libs/common/cf_tracker.hpp | 61 + .../cf_tracking/src/cf_libs/common/cv_ext.hpp | 38 + .../src/cf_libs/common/feature_channels.hpp | 186 ++ .../src/cf_libs/common/mat_consts.hpp | 48 + .../src/cf_libs/common/math_helper.cpp | 67 + .../src/cf_libs/common/math_helper.hpp | 319 +++ .../src/cf_libs/common/scale_estimator.hpp | 338 +++ .../src/cf_libs/common/tracker_debug.hpp | 49 + .../src/cf_libs/dsst/dsst_debug.hpp | 127 + .../src/cf_libs/dsst/dsst_tracker.hpp | 707 +++++ .../cf_tracking/src/cf_libs/kcf/kcf_debug.hpp | 116 + .../src/cf_libs/kcf/kcf_tracker.hpp | 931 +++++++ .../src/main/image_acquisition.cpp | 130 + .../src/main/image_acquisition.hpp | 90 + .../cf_tracking/src/main/main_dsst.cpp | 139 + .../cf_tracking/src/main/main_kcf.cpp | 149 ++ src/3rdparty/libconfig/CMakeLists.txt | 21 + src/3rdparty/libconfig/grammar.c | 2001 ++++++++++++++ src/3rdparty/libconfig/grammar.h | 113 + src/3rdparty/libconfig/libconfig.c | 1616 +++++++++++ src/3rdparty/libconfig/libconfig.h | 321 +++ src/3rdparty/libconfig/libconfig.h++ | 459 ++++ src/3rdparty/libconfig/libconfig.hh | 23 + src/3rdparty/libconfig/libconfigcpp.c++ | 1167 ++++++++ src/3rdparty/libconfig/libconfigcpp.cc | 23 + src/3rdparty/libconfig/parsectx.h | 48 + src/3rdparty/libconfig/scanctx.c | 171 ++ src/3rdparty/libconfig/scanctx.h | 62 + src/3rdparty/libconfig/scanner.c | 2362 +++++++++++++++++ src/3rdparty/libconfig/scanner.h | 326 +++ src/3rdparty/libconfig/strbuf.c | 58 + src/3rdparty/libconfig/strbuf.h | 40 + src/3rdparty/libconfig/wincompat.h | 90 + src/libopentld/CMakeLists.txt | 33 + src/libopentld/CMakeLists2.txt | 30 + src/libopentld/imacq/ImAcq.cpp | 279 ++ src/libopentld/imacq/ImAcq.h | 80 + src/libopentld/tld/Clustering.cpp | 257 ++ src/libopentld/tld/Clustering.h | 57 + src/libopentld/tld/DetectionResult.cpp | 93 + src/libopentld/tld/DetectionResult.h | 57 + src/libopentld/tld/DetectorCascade.cpp | 305 +++ src/libopentld/tld/DetectorCascade.h | 93 + src/libopentld/tld/EnsembleClassifier.cpp | 246 ++ src/libopentld/tld/EnsembleClassifier.h | 80 + src/libopentld/tld/IntegralImage.h | 78 + src/libopentld/tld/NNClassifier.cpp | 190 ++ src/libopentld/tld/NNClassifier.h | 63 + src/libopentld/tld/NormalizedPatch.h | 40 + src/libopentld/tld/TLD.cpp | 418 +++ src/libopentld/tld/TLD.h | 76 + src/libopentld/tld/TLDUtil.cpp | 227 ++ src/libopentld/tld/TLDUtil.h | 117 + src/libopentld/tld/VarianceFilter.cpp | 98 + src/libopentld/tld/VarianceFilter.h | 58 + src/opentld/CMakeLists.txt | 43 + src/opentld/OpenTLD.cpp | 67 + src/opentld/main/Config.cpp | 527 ++++ src/opentld/main/Config.h | 116 + src/opentld/main/Gui.cpp | 153 ++ src/opentld/main/Gui.h | 53 + src/opentld/main/Main.cpp | 248 ++ src/opentld/main/Main.h | 103 + src/opentld/main/Settings.cpp | 69 + src/opentld/main/Settings.h | 83 + src/opentld/main/Trajectory.cpp | 90 + src/opentld/main/Trajectory.h | 77 + 124 files changed, 29533 insertions(+), 201 deletions(-) create mode 100644 AUTHORS create mode 100644 CMakeLists.txt create mode 100644 OpenTLDConfig.cmake.in create mode 100644 README.md create mode 100644 performance_report.pdf create mode 100644 src/3rdparty/cf_tracking/.gitignore create mode 100644 src/3rdparty/cf_tracking/CMakeLists.txt create mode 100644 src/3rdparty/cf_tracking/README.md create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.cpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/init_box_selector.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.cpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/math_spectrums.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/psr.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.cpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/shift.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.cpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/cv_ext/tracker_run.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/piotr/README.md create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/piotr/gradientMex.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/piotr/src/gradientMex.cpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/piotr/src/sse_to_neon.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/piotr/src/wrappers.hpp create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/AUTHORS create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/COPYING create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/ChangeLog create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/INSTALL create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.am create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/Makefile.in create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/README create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Arg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgException.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ArgTraits.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLine.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineInterface.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/CmdLineOutput.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Constraint.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/DocBookOutput.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/HelpVisitor.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/IgnoreRestVisitor.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.am create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Makefile.in create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiArg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/MultiSwitchArg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/OptionalUnlabeledTracker.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StandardTraits.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/StdOutput.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/SwitchArg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledMultiArg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/UnlabeledValueArg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValueArg.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ValuesConstraint.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/VersionVisitor.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/Visitor.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/XorHandler.h create mode 100644 src/3rdparty/cf_tracking/src/3rdparty/tclap/tclap/ZshCompletionOutput.h create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/cf_tracker.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/cv_ext.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/feature_channels.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/mat_consts.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.cpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/math_helper.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/scale_estimator.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/common/tracker_debug.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_debug.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/dsst/dsst_tracker.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_debug.hpp create mode 100644 src/3rdparty/cf_tracking/src/cf_libs/kcf/kcf_tracker.hpp create mode 100644 src/3rdparty/cf_tracking/src/main/image_acquisition.cpp create mode 100644 src/3rdparty/cf_tracking/src/main/image_acquisition.hpp create mode 100644 src/3rdparty/cf_tracking/src/main/main_dsst.cpp create mode 100644 src/3rdparty/cf_tracking/src/main/main_kcf.cpp create mode 100644 src/3rdparty/libconfig/CMakeLists.txt create mode 100644 src/3rdparty/libconfig/grammar.c create mode 100644 src/3rdparty/libconfig/grammar.h create mode 100644 src/3rdparty/libconfig/libconfig.c create mode 100644 src/3rdparty/libconfig/libconfig.h create mode 100644 src/3rdparty/libconfig/libconfig.h++ create mode 100644 src/3rdparty/libconfig/libconfig.hh create mode 100644 src/3rdparty/libconfig/libconfigcpp.c++ create mode 100644 src/3rdparty/libconfig/libconfigcpp.cc create mode 100644 src/3rdparty/libconfig/parsectx.h create mode 100644 src/3rdparty/libconfig/scanctx.c create mode 100644 src/3rdparty/libconfig/scanctx.h create mode 100644 src/3rdparty/libconfig/scanner.c create mode 100644 src/3rdparty/libconfig/scanner.h create mode 100644 src/3rdparty/libconfig/strbuf.c create mode 100644 src/3rdparty/libconfig/strbuf.h create mode 100644 src/3rdparty/libconfig/wincompat.h create mode 100644 src/libopentld/CMakeLists.txt create mode 100644 src/libopentld/CMakeLists2.txt create mode 100644 src/libopentld/imacq/ImAcq.cpp create mode 100644 src/libopentld/imacq/ImAcq.h create mode 100644 src/libopentld/tld/Clustering.cpp create mode 100644 src/libopentld/tld/Clustering.h create mode 100644 src/libopentld/tld/DetectionResult.cpp create mode 100644 src/libopentld/tld/DetectionResult.h create mode 100644 src/libopentld/tld/DetectorCascade.cpp create mode 100644 src/libopentld/tld/DetectorCascade.h create mode 100644 src/libopentld/tld/EnsembleClassifier.cpp create mode 100644 src/libopentld/tld/EnsembleClassifier.h create mode 100644 src/libopentld/tld/IntegralImage.h create mode 100644 src/libopentld/tld/NNClassifier.cpp create mode 100644 src/libopentld/tld/NNClassifier.h create mode 100644 src/libopentld/tld/NormalizedPatch.h create mode 100644 src/libopentld/tld/TLD.cpp create mode 100644 src/libopentld/tld/TLD.h create mode 100644 src/libopentld/tld/TLDUtil.cpp create mode 100644 src/libopentld/tld/TLDUtil.h create mode 100644 src/libopentld/tld/VarianceFilter.cpp create mode 100644 src/libopentld/tld/VarianceFilter.h create mode 100644 src/opentld/CMakeLists.txt create mode 100644 src/opentld/OpenTLD.cpp create mode 100644 src/opentld/main/Config.cpp create mode 100644 src/opentld/main/Config.h create mode 100644 src/opentld/main/Gui.cpp create mode 100644 src/opentld/main/Gui.h create mode 100644 src/opentld/main/Main.cpp create mode 100644 src/opentld/main/Main.h create mode 100644 src/opentld/main/Settings.cpp create mode 100644 src/opentld/main/Settings.h create mode 100644 src/opentld/main/Trajectory.cpp create mode 100644 src/opentld/main/Trajectory.h 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 0000000000000000000000000000000000000000..233e4b5d6d07c8aec05bdcb991dab0bf190849c7 GIT binary patch literal 752660 zcmc$_1ymew^Dc;!Ai>>+00}<0TYx}tcbCE49YPY^B|va@cXuZc+}$O(L*O>~{l9zv z-(K6hyXWj2&gq%qt?H7eo~pOIhe}>ljDeYv6BUW77I>i|F@u;uwuTm{NPK)?Wp_IW zSj51|z{=JXEN@^6aRjjd|5gM`8`zjqdzdkZ$kKqoN=^>WMo!8O5Qw6!trLiy^Y0QF z0|!e98xvbV&C6SeF$h=&5fA{&K%5MW0i7UL)|YcBf>q5St`G-#2Z#y80b*kWoP?G2 z?`Z@CP>~=u#(%AO`QqQq`fCnY#Mary3B&=GGBvKwF8 z&2?*%bJb>%PvTB2;TyE-&8E@!H@%zl z3)@YxV|HMA80^)b(Y~9W{`h0*I>Q%n6V2SAFIOOU@R>P5;tK>V>L;qNiKy=G1!VFNd4tBQ-xXsS0itk~BSqitiZmorp-$&E*k@8Y7k(^bM@-emvYYF{3l(oOL&4-Vb&bHqL)V{G72UfK~PKG4(&Uh zjUJHkh*d+e8&mCAyzQAmxu&%M{xPM1+^68RdY3ZF&~OEp`rMmldDv`4qJs=2`j{Ou z^*IJrFFO6=AIpaJk+r
uMheqB~ae_l0`C#K{{$D@8tP+Jd8abHTIoUdZIQ~|vn7Mn(FYq-D+q`Q{K3)a zh48qU*a1HH=RE@pGZVo7cAp^Tre;ncP8Kfk2N%=7rhwSkm;qvU`{x4-2M7D#6RG{P zl8uQ8to|QTEbL4GCm6g00bpT(SRmG_fb`$x!hZ>j0gwj0oD0Ol#KiP+ntvzg7e4(r z5C1FSf`w(kvbGM^23BAr0}%6n4$BMm{%?guKK#4T3oZYf(0>s3e@*yb`u-;wAU0NJ z@PGKo%*+Z9ua&KXlAVDO`+XZhN%egxr@6E0y23s41j}yv?Wzq#Ata)^+wzEYzKtoQ&<+@)F$L z>_^)#EGj#`cV@_!ZPbSP|LNuH!H125jOBd(NM37wT&nB&UW+l*YSN@ z0iqVU-d3wB!Rxj8AF2Z}$)>rF&B6AsAm|u38LC2q?sh5ZPOfk+WnuEX>+`qoE zI)_CTbQtk9N7x@k4-rF;jwQ>YcVKfp4}O0}J@J6-x}&t;`~A~kiWMa3(yigHwyRB` zY!gv0i;Rkk$KLgvx#>gPH_nxlh?|EPv@e4X(vNCwhfTkpQth6k;=rC8BG1Fm#>p#T z9DUhZV-C&_FrjszTH;h>MTEj_$L!`)O0wbMdJ~nSUF;JJirD+XfCbxIme6%B()4uO zJF>^CJtE=8&}mDOkpZoFA>GjtDsJ`5u6Kyl)CHQK)3{tHmWo>6m>3Y%_tWi7vqpQ- zf*nfITESE`8pf8Q9#ASqAfHIVhsK)Hc$(C7PjLvJy{C6qNUGD~O%c>W`B!pUAGwtT zq#$@BQwj9T!spS}9p+#$LPpX%A{}{)v%YT0V7miYYpe<#KMaxARh0zUtipx`4=jT9 zcKufs_`^@*g@y$ewS;v-{Xe}zGb=J?_EMuGS`YPC^?!tBGP%CKXFQy#c02IS=UI;k zBAYw<~pBrQR))=E)G-<`T%l>`fzkDqEp|~i)yswDbRE3ihT9>E=&U|AvB2@ zO+sD(Nyr2oP_VL<$7zl7{k=Sj0xF&O3R@F}?Ky^E@kC)uUOj%y(E4n6TGjjUv7efI zpEyYSdrw_2ddUW^0)q$n?eemzMsiQW4(97J?b8+O`=uk!X#y;^-;*YyO~SBs*LbJr zFZ~W$KP|WVtAE}sSnv!)F*y=5@bHi_WXTgs&d^)1(){kKgxKR}blCa(fU@-@EXZM! z#G+u1nW{?H<5KeizwVNLqH9_&x<SzOC& z7?!4s-3qf`H5cH3y+6@!{=lO$*Ccrsf)?!=d^HwvMVu?VwrnYrdcR(X24@Nq8!Y(X zr;@B*x;8$c`|yJ6xMG%Ta71X)jTcx~RL=I|=YEK(S=c%8(=BT1aJx3u819|4{mzH6 z7|IJcb!+{=gZUj;9c7t)^g#k{+Kn7>dvR1TtNUPjF_m3tuuK{WN_nJ?f*oa zB^nkan}3I#Qju0wCM}HgYQ(qoWDimY9GGnc-*#~vj@f7Rpoi}%)RSlPm-!M**Ma8+ zn^2^8$Dn@<@;95)1xWt9mtH1{<4g?`l`0r{jns4~=C|%RGWs)4TOkA~TSQs^6u)(*=$7&d5Zms7J?Epz*mm zmyh_~y~JLNNq0^J89tTKoS_a%^tWakbv=zVbY@BkOi$lm$sJ?5Uu|LqFC@g66=8=C z`j#A1(hT>+eqU~RW)F){rXy9;O4Msv4C2#dcNVsI=tay&^AclqW88*puiT1gV`1Ky z>&PU6zMg-xnJmMYy-y!_jJIjm;BRQv%_~vlx^@vm`(Sjg+WI-B5PygvUA+m_KL~p? zYs}X=rrBx7sJ`#auaH-tMNmlZUbR4b9hKRP&3dt7-CfnNU`A*%dBO0Ih1_r;LCqa2 ziN7O)%)5J~UGk5?@8+$m?E`#1{@y5t($jY=Jzsyft!GcE(v;4h3|YC3^x8UjEk%Tq zA3%qIoi|QQErcw%Vx+i9zD2pZG~A<1`|w6MTr(hyP)=Pfyd53jG6NOhE_%;Ox2O}osQMJuSP zmtT85Qj>b|-w?=(3!V4YJ^SIDL@q|I8ikrb;xoYL8>4>~sXws!8P@v9j|P)VG<`EV z!Kd1m;@grMs!UG|GN5)B#AFyexGs$<#ebXKYzyxW8F{fvBn5xSD&U~L&Eu+CFg6FM zCUpr)wwdbYRlBd|)B)rHXxEPczHjkLiSCN;C3w!&N@@SVF@(UoaYTvKmsy$c$0@Yt1G~i(ZSaENpcjEM;!zcRqcIO^ zuYBQRXlt(1?$vm)g5kC#OLa%uR(1+;#RVu}4?d#S%b!Z?*ZCkNM)zI_iP%JDgxL;5 zeRQ7Sh^U7TyT$BACa2wJXJwT65X~vJ%M)t;Pim#zWt=$Oi#1FxzVup0L7BCk=Ukzg zO$2w3YU*MW5mMRZufOgOP%UNZEF{FjUOQolM2_{>n?%%2d>KkB8=t)`fLct`7%SMc zKgD@SJ>?5FILueC8XEVNj)8}`%S9So?B7l2QNT$cf%TXzrX(NgDeH*W3h)(kRnmqL z41-9`*jJ37=nV_L=O2D=B)SGpE?-Ny7#8M1;bji*lJvO2UBc9vwisRDjd-;GE@0zv z+c>W{fb%RU_490XO)b3Vz4Bw)ANRBtl-MuP$3%%mQj4RzF?mX$4?D6gfy?KPp&Y(J z#or-Wi=%{fLp`vx_+3Nm1^A5T+B0%UwHZQJVn_Fa(fCDQAeRK}D^uKMhM&;S6&_>X zr``)4QjOxoyEE6*O;rwdLVIckub+B>+V-{hE|@d-&&iiB`YTDIzZ@hCkS?a;i5MJX zvcxMCANLs9uS{r9I3a;?(0Nd9wj7!_>y&mZIS6UO2(v79Qo@Q!aJpX+z9T|;T;A{e zq{6Q|1sHH$$ZVIhKq5vHnU7ypspy+0SKH)NG{BGSX! zD7?05T}@_@fy_i4FOk0Q{dJg~!{1sqvW&VS>MNiD#~@hVouvYvmrbH$ zM59D~{4)VNGBI-U!_lz7hd6nKNfHV5Z9|vh(fe2#6r-Ofp;DZ&c?LMW*|z%uh{T-C z%CiGJc4V*FRlkg1DMz(lGPtxhSq|>jM?YL*h){a4sgCV;?nNMr%|1|vG@r8T9wDoV zdsSEaFHY|I;bVU7mpi-o?)WoZUl&o-L1@`OIypA}%O}W1i#=@nk174m4Ua{di*a>o zA2q@4OZ0k{3#IK8e6g&Low{GzY*ytf9@HeODUII-v?=>qxr%q@Z33lT$sRtw@Y~_% zJC_e6gu%_GGq=OIfs%L=tUJsfx1~$s6p+k6y!oi^%k*_cqHB{~lY&SDWy~uhpiAJi zXfVLi8RGtJG~Z&WM_#Pav~97?SWt_p`{+GUgb_r^Rd+FDgwMN2Ubl^)*p&7Rq-ch_ z1X{3zBO<`a=EE$_#u3pwX_fDlG&Bhhz8g+p#;Fy)YVvPdo|vg#`aC-yK~|&Z!g8m+ zM)p72c=g)yLHON4#?Tn5UtWM8lx6 z*JoAk74!1D;T7)`CvSrQLTTJ)ePkxNYj$VT)Qo`lI6KL9J8v!NIuB!#>4_3O88mOv z3F=>Ez8OMxh^Zrc%l=%?E2Sq;ieJ+T{Mv{HpVm1I&Tu4hPO?2xs|0MGbOv6DIwbTdRSNT z%Vl+Gox|*M&BcJ-7iM-b7(MEpSi=4Q!Ft7)_v6s zhQz=pdC`^*sB4fSGApxN3$92vAnR#KXcwsGso+DNx2?Qw^1tC1CAV$PO>Ql;P0lZr ze?TS3AvlwG&>K7e1-Aql+|zg-uTJzSVdR>{aA^vPmzmoU9VJtMpUE@|C`fS6?!BD) z$Hbf!8(58EyWHSh+3h|%$`~?>!r_0mVO`>mpr3MP<)ihw*sMculk7m=C_2X^$a$>UYZrs%=T|dw?T?8no^i*tDJced+j@z;wq>mWxDc+=% zv1nDnIwvis@~HdNRi)T6EAw-*VO5{E2^@-~f!=>(*NrPs zFcT?GV%qLSpJw%3r_~*ku~pY|%ILz#BYI)spHSA*&{}i>Pif7P=G?q+6C!vAY$d##S0w4TD~Za_w|+zPk%(@(o5o`+mU?FcE{0)0!RY{GKcn zN5d*#Q4V|B!t?u^IVD|`+HPo;JLQ6c!MCrK#}>G93)J)*)0}&L`ONvEX>lnnEpJNf zah=0^oP3mY3^Ck#H6GHdYcxyv+XVHnA_kKKsVkinQ^48V@qUOzf75+6eUkYjC>AP2_T$erRx;He|D%RmKw$wwLp50-WH1jMrYb=l44U zUqC!jk7)1dbv5S?dMcVvIOgp;hxa(Gq)$^6u6jFF4i-_;Xc=vsuIoiD`%Zq55d@;M zqA2^fzk`S=mPn01A-|dkw{j~GeuIW$%@{b3E>ipXsKFRhSexI?etR@aCjr=J?j_x0 z1}OA6vawuEJz5=(OItHG(s4Vy78Aj~ z2gl4)Eb+bQ-dAiGV=3%sTMwkjfLW9Q-OZ(PmQuOI&4$gc>#tVizwS@(*GAws|DKqW zzz5MU8s;z^Phml1o%^OE5G)413x?tseN3%Zcb(a8B=Gjr<_t8>-KkGo4i<0uR;yqGJ|;g2!*9|qkWu(yKr!h&*@s|(sDMVsXX~aL>?V&D zv%oTL?UphqSj09?X2P0KBZN{KOwK%E&BX8fYrp}!+iaQC^UefvfQy4HZNMC7Ssy9I z-_Bt&Ihu}-NlBC5yQzby^hbLfj*NPYr+(@v-JqYq2=$%`4>P+1FMm$cAPz zC>T%rLDRPkT9w*8QBKXhs(h1nvoanR+#azqM)mcU%M38BuI4`jEE$wkPy*$CJmGz( znf?=MyDXvi$KDfnZZ7M0z}@D}eC1nx$M8E$5xDASu=++@TYhxXyfwa4ivRE3uqHb* z(Y~=nRu@b{{}OaIB#kdUzxNg!nz4g2A$w4 zH!2+@^XWT zYV_LOE^Qh1JC3NJh`acw^m3-}NT8TEQfJr`#7DFyKb%E$KhU@Jh5jIvpE+WEUXR1> z4kFw@S-oUPomrJn$FWIIxBe4Zm$uFRAmbA+$c!?9QrbBA>BQQL#$f4#3Ij(nH(#}> zV0{|}3uPbvV`*~b(OtqQg*|cw+x{rNkdVX~2hWIKs zGMi{RJU8=+jGdc)H5T>5b5z~z#Nx`jv)D1A;ctdTo=KG@w@~|~@4r&y9sP2gO_FEc znjvPHU+GGDrd4d}2+{lQOpGDotfwV{OZ56Tu*ooQnLXv%XXE=qq2=E~JYlt{tYarb z@+ChFU-2_2n;ZA@e#^0IK^iQZlw~A~9O|dO=suuW$qS>7ZzZ%a8#8J8<4DLmUhTX` zFZ@o5LU}w{s@9A3jKhDaS;NeDVy1L`DT>xgOX~Z6!XsXi4}X$kHr=fQ`{x8r=hqN} z1{XX7O$WWI^v2WD`a9&4{W0srlS@-GI5r+}@g8}Ze(~2o$+lHc;vva3T201UtbU#3TACNH=9J`6dJk&hX2>PbXn7Y&Q10_Rg`0w5Ic9H*HVyGNaLNeu7+q1tvydGe z7-@Kes&cu>qP3Wm2xIRJINvFw^bX+!WO}ABO^q2C5nPnX29x{K(B^vpQ!;@yM^6-p z|5IFrQ%i8*63YAcP2Z{{t%Ypaw=|R1cmB}43;1-MyLoaj<(GXmGMZStEVC~murYi^ zQUPp<>Sy26&kN~I@FsGxXINEX=i7T_yrp*>r)QKr4!G|l&yJsejnfUHLnz%3<{vJ` zZxVx9)lk={BM;Et=Sw%~4s9|Ybr6N8%b1dX7Ts+m+he^S6b&YC_Glj#;Wo-%lNxe{ zQA+=VKOO$XRWvHc2~)66{R*G^G{gq)+hYFv05;z1(mU#UL7{P!Y;1c-eDp`6o`i+D z3pI%^zX~6deBJ+GHQtCKbDCDJS7vf2gP;7$OISxdg?r_%0&P7m#^?fU%GEqM>M0DV z&AUdk*T2+A?LTpWP*%<75S^Iki6WN^)HvVk`mbI~eDlUf9C5agy6 zX(^qBS(zM7p~g&;HgQOVvN&r#<_X;2|6aSIg?guzyWv z-s>J1z7+kvgfnb0>dPG#T25{rgPCwIdgu3%Gt-kkK8YT5jNo{Lux#-KEFf}U+1K4E zQfFc3MGb0$2!m@-$%HWWKiqxvZa)sj6v+>h6hy)iNajPUY;ox$oo2-$?Vg`Nc)2(} zOHfdRQNbP?%VW4#^NrWX&}2?fi*hyNiG1=b)~HirLd0s(_3^0EzelzP|LvAab4wmG zy450A5V^2Mt=7Xhne}`~CeOX>1}XbcM5sGYzxceHqLxYC11`>thHR>&A$9pu;h8p} z^0gDU8#p_fJ)ff>Ys#5o;B+qD9Y=)SaPiEw+rhQ7i^pL9SzW62)U7IM49SI>LpZCge~H)VEbbOyG<1)9HW zSJ22`?MwxxT`K9&ncZ=vbN+ztJ)P*odTa#$Dwt0t?RY~;6$R2J6@EUJ5j@K!&F+_^ zB1PD^f#r8?<*(mAP8ROJIsf)NU@Ev1*+#PTK-*khtUtUDTp#vj+6?vUk+->9+Vcq= zYq2dqtL7im9&{V&~MF(T4ynYh{+ z6|3Wmmubr8%S(K@o9?jh%hl^6b=tlZtziGCM{*{TFQ3r$G?3hJaI|!?esraev5^xE z8^;-@kg5-M4xd&GX@q+>1VJGVF_YBrp9{?vzD7g1;8bNzM^zFL@)Ln(HD zzw76Fb5cQh7JNF9?ZE~IscQL>-7X6}%`i#l@V%?iz(HqE?`|c3FOA&ma_O`$^nb^&h(S|M~7xsv1qc35fFsm)f}?=oA^<&*?8NksHX>Az39 zTIf~FC@+XaBaB0a?lh1ul6pn`1*ph#MGK0?IM}d?T=LxB2-3B$oBbb|^uJlW_$Wv? znz{|Mix%yBGFH z-2UeGNlULNL7ZPFgFXmF^!jN_!Mu8l0qy+pBRVt&oV^0}M@GDt!M-pRnu zaJo>3f^kSbCm)T`D1$1FGS_f3<5TmG$T|N@G3?1~Pt^f(y72v9KCHA^?K;$7Sf(2) z=>sLS=oe~i_G7ar4;ELj^v*gSrhBcJ22cF7n`nFxEm`S_We7WsUv=`Zc)f>iroFA`Mk(D$mwIUN4 zp>ZxJ3{Po1{{b8-inm@wg zjE0G}Np>GEY>BXApgF|Bo@S`Le!t6=@26w!nj(j0lSqHVR`^_X3-a);!`gWX1;aCM z05V!a7Pg>bDP!d{S_%st&_b;2XnHkGl^^hDCqsr!_ur6gS}2H0Y7Cw?5;y$Np|qc6 z(Y|fKem=5j(Q}S)7^WZViEwF%b7ZJIto9P8W8BVvmuJD<$NqlH3DY|w#dh=*kTb~| z`on*@nq}gYz^Rb=`3OsW{=MApPC^X1zpXU>nNYN)H7IHfM@xIiqgJZ;%xJD5&Q*r2 zRn~r5tdc|SLz^SMYyz|zOvu9um(#M>y(LV;X#X&eyCsL5r*ZkceX?)qg%5wQESS^J?#BbYMLVE{p$XLQ~t0Y9hMFgR?|jGlQLP@uwfAX zHS(01QQ~r@Yr>4-6ImT&8nb&>w{ObxHS}`B@dW!?(K-)Dnpsyi(Wqsa+~?ipg|Lov z*A4N|2&%xAu!cC|&AngbjA%u^?wV7kna_y*ldVhr+kdFH$o4SL(45xcimbkJ|F`}Ek$6nvN_^H}B&6X~h*)yh0+Wj6+0M+wL^SOGC7Y=UqM2F=NzE;hYo%|{_ zzc-C{h^|&Y5hdqR!iIDFSpecpriO@plkaAZ>A{B9Kc2$Xu+=+&>osLBx~xL}o4xJV z`0xN-*37rhQZY@~Mk2bHJj^6y5ANnLtcuKM=MGyJKPcI0L?OTOhmJQr2=2-Y zf52}CKE0CPbg+{sJSD$WRc|%8v|plyx0cBxT-8_l$m!%COt%4RMg3X$Rhd6-%AASz zkj9_AUj$_c?OCQy@+#%GjOQyK22FJkw4D{SpG#FrtDtonC#B9d)&Y_(Bdy7Kkt$hem_Hv9^cnI~2?y=Ae9(<>3t zAM>1Z!>8(>Lg!NrK3&WJo^9E=dw!T>C72i)_y*Cdii zC=TXIkOcce^C5oudDSTRWYeq7^@HHIs@D#<7;!?F^5u#p6cv?KBt?{1YJyg;-hAwz z?%!_5(@I^l__EX28EuDsCU8Dh*xQ0tZ&xcSvhMd|SDEZbwKKgBu{JZ=+r`=O(YO9F z=XTj6IqIGpDmeI&)%G$VZO`mYJ9}@}@25P;C7P*g_gD^Gx>Eea{s&UYw9TPXJ_y{V zn+>q*hL+kKWpirsfyx3M3PL6CjQgC>dOb+$5KhEujn`vV`vMHrFDLBSx8P>&ytx#m zvaA%EMGzZeWI>1%553RGBq#N<@yop`bVS^OfsvbUIz>!7tA0dCMVvI_jU$a@%JL>2 z2*r5T;EdFS#HZ^_=(?+~_&Z{ac;YEbA#gk1if{~a(jGl&{v(bKzD85Lj| zs5Z>{Z~|Klt9_H{$!PvjmM?Q>*KIn!CP zK(lz{Ztc?piSy=tY)fzd^~zu5$ZBtssOXyYH$?5sk?!e+B$1FucTEym4-=9^7V+$^iB`y$(z-Q`(dWFf(m znM^&C<2c7d=TxxHlbH6wX_0=}W8SJE%3n%}Mt1waULr};HSt>-x2N{R5~+jr)}2&$duJFOiZ@7c^#+g?1%Ik!@z5RJ9rh%&o6v|;1T+p+raKe})E=JN_!)@U2*zU5gi zTn(h0PVBk`sj)2yWaYKNskw&WsJ<5VcPGaAT)in5pvdBb8YZNhl!vwZ&adGf`Cu z%l`Z!b+cJsA@gljMhM5EezZ}=(kah@u>bIAjmE$rjg%&U)36&Hv(#!j)*I-L*X;6i z!EU!NIwCEbdDIcsnZ5qX=bG4u9Xsyf?CEDtW0MbRMOsOcQ%9n;1W=9QGKOY-yv6DYcKrrv0h zG8SUw7>_ZHV1M)t@3zWdN)tIIL3JyGVsuaQNgVEEA3ZRguxM?zY!I98pJt~dQ=?q4 z%*PI_bhT!UaOk-Y-klE!pD!qHhH1zt9`GS$EPLfPGRjxqQPj)i)s$Fr;fjoRWTHHp zgh)uv;3s!4yj;XWmT>uo<-trzH=qWuAhlODl5%TRJT{E(v(!P6_lM74it)n8cPB!^ z2NdbW>g|?a*@PDKF`yf#xv+9H%uqP`aReGtr?xEZhzhA>V-Z=6w!UrHdjE476+Yn+ zw+dTFoWYf;rqBnrPO4#xGfIt_-v)tC#I)?4>1_iaZ#2Ps&C~*cd1mjGxRV&oDD1d) zPGt@+ZFmN5U1e>>B>_+EpP4g@d&zB6(_MZx6g5%}Ke|Mn-t*fW)ejJQ1*K^8_r|}{ z2;w`;gU)*^K>qU_Qq>tFEk-`XTvMIL)8PMwOV>$Tu|Kq~!34gs6itJF+pn(Z2$Qj) zydxFmLNv%Bv1fa;iEK#_`91jAuMS7R)PjyrBiM@lON-V4N1L6U3{?W@(Z~vKR|l0` zbvF*$;6p4s0X(OFx$7Q>e)AVPXb!xTqTY()!!I9LKJIQv3cOyaApk2~)#xy&Wd9KH z)v7-FrZ(ec_v!hwUXD$_ON3>Li~at%EpSJJE{?-^EymD=&O^f{+HxE~e zhr!jZbB1Iae&;abc!5$0LR!|xG@v|sURSMtRb!YxJGE8qs7;Vk9vx`>(A)k-$`e@AG(^ua^!S6bMt7V%1u3L0!P%jbyxH^LmGAdI0&D<*8Nl*Q^Uul z^Zrc0b+_SQ*Kw%2pNc<+j6~DU`K#D`=Sl+RYa>Q$m3f-7z)gH4{z_{D;rhVV?zaxS zJ)Olvv}HW^F&mceT?x**KBUy#jkwFgPIa?PG8fo^T%024Hd3Ea)Gh=0w58S`Kgq(| zAg*jR56Rlcr{vSsA6y6pu=_(HflVuFO!s@t($N$z;{(M#8BJ zIR^QR+DrVtjr1d7ER;#xvFdYX_gYAk-0D$lUlGa!)Kx0~pp|eoICcJk$Emt(k|P_x zx`C^i8%x6dt#XPYSz~3K^oJIHLr&$AGlG`(gt~QyMIXGLnli3Kf4f{)t?5)}Hc>;L z&=S?sLmIR!H`Pjql+VTi+&}-40jh2F&hK;& zt8;IWNx~l0i<^x9(Z;l_#(1Zl#~{9cgKjZTq;ytU%Yk8dqAfJ{*|xymw*Ssl?m>1( zDV)XX`!~KqgCmw*DI4}4;*rUSyU5qCUjJ`ie|+~iv%>OE{>K*){<~jv{jVNsXXa#K z`qxwKEWktk|F55F|NASf|HV`7ENtv7EdPED;b{3zY09I?K@sH@`oc+ zp9bvQ-F6-%NwNNN@)bC_X)M3te!fM7g7Q0Y*=z!IkJ z%eN#@Q2MAebaZs|^h@=&tD~vB+1c5^8&XV6Onm&klM`EyX#`+x3H@ZKJzzm?aZSzC zy4}|9uBoZ%$zna2nVI?ByLZ&o1FNgPvB~?n#K7VTE9vq!Xeg+e+^npurKP3I%gfu_ z+kt^k{B^|W=t5`cz?#FjeJTzpsE#HzUEO0Rp5HFbKTQ_vZS^cHEUc`o+}zxRggSP9 zCQFdQ02b;nwUz)@oI-MQb2*Z&pP&9nNJwb%p#Ttj^(teX9MCsIIB97L7>L@l?}Uqk zGjCOwl9Cb@7S_|#GcYg^6&3Zc_)YT9@6plGad9<9{SiSyL2GOJJM^%Cl8YqW1Hh9ttVZp!n3$NZuCB+& zM?l-ZLNn0OA>`}pOXqIp(fS&2|Un^QZPLH55 zvJq(-5de13(9r&3hb|sinH-h|blygspF1=!rzIs7ntspD$^ydV@9$q{ zvuxopj|>?&;}??IkPfywYIO zmo#E<6GybP@bOm@6A=+%U|;~i1~51eU{HVh_U_JlzUt$Q{^!r1J3Bk`)Pevb=JvE1 z6DIek0s^_YxdCH?gM)#T0>;ji@mS1X@(==&By(GJ^FPOauCD6MC|6Y>0YF4UOHfgj zmX_Am)>c$h3|TDGX`Yyva5-7A_E32RsBKXL^0aKT+V0y0G6t+aaHFhuOFWy!2$(npJi3J{r_N|krgwOWn)M zk*GTf#1v|{q@`sEs55|Hc6WDocJlJ`hdp@t__V)o09F|W0udt6P!KAnTEngXrqHpq zwG|%(!-zZ?$^{7PUvZ_50_gWXW*x4QuO}pBc@GZ-MIVC$KQ#zSQxMY7F~ep8ijsn& z+iBi*P`Z2y5Q1U_k}`eD1P0rtH@i{Od0D$rANmpk>`;N>1wz6nCO+Z@an1h>fdOnO zPo-X~Vru093J+=~rK*YrfK+NKgO(pa1|+;L1Ee1~kgFg}t?_^_>Brs*9dmQ);V?ib zOD6vc!u=I&0@Am!u>nxnKc!kz!!|Ezwc3^%0QiS*`VqQxzr(@xIt)fkTwDv*-?dRg zp#xP5&5LZ(lJUjOR)XW|s_{KF zdY=J+Fx}|t>M9)){yz|@wZu~p+LSI&d=W&=|I2vTf3s@}bdS8eAx0W{`Y^z8zpE}* zq=L!MfVpWp(5(n?Sn%4_(%|S9gCD^O!z$|Pi3thyK!*a74)A19(5rd7!O`JM7j&qK z4-8>29?tM_L^ChNF*zxd&`^OQ4gU5b+@htSk@UCfco?Vz1Oxzla&aZToN=s@35nYE zJ3!$T6%_!zev-E4{tm0q;e$7%v@Bt#(HZT8|NGy8Hb7k zb*>+s-1X1|69RA(kmTIlq%v89Ql{3v7a*T%Xfvt-Y-Dd=xoiWbrjGjf1hhaSLqjKJ zNg*LW4nDS4EqEyUNSR~~_dIBJq}$o{Clxt3OKc``@(;~0Kx90`pl^GN(9?8g1w^4vLfOe=rpf#}X-7t{Sk}^M_ zk7^=F1C>q<$`z!in54sd@vAroC^QSV#Ms!_v@}NEpFlXr0s==g5d7k^6@;Dzt(;>+ z?SN50I~-ukr-%0Ehfr`E2V%7>ky7vZ0{?=!8Jy^7Dh5)Utq5 zPk8+EXB+ci8sDxzg5(DRz+F>!AkXWg`NQk&1ic?+Xwc6l9{d1*L+M-7fWcrI8hb8c zO}-@nPyiOyxur{c!l3~lUs#8f^hxjeO3xuREIeGs;o)KRxh%e; zrlw{Y0Qh{hIP7Ol%pBSv_TfuHfTw{8KmpK}o}QkRM8mrZpys7Qj}y6vp}hL?WRh!8 zZg&NrHM0Exgah3zG9)Ayj!YLC_2moTlbAje$(JeBW>;pxVx&u{O=I3C3?`s3(Ku=g$`02X7y_FTI z!Etv~r`bh=1cv|cb5}L~CrR|Sp39+^F!+@NVQ}Rl2KqvktE{Z-OhDjboptPQZbwC^ z5@Hf`Vr=Y703htZAOZBF37KI(J+HHmfOn*bvd@XGJFvm8x^|OvKLDzrPVH5@ySuuC zlYhSBwVBT!9_6Q`{0hKbV8r5e!5=8trAyI@H?JbX!^1;ErDSDS_6-cMPrZAE$|<^a z?}Xm^&zVVs30@Rg0VE?Lo;wf$6pas%NFIh>CkRZ3#Ux9H*W;HjU)YiGad4<+zXBZB z$hBv$-zcwc>T`26pH0;k`3_c)7$XPsl^aXz3uQt1`8qag1FZ!Z7T*MBXJmkY!H|lI zii1Oyh!g=1&T6@7dTcB*cDTa>=qpof8D1$OA|e2Zd3m*v!qsi~YQA2oHXQ>xRjZ_b zXbF->E?n>{m{3y>h8N`kp=oMb)Gt<7S3@?_V`4C|u&{uB3{088Fxi9-vnIzwEGiJA z35x;@8`Szh9|bte&@ju(surQ4g4zJ*tcJ8jC6=*BuLlvyy`Rp#iX~dsXA}iF&`(s z6gDBPNlCA+|3!^^gEnJecXUF+d)`z41V9`B0DTJxU@;|dBNG%994qr%Utb5t0f79J zfHtqBv`PT)mHrK*Q|{C2iBITEU6-jZ6EKvjC@@9=4S#aq>19sQsS_+LECgmA0L5vj zXfm_revs>NYJF+xFfnNU_b^%t9YA|$%u8G&z|j6K=08G+FatALZ}Xx`-5N0C?(R-Q zLjx!vSxL!|@bKx4bznG_nRWB)Jr9Ek`1;lDBQy}sQpvR{WwaG{3%BUIj+>8g60cz_ z!}lLpU(_USIW*R+8~h#Z3;^(IYHE6UJzfKZYQ30;ik4IzHcf8JI!3K8BqWrPi~}DQ z5g`k7D{1M=A8%T6sMj9oJw>D9Ko!S{ZSPGznFgpX0*xcA~(hO;D zZ{PR8oT>kr%xOvRD+I=7wM{46@0??jI%5>^Ze(IL(0vs5ZbYM-4HM4m%RUkK#kLYO zASlR4NXCNkDJjGxBqW%aK-;UgnioE@>%Od720)NJtBH*2!Yf z+u$+wG-GE^{gLP37sQ?LJ`s`h0- z{(TK>NPr~2Ol$zGL`C5c5g&j_nK9n_70?eBsvx0&SrA~-PMFop_R~aQBZ7bQa~&mo z8VLf0!$H#<-wOac11Kn>IMZ&CfA$%Pi9l`R5E4puclR!~xL2EE%TM}wyyXHC^6s5j zGmHiFFQ8l3vP>qQKVP*4WqgNAAjFs|%9t%QDDsCA7`hC{c+q%D26RCMh3KCqu?$)s z9v%Q0Dl030`ZO?8swFeK6*gaE9t-5vRILM;N&$KX#wc|i=#QG33&+dNGAGq|5DmiD zZH_ZcS3*$fBbTTz`#Y#pa%3XXE@pp}3M*xUprxtA_zHD5JAoxx791q_$K7SCDd z&jZxh{M&Rv%eiV=vwKchDBHXfwHFA+}A~3lyK;?N#BVK=|UPGiO<}8VC?G=Yxb+@<$e(wyJ1Z<4Fzr1uPsFEN+RbOA9 zNZ^}PKKJvZ`Dz^*znV=7laj68xtLy8PM#tUt?m)S8fm8taNl8hmsj11yo>vFchqL9YE$$Z& zC+*LU7+b?zq1zf@y|$FJG*Y1Q@$nm6elHX%zb`siS zjhKI0bwFzb3Kj<3TCDWy_KV+8D{M$}3kwV5 z)N6*4zQcw-KDtl4@7})`7Z(o<2-w{CahD1vEZ@W*=@&I2&5McT3iL^WpF~ zFpX!JUN*86>uOrW$&rMl%$XvD%yam?9-Z&+-gVbq>)wCvTKD4d1vu55|B{0G9f=g~?X)gyc&l3dG93qLoyI+f%Mf@``Gk8Z!%k`h1VsdhFFezc% zAoIw$Pn#fEQ4yV-X1`_Xq>X#=;Y~J{`g{{(W5H~1&W~yu8z*9`xr{z66L%|>k&?O@ zF4Y#09vJ;q>GKJW(QitQXT-V)d1~=4whj)bJm*Kl51*xGll7YJuWoB=%iYjG2v2HX zx^xMZMpM&tH3yU%5cFfnHc=6gqF1l1=%?QY@5M3_Ln_yJbEb}sP1=2WsQxjNpb`FX zxFI_Cdz&4-qlg|AO)a8#s~Y!Xh<&JhJw5z_xvgWbI_>c5jeS;9k&GlST{S%{$Kg-N zyLh(m$D7zTnllClvD&l?#w8~{)*9M}L*H_Bb#*F@*j+kiAVwUHR}>K7>Z)hw#0Pt& z6u+1GQ75T@5gqSTXEQS`m{w&W_RaI^NY2Gw^ z>yiPD3-?C7eEHF$u>Sr+e5yS2u5DEm9>(#G8ES9pZ!az`*4Xc)VYNd6&&K|#{P z^#HrmYVne;GlR9if7=7I;C-3N;^N~|SBocxxV}B=$Kr%C2|~E@S(_}*&p+wQ{9i>lLT?i4%wW&Ts0f ztlre~ICH2E8(}Ct(dXCi-?Bb`-jrRsnyCvcrlFCye2bUh=WUy-wk!)I-0Iw@ta4ZT zq^50fnEkv8k!-ZZBgaNXG3qTQ%6jXk_=(x~eCFw2Ut2;lNR+vmc3A$!MmBRcMN?yA zeM3%qVD{bqvnu||6}kx=zT$iwR+q?he%D29?po1Il=cu77w_oq=5sjWVO-Ch4>3_p ztbLx5h0u2Lc4{SqD?;w^5p`DAB^BwxH0L;`MU^b4!_h=3h+k08;-)LvSDt=snVX)T zzkAE2goI4akjN0jM(454;p(xmvHJRR**gWeIe3iwW9TAAnm&CR4IfBVB-L4EqW82b zDK0K9EYuPWp56GXRK*$Y@bj)PIO3If#eTKpSG1M2YpY@Mq6+8MBfXv|l9;<9;>PAi znr-Rxa&sLV9j7SWwefl^vnVpr@^u28flCCc^GgVUjz@Kl<4%K5|GH18@%129N zk@Cr<%N+PCJxE(p35sxt%gAIeobKCL`!$}nT?>lK+Ulx+aRtAD{0jR;ZEZ#-rfxe? z$U)QBxNRNB^={rQ?Gc=pi;ZPamUbGto0aw|s^ja|i{sqI46U{@7)Dhrzn1yrQNE7W zboE5+T4FI82x2=)vD{yM`-pl1k~veBUJZ6`my%=8wQyRwt$6f^N??wfy3)wJIPkLH z>{Ds|ZVthwA9W9=zL&OlcO!H?I(KR7=yXpmWjN}TAKcUP{d>6(#qv*@ih~SuB&(JM z7F6oz&+8QiGU-u%JzOKHd)3M5!p_jF(!(|X>gE6AF*X#*!p!{EXWbLoDCwV|p%fi$ zZEam$rJ8?;TKnq$`!)hIqipMR!#|U?bcRm-+CRcwjDm>~Y^{q1Qitcg;jbB5BTez+ zzkgTYHvuqIRrxWH#XWiQBq70P;aB9?M~W!b1`X|V8kSTK9y}0qZOcnwer-Xe#b9`7 zZf!XT{urLQ(6_|?8=K2yQHzzZ*b$dfv@dhD}N0INUZo%TB+hjBk&HTN>HabY4 zy`6&L5=0?;{4PTDa{HGrPNScbQhXIi1P$MO{{Gz?<4N@0Sef}zSGln|-qRDOL;Y~D z*>gz5wnI`xT2%D)^4(|Ols+@_%O7_P%aeUFdjq2F*!Xy<`^+Hbo%z54^YouCk`U1# zWsSXrPQ}*hD#(8z(|8aCFv}`sPC-EfXg#ilKm=_5A15f=hG+mCT62Qou=3&ZC}4ecAcX=QP;oZ=i{qkiN zsNPAb?FkTr(6vTdT&Q}g{J)8Y#xg_VF@9wy|vYOyzN*v2~@W8(R=c` zPIA4VmGd~@)s%%awX0dLCe8Om)+u7-ZFnGsfXtS@eLM6B%crZUIp8QhJ3A|0LfP-U zFXwpm4KNo~HWmq|p%*vrV;I>!!3oZB#P#<32GEFHogi~_v2?1U)N{ec*S9i?giXeC zexmb4*tUoQVFw0-MJ~54>k} zJl8zdYxrYiZ?6#_1rpvh&wm~i)!Me@mHmTM6w13ppH}W5KSy)q)U$=tt(E(y9rWcR zmPS5*)=*b(#)Rn`7yzv_eEc{&H&<9tpsI72kaZ?4^q;D;x+MzDKEaZ8dW+kf(rs;Q zzBnb@?HS5Ju12s&X$1u3R;()j-Y5_qotT*T_3N$Y!Y?f4&K)~m@jVmuI81Su=JV~E z1g`4TCT1Vw!*axDU+2 zMxE+}?LPN(4>6BSB3%79>;Q7XGM8Dut$TUvA zq=EwT!Zi~F<;4r3a_4PO179wy7j(W#_5*S$cNu%6NP>*LG(GUoB!xKk0SLy46aOrU z@<+C34fFvM?L`lD#sCJWWB-Zy-@w%L$l>i=Y{>xiSYF%qoch#KumxD57KM|2m3=Pz zw^vaJ8@wfH%i4QH&B|JnMyjDr@%O!_D)V+Rx`4}L7M}m?AXM2rjy1V)cO^IJ?6Nj z~MxBIHJ09NoXm|hIeYR6MB?_6z z9fLn(RI=PsfC5dveK?r@`t|FKjQWsm2@=jfV;w30aZ3Ic8EDd=3d_rH#^QOrVw#xS z?mlz1(d~6rvEjsa&%QXGVH$GFPp@lQL$(EUuDrb5$vHe*!`r*O#~Tk1KDf;`Zj6H> zPp%vxK&-F$eEGs5ro|WS-d{zMYowl5`~-f9xhXXisgLD9L5rCL4BsHkAye(#xpS(o za&xGD@8qX6vM6Nx*j~MN(d)l|O4#Zi_78R7d{G!UJo%D{1|cQf60t|plTDwkj;5If z=k-|~OK0<09{3bljrXRf1r>5{o; zF$F=F7cj`q?yI$-HvKeeOu^i*@o`i`Paw38j(w@8vMM0`v>mPq4JNlau5n=3FB95$ zkx#Mvr)7}s9QrCEX^4h8Dm0i!J7VG{OJ|FCyc#6=v?l^S1YOY}8n)L?!37=>n=dTm zWSoN;cK@k4D0jSkoXn5vnklu0#~G5FH*bOgvu<&?y`7iF9%?8137t9YKfBoa2rJ+o zPFrpKeZD_W`i6~-a>au*qMCc)p{R7kxS!#}3beIVd)O}z+WS}QMCj#b$4^qR;OxE^ug54gpp?J)yx`>e-)}dO$eP? zoHQsg{P67xU~Lea4-%OjX1+1BVYr}s5{__G^jI>PpNK-Uh^;^i^I+CGoq>VDIOhDo zfubl~J-u@Rw1fy~vCe)Vz)tHCp}*RVeZ2?X1z@*B&DfZ25bR=rnzlSUtkT*o*uQC| zFdbhQD8lvT$zAM{;b5b}K*+7SjEGVJ4X4iiuv8&!kBx;N$eGZF8_x~ZSKn{pql@0Q zD$n6a6+4)6$OW01j}N?xREgLLg3^Bgd5yjOWXXGLdLpe(2Z;l~PF0CMNg*ySPTZ*@ z&52-2PkZG_*hWNbb=`Urr6DPWKl3s`Qud=#KEV31XmqSK{nW;CO3yR%8fXa|YvHgl zdwL98zcHD33thG*^xJlIcV`#Iaaxn8~;Fa2=xwe)8TL)79YgA8O@Sk9cB zDBB3bil#UTXDkCmm3gQ-r8gW*b*f5ABw7tP`hWOr-fm(HFaG_=f@*Vhr}s#MGeSg{ z39j()Hm-J=lAij5f1-_jN?ga=0(LVEF$xxMz?z001b7UzZltP1Pq4Gnu0*zYQKDeG z7=p4a(G;;L`_L4Df0syYv?eT{qx7GiT}#&6PGy& zemCYmas6Vk^mtac{xmjrSPsb=o(7s8671UylOxss>?~2JYWGki5!uPZ1OpMQ<=4A_ z-OOYx`}VjM{ft?ch4bz zd_m=8|**kT@(Z_7P&XPeZ z2!JW)fe`rE(AHarSxnA6>FwNJ6*4ywZ8c2idf!<^CA8^!oBaEC#P=o5yZ1^gLy@GY z*w1UnaE;X&lG4&rhn_bB@HsaAlqizK&}~b+>PqW1_cJVt6fawDK_$q|Wrb-_qiR*! zLx>81$((xk+jL%Wu@2+0g35N<889U~?*mN&3)4tjfYIRsnMz{=nO^sm&bux_f{H6uG z|8nm&ZGm@ARGTX!iMfU)POJ0QdMh7#li*-m6vpJN5>&2uo~0&?*SsU*pUz*=#Lk_s zUxzvcTb!THof?fMHzrzHOJ#~A>Iu>wh&2$w4Iqv6^>rFlM}W%F(HEGG2)X242SOt0 zyw+D2Mw*%1v}$I(?~-q;dMdJ26$4hW2n7_(tgKOIG;iFvfyKt=7M1?g*qAzSsExl> z%7HL_9-_ot+>ah;d|h3?ItBCpJwGD&MBoo$ihWAeqfS&z%$9x{42+0Cu<5h5lnLMU zg?3=wqYPE2m_9KlBqSi*RIYLI7^ryUh!Te*!gic6O+`#QvkzEhzMN>7#5JQeHADis zaHzjeb?P~ZNllC4AgvgvCY(^@YNT9!m9K`$4Cf)y$R>)gcRZ!$cR1nE0Og7?6I+0& zsZC9>v9cQNBf}$##uh|O5-b&n5}&6{hjZI>P&4(-Cgw#+kw0Bw5$puJJ$U}_ZP2$0 zelxSMM40PZTBh6Wfvq4XCkIJOO^uq0CjX_mSJ5V5nfGu(_v z{ey@7yOchMkpIdsmGva}EukyPcWp7dNARyq@V2zHIZop60TR7AsrV+e0=1fRE{nHH znGmXuctVy~DgKt7l$4a8-|~`+by2>k6BN3}#)7`Q^H7PP&MhVael}$g~RaZ=3`N5NRFF@H%8PodpkF(HZ!DR z&MBwIMd(=wpF4lSJWe(0qjo#PVG73N3kvrF-h}foJMu;=P#$Hz!k>4`Y&?*4EWVe? zGpTeevbWUQ>h}_5`mCyNFfHf1npvN9$8qg1^LHla;+(}3oduv|y#=l0I88wgS=F4? zeYx(`hUUa9T^5~LdI>su6l6F5%r(od-CLtOwcLN3=G33*#1o?HgYh?dJ&5vOot~jX z`9fQkb`|&!#1ydHCk~`yqM}CSo(r%UdDcnzDUJ6h6xlALvg&r^m?m-FmGj4Me!u)v zSms_+;wfVkQ*CXs`bxVHR8I2wJE)wgK}-P=D2JzeMcfVK4BYr zF$&BZq6RAzLL_?=tBc+b$~4(J8gUeFt61v2ndr01>m6CKJQxaF4q^$&$=t=$Net5{ zGG=GP37KJz=1*==^`X5IV85iqgQPUDg!4mj;Bllmg0>{9yAn+u&`NuIJ7n1x&!6An zSizKz6tx@G1eiZLGjR`ndfE)84^Av`F-Gs*Txs^LSo>WHvv07wu`rNJpgB#!^yo7o zx`(m>z@e>{b=iJ9fdJelI_e)EiGBJs$FStxx4@{VC^!j8414-Z`0Q!RK(jI2JC|#k zzj7$O;rvh<7{Dm!vJ3C}vc0WMkw(h%Ps{cQ*84#7(%!2s=H|mu#|(JdyjO;!i9*H~ z6~Xf9ce~BnGf%Ua9f`mqDtd3MjJy*Wc_6#0^ybGWOp-_N)m^`C%~$I7Q0VIGAH~&& zkm~aDXTGGWATgBPT*~RFK3Jt+eVep|RkzI6-Sjr;Sah_CzZESsR`+BGJf5>(oEOn} zhBmIX#mSVaCxgx*L}dNoR*>zT4r|E5Rd(<46a+Xaz6TS*bLGZ@U=CN)+x|cA+uj=& zZ~IdBWeu%X-pvUz(BZSPvl;YB0y6x1h?L3u6$1(Xts}pgQQ#IE_s{i+d^+YoZ#K{- zv;(t1_@f4Sd|oJZC!dTdEUk~*X;f5Hc)5Kii`qr)I{a=0Wj^XCVaEWbE?u}#0QDVe zHC7&aZb3ywMSi|!$F48Jx0xO#8xq(Ba&~?Z{E>CJW{!B!34f1FmfLntQ@wZFDMi8PEL-j z_v%S9PBhJU0^&ew(9eF|J!xOuJu(*{pJa9Nsakqr=LGc1B#jRvbMOsfR0B6mg=17X z>GE~&8U37bk5fypzlvhR%FO(zVfg!rw{PD9-*BDivb=jRfFw()(w_GD#X(q8yL&}G zamg9+`!k~J#Lqm{y?x4nvo zD2iSyU=27WAgR}EY*shcrm)Ys=+3FDKhVw;iBY|Enw>Eesd~N7>}gz_YIG>yyk>J8tV|YxB^)VbaKA(Lh{A{~bskTf(j1ZY>G zVF#^su};1j7hh^;9;7~dozFx#=F?T-(91Ml+VaL`qOqx)(n*5h?$WH$4d$Y;3!dfj zNe>%_Wn^S}qLm~iB|k@#X9j=f_`nq8(LN1ke21}mg@*1q4XqnhtAQyo=~OY#w5p%d zq&ywIorwngg~!$%@}{xxx~pmbA;z@3Did~e*z7McZQAh8FI|GzGyzJ8$%)wLLkDJd zc9;Rlg6BGvsgulbMCnVrie2EdU{#MsQUu6Xn|z*hdvNdGlSYe_mKQBn7mr373b3)T z3^{RlXTPUzBP3+Gw+qqG(d(0roKSLX%Nb~E(>Bc~54nXf)3~>j^};7dL?QwK4y8u& zO!ZE-GLWeQqIOjY5nSAEQRp3LATQn)6%jGfTV4t$vaHMt1TKjBpd_R-n6*&y|B3Or z&iAZuie|@c1eyU!`$d^)Jq8N0)zzW7m5F;pl)qJ;3m*19o~@m^HA0GjWXm1xbW#@5 zp7Z41!P7kq#pD}E^zX7wjreC(kNHb0J#?UQmf3Tg6o$D83G`;3JJ0U=%kK^mgLzGD*GVLGWpq1i6PY11C_v`GkvOk}b{sD5z%+0NI9N4B#X6N8A zH8!SsG;+u7>Zzrm8ln`KzuV51$=Lb6VoJ4%ql?SeNjC$2#=_357OSr|MVLrXF~FkV zzZG}U{>*UC|F8{#7dbF^xdubcKSgYi(Ou^mO%?jtRb)$CRjiw}_1Fl6=ig8SSAS&+ zRxINy9$sIPpSZ|?eNAI}v>*O5tcy~IK3RJ*Y1dyD|M_S8@IpkBO6mnH=Wc&QrUD0g zDq1Ms_^UR37_p z4RD&5?Hi9Bm{M(1NA1vl6mG}0#cM|V7kW7E3Sd7Ibg6m1Cg}zYMu8i|OE{;!efzW^ z38kcRvCEd&)z*fDKNu=#)<1B9Rw|c_;AdHgK7a~pYlt#alwad60$PZHWk zXz!niF(IfPG%@Y2SHPk=l`Txr&3>>Bnxd-O@>R?0excyzAD z>63<*l8)7u**>WYn`M{VO5%Q(?#XLYxI;VT%}>5NI#?SDr+0XG7~sHqrmBX?$X#xN z?t1~dn-e7=FA#kl0SRYem4K(5!nOgaeS@LSS5(NB7}}p?zAT`_L$93PYS#XcV1bs@ z`N#W1Yu^pz^-V3gOH&8cnB|Wyc!nvaXz+|$zClY(X{iB6_}zmvId(l9Jd|{0sAzM{ zoOjLGF_8oaCNSzNk=_8i{}Wn?G51(q79BaQe7R)>7E90X#-H3y$a0tGW0%oJ(=0mU zX%0$W)X}*CGwS0guguhzu2i6(4HFpodLQM#mgoqD$tR!0?zXbC|3(ZfQRJglx`6Ot z6rAw|$#}KUS~H=25z48C0#lQd4B8UA5ASXN$;xQ@kUg4oEb9#rfCi0M+T|KUy5~H_ z?)l{U#QjZ3`1at`#)s`RxzKOWMhXc5f;`bd{-$I6Klmg4)cUyz<=#O$sq!5J-Q)Oc zTAG@g81ApH8M`6Mm3u}OIDLG-wzf9xR8oJ{Nt~tHL?}`@`0{HK-L}~kFUk1(bw3ak zd&rT^bGVqp6tlG(h81E||1H&dPtA~cL|~Uws0mzgr11pnhtD)<=y&Yut@LHvNnS6BQu@ z1(?V&^WliwH(XsAinj&IC%H>EX_2&0kWYKH2!0(Jx+gas z7pZ)vGSb`I``w54=HH@uUXfF9$@PjzZ~jm1+X_O0t}KsGiqHcyX^L(EqcUAoStFwj z^jB1_{EU59Rdedk0F7DuA4d5JmV*QnUPr!ubla%MiMM?H>N43SqFg>^hjlv0!a}c4 z@?%C^*_Xgq3;2MAFZ7kuaC>PW(VDXSE@FuI zn_$$tx2aEzJl%`*&KC@CjD1PfN>{t2qchc8zJ{pt7>U1O)0I|nPs3#Kr&1_48k=oyd(T&_W? z-Rnk`at7#xU~(y0=>baK9(SMxqDu$U7Ln$=^!)}gc>{&@peDzUZYO*)Me`H(tFiaO zx8S`;UYAp3SJ#Z4%OQ#4m6O`|ocT z%9ncA#v$LMs3ob96Kor^GW_KEOtiFGBl&dhXrE4L8J%0%c8g&C8~;}z`X8A+1fL_n zC58?*j=6YxdG$;!5dncJcST{=#iL{NKzf@#bgMe^{VYikhab$Dt@wQwi;99f#tB=yRB{S?HFxJn{pNtohj(SMVBIz+ojsr!E zp#kH!q#r&Eb*)^4f4f>dkDXb=RUIBqo7h~paN1MdbELk$J|IjqbyLXRm{VH#c%*Vm z^*-vLb)U+uo~52Tp2zj8Yip3qktTbd-mQRHi-m{m1Sbhdnwax`edSfIN7rhBb!!?? zJ^t};Sfy`&QU}*gf^ORA3tD{=DEuIG5M||q=!&;ppu1M2&s&aq5V0t`Poj+47PZswXmATKLH3VKT{xAEUXAyc?%F0R9r~8iX_+ksl1$wZLQZ%-4WUeI^%Y&a78?(+o)#5Qwp|IM_ zxJuVLcG6pqBm6^0$CK{Kv|LK>r(Q9hZAUE={+n9AOH+_JrKgF)3rHsf|L5;35z7D) zX#3x6+D=34tw)1x8+8S(7c6Ix1~>%>_s?=Iot+Zm;!5=ewPr~Qv9rn_kJmPNk`Oj* zp#mp1A9;LEz-z|q)Z_Z+tz!|&!*R#_QOvb7E_#;t+7uyYR`#(`1PsoI$Gh4(lOJu@ z8ROd%rZ_f!?nvcl*K@`fR`st-jL*k4AME)@Zi zfl-fU7x(H{`pEpcL*V-WA`YZO6dWKzW9LCN7;O-&M2E@;*tY_g-x7D~>*8VnhmZGp z1*w6;_h(!T`5V?z4={tQZPASuV^2a9Q>0UJ-P`lzla{j?V>_oQh z7Iv(mK;4mEG%6}v)6$i3YXLt;!RAOvLbIRGSDPuX@V(*-LCL~Ajst_Thr7wVI=|GX?g(A9%L(rFjPDOh7!4(*QtB7u zTqi~;M&j8XzfHPQuWflRBO)UKY}>wlyH1r?QnG?b1-ppY=FG=#-WVaJMa|`AzmqUs zs;aIIGz|iI&>m+Mtxnn$=?BOkw+v-Z()lueO*FQ9^5^i_ynUw~qcffM@ztLe!ZBBc z&-K}F)bBrd&{dpe-fL*%LJp_%A#KRsY$LLD4w&nFig2Z(dfdFR$W5G|ewJo7^ zhtLA$B}Nr3psF#{snYqn{Hza{inlRRkma`u6a2`M_o{Y?#3^xNY7|rQ-<+A|Ee(uR zPE|~4LAfbUkOfsc^0+?ojqN^0_3OqQn;&LAC~RcRt$1NAMPtJfUeEtHDI|1Sy%%Vg zHReNRT+3E#*|g!^%eP5%1r~pQH_+4bfVi8B4itErXs&x^yyv6TvM5V)Jxx%}jJx54 z3kAU>A7s)+QbtzR2-=am`xB-gO}-D=4?dAie6W-E^8pB~$@|EgHGxI13M2e|s@z3h zw~rs(zaPhs=6@)kx&wp8sU&W9@ZV}8ywa}EP&EG#{f3sWKGF;`wHQ#3mHFqL{tU)FV|rI+ljW;&E^c)i8dVb z2c6+~`t;B|7scVdH3N=9`<@@E_->zm_S8C|wYgB0dwgmN*cz1X(SBrCv!D@Ts3y~v zKHNUdg4M}{m!uiUnS>XI@b{S1-8j39WsvW{mcWuK9Tv?#ID( zKU^r$7CM__db|4Bg^YxPOV5{o=P9Nfk8Pw5y6r%0w@SZ|f#WHs(yElto~oID{3-Uv zUEjdgvFC|yDJ|mC(w}NXJ(eg|(M*Ft*;87zeflayh>jv#9X-AM>STXlVSw66NA!gRro zYmXZ(PB4cd8)sZ>vV8bVKN}@(UQ-~NZx8wBHB=N;?%R(UO-$Xtt4p&!P)wPZ8lGF} zu@|cq0;~3EA7yez3&1Nlvp130TdGW&sd1gJAI)*VIypJ_4M=#Ue*-qNvcA^k zm!^Ao;k%1ue51v2V2IPFg9e6%p6A($(*-Yk$yQKHB>tCXp*dI-hTXp(D1XQ^6KU)f z`8IwkXiFphbgVH-Gc@b6UmQ|f$A+YudWb2-W4nr_<&nQ@5*&Q_fDq%6Q1fEmmN zfHGzSB4p~5*KZg;Pc5BI(LDKrK=@>BV{2%c8X-&G zEc&U5M<*;qOad|%vIenX9}P!nU3&dmG(@FH|JZQS46)=GkOcgu&;Mad@Eb&o{$g@RMS*UwOAn~|A_|+=o^9K{u8uO_%aQm$) z90L)KdA_6&%1)3b6BJcWy?|`ErA)Ta;vAHn=z)WB`q@#r5=%&#Zf=7%L3Rbz!9eZs1I<2WGi?0mvI7lE3flc<({B8C#V1XvxJJ$1VAA6ko&>nY}?+$&z{W8U#^+= zN0hKWI6_ZR`{TM~vB!sf&#EJ-q8|>vhooW&peLU>my?tSd6+if+8&WS=;~E5Y zb($qEvq&sT)hwr5fL&uJ+DtB8A~HD8rjY2>)zv%NRp?sM<&RS3uD!nj#d?pjJ8wCT zd5jp;xG=}6a!W>el#T-1Z9)B;z236M;w)*!&}MKdo2Uhha>5~Y`Sh;^>20~nzUCqY zNeQYQ+c(z(*61`(VZ-bR?=Ua?W&-*M^9KwPJ_He{fp`ZDvlH`|-`R|dNK0s(x_Gqq zFbRS~m5h|2%UoL;__&@kniN`8tr<$Ivl=buJadu$dBL=ZDA^F%C~7xl_c5v#4lo@d z$O40H3L#NrE>r>XP-q0ALv4fq=p2Yq<&IP?N$xV70Wc1WoX71Y`YGAYLZAl3hKMZqCQTn}GeH zJbx7jL9r7B$zfj1gO#IO!uQY2SqdTie51wO+B)WdcV6PbdV9X~%E(0wBap`z6~7kqab zqV2=_t6<&q(<#Jya+=*O$v)U?rk3fiCj_^0f_Ux%nkdB%gal70o?hI2FjxUP10nB| z=C&tl=^m5ZC~NVtMI8=FzU?xh^%ADp*wBNzAM=3`YJ=*hAhp%Kf3EW6)~WMOmise}P(C^3C&{5vw^&O>sq)@+`>KX5Pd zCZTFCgO6s91sS5Gphe)3P?l|L4qa2CFaa10*tpx^;|U;q!0uJTVvBXo;U^j2WKnpXkDbd8?kyopL)z}>KFSLl=EdC}#AVRr zp?7{wj?)uQ9*Gooeku<9C+RbCCcyl#QwIamP-uvyG3VoR%8EQ(U~B_=Y2R$dfL0-o#5;*T_Uwl)Wjh&bxwRue29RcvKhB#2g zHd-_#CG>K9SPH-xjB<lwbw_FPUDlf{T`b_0w@J|7dm8pLrnd zIlZ#J(bA&n>G!nJLOFgkpC`HjlwV3pspo0Iq_XZWzqubS0-JFTN97>xZMwmmqc+J4HyL7k`XN)Ri zF?q5I(QGS_56>`0Swc!zH_B}vcaa=BE-5X|KhK52^;-o!x$lYcjytz{#!g~lhAC&+ z6lcA4^e&YNGM1?prk`*2hmZj0>_N-))^p9qo;GuAv)D@Lndt87datI4ckYxxe8V(^ zC@Cc=36wJIG*c^J%DT0{ZPZ)jGhFHY)Y4q)ks|%|WhV7XLH-G5U@8dhy+@-Pl1||z zPb*Z~pMQSD$1bpa+_m)k{2L|#GV;v0m4XxIp=Opj#9_bp(Ip}Hec(9@EFN(f-K`&K ze^%N)dGXCArNyead#ncLduia2BS&gCK4I`Chn8)ex4?k3{+%DB#odkDgI11`2pZ8! zrH~Q)M$S!~#dG;3Ll);&q(S@G*wQunhMhFya0=~b9LMrh%;g%CO(Q#@eWNLHYDfB* z)8b{@1IO_?>W>o$&!80MT^OG82r1XfxX91AJE(@<3ARkRk^0PHTy2$JY2c)r zl(%^KIpG+E<3u$y>cY%d1!}uLK9$WQKlGFJvw!OGAaP*V=tvL~r^)fV>$qLV&m$%w z0p}3uC3bEjiEcO(ju1hcSi)wGX_(>_(b#ykBV@gZ8rBDv!ZAR$A@#KzL-_RsAFVAP zy3s0IFaU3!Vq5cRnzO8nZ?6 z439=GE-ZkI{+8NKpx?Xp2cAJITma!1%AlHeZ13UZYG=kbe>a6%+^#j>P#g$B3|Y*g zaQ?NKuLW`R4flm!pBYu5B;EE-+A@c0b}$l`8s$HBg}r#!TMgEUQyHlc3iji36lZxE z5t`bWmvYU^n1_fgU>YZ|tr^&0}{;_m!HUxHsruy@5a zLY5Lei$$RxAn1dNfl9$h8}1Hsy%e-6#+*D5*OBrqX| z@|(|qOC)RX;BYm>^$O|1EsG?;5-9v#A)-T|S45Rf<#_M%vN)N~8$qIzNT|ehAe?=c zN#d>J3l~1s7b&D(I5#kgfde8sI5EEWAM!3uZulfhH0PSTft zB!+V@U~f@zaf%2nAwg+kj*?(PdmduW+=?o9&CCTJdWgzyrQT34u&lh#zKpqm7nJ#SCkYi4#Q7y^B~Fx`(rjiOpvRj@Q1WpQp%-gY+h7IyO3bnt|5jJnfp- zHiA1fnhpTe)Y2bsW4&F?{$3gd`it!={bSzrea!c3%}}v=9nH+P{q?a-Tz^PNqst;v zd8Ry8iIa|;)JwMS!-u=yY=%j`qh!LUSfksozn4UtD!=&@@r7@^rkl@Aw2<3^*TI{qB>O6iyg@&R>FaOE1eHsnt-)uz6k#&%5R&_mh zhA1Lg{NBB_82pwIyES?epdD1R2h0dWH`o`C|L4c@90b<<+oO`1x!XIK5UM;ehf?qm z(lx9B=-t#o0R}bnyR3@zBb65nZUluIkn)0^HgUUG+%3_)r)7oBuC*;}@zk)z` ztS*v`{{)%k?<3o+HhEaQ_k!Z-{iIBE=!0QfPkw_JO5R;Xad=TshLB~k;w2l~I7@le z^XW}#R#XOcXS4=DDnuX3h%8Z=zJKqYdwH*;I263mYuAnU5uZb_s2_HU@YZO<9cYT3 zxCcipMm0ia;>ttnN*jNld|ZoXZF+vnly3B6x+v6|D?T{8ZoIKI=}mN>>L-*anp=1$@BTyJxv zVjCaTo`2h?DH>ajNdS0!`!-pGwleJ%n>OLpzVi$%p3ica+a8(F*(^#*DB{?KK@U=A zd4gB`u*$JSyT3NGq5ry1?k;{@ts=Bf{QhAr)@!#O?hoV6!;wjxKr%8mPQTnvvT@G( zlovrjvmg`|JVO1s7n>{1L&cQvt5hRSB|4&Xs`{kEACyzEb01x*k=yfdt9PM4=Z2;}A8<_uQJ!9H8kq~t8n7?U?0e%S zyO|J1IxN)4Y%dz?^xNv>qvljENt&R4x|p`o`jA`+!AikhU zX`X9P{`vZ6!g929-x-Ze|D5sriicM&Udp`GP!IwGLu0wEYk<>MJh}mxK%%14j(W%T z%Oa|6#5zPMg9tb%-bNMw>fsCTU^rFXlalwf1fo?^AMMD+DVWiy;I4QjV~&c1uv z&DtgcNNXML1p2BbC$Dw6a{uZ0Qqf8BN9Pe^b- za-#(RwoT+simELB~esUi)JD?Zj$C*nHDEMjx2;N%C@gq=a2%pZe@^b7nrR zuVD31#Sqx$!ZCfmn=+GMm^S=hISBMePnVr>tn6E>z@-YfozkYruDgvVv%L^IP)qXv1W*_gva@S}hZeQz;(iwD@j=KIR%XEKSQ4MjT{ES0B6%`3; zro_oKw;tPT{t(L){T{dx8B=zQ7?9~=4 zPKR_LR)OfglJI91R1Li7V{0Erhr+NE@AgMq8GumL$5@v?wT7~Qyk7SMIKF!$HZ7)k zgpG|2>$u3Zm0vZZ*tu*y_#=;v{lG7H<3FXY4BsHyH@N)_wm6@M*2tfQQk( zK%9qEw3yu5u7ti=#JsBXn9A2#m>lxtJ1%{?YaIa&7unfiZ6;>rFDhDFJKRo>SpxeW2MXrVN?3Gs=1N!dq4?2&AeJ zIu9=Jp;Z3%8GrV>$vpS3>`%mg!es5ax#t~V|w(D`2@1v1MygOu#r3`uK`5V4u znG!>$?o9CC_rTbS>=WZ#EehKaR}d?xs$=MO00&0m(x? z!f(U-2OK}2{c~%veM?cSQ#ncOjJ2c)vwHr zVAsF$RsHklQPzO?eb<3$bT7F`0t%mOrL_HUG-Gl#cfU{Uzv+?;@iVW`|N1x@ut*1;UX-7Nj-0^jfoZ}K7P3g z#pJ);N*6qFfRC9!Sthf@@ONYwDbBM|!*+#IszYU)cbAg*8oAHClm7k`p#mKaru*zg z4>U64!eI1o6!6yw^Fh_AYjV$oV(2R= z;fh06q1gPD1>q)NIIQ%d;_w*Y$9m={U;lUPf1l+jfplSC+?p55Y5N99hu8?WWD(l` z<420=zHc@~Emm;Pj_vYHUGTKkV!({gUXBK*V~o{>3R=+HjC06zi&(&m_?;a+$~V+eI#SM55>S+({@&!*Od z?f%QGxJo5+ZYAz2mF?>fNXtuWu*j@wzlM=+_9^3yP{J}U7F_GT9yjAY@z#D1=~b#N z(2JTo<}Qu-MrUy~$9MZ;#M9A8l>P+9>bknR5xp9HI>?sSS+po2dlNqb%8x`?&a}9d zx?a8^wC|OEwsPvDt5lVAg7{}cb(DF1@Vbxj?K4-ao}YR6U!EZNH6#(|(XGS~Tl0tb z>uZ%KY?pC3BGA+-PYI$dbr7~pxlxd*yEx023h}=WA{aw-_^u=rk}O1dx&7dSI*d*` z(>k;tWw>6^-w9WBwLR)bIC`3})cx<*VH$N5=d9+yrUpY8Uw}r&Ltk-;(hGP#CM`p+ z=63bz9eM)MPeuOAkC595sHE2CUMFSvC7 z$8LHo@@IMZMK#C$AEPe^(17{f{)agCrT@a>4G%(e59w18G^RcFG)dC<%vcR1jkiMW z%htxFCywIy5ApktvrOOqEguBGP`dvDNtzWm8Q`ixYbXFjXH^EW!q^)~#cYx{W+6L%Tm?G8(or0mYe;zMgrHW1CO+U#T21<36YHI0b0a3HV z$8WcbG;58JA*yQq^S&vm`$)~uvt<)~n-NP-te;{Rez$+1c({?dEuiNAoQ^E1)+%zj zs_lyna@*0qjW^30aJWQ*H`iTryWRki*)>9HX2l@n8h;Bk<9ua>={T^?UtQB4f#da5QZZ`b>zjrXWi( z1v^jpz6BK<3r5$a=ra;|?a4eynC{VbI)tV4sVt_{`Mo@o?vuO0$?V6tW-CTM`DNa@b7D@_uu{1Q0%JN>7p5KEw`#h>h~{)w;f^nPK#pY z;3wZA=6Qc5iONG@0|2%Z=4C zUm5f{yh$FmCZAE!Jh%T#9SOmB{}t&n-w{z|;p7)a1jDZv6jbGv)#T1(9}Ad24mCnC zmf6aB{`Yg9`}1T~ddKu%?FoMvrE@`B)3)_B^VnWoG9UAc@^`1&B{jO*-F}VwujueS zL6@x7&zIPAzYcqA@P9J7bW#8ChekMI4-Voc;{}PmO5%uL>K)?>!P;i zrA_^Uu2$ z0usVT1f;tKq#L9+4bt7+NGJ``DJ3l+-Q6YKCEX#?@muhgp7Wmbo$vph|8;S(_g-tw ztY@B>x$l`-&&u340}*R~K9xufH9?ef8pA;-$1W5keXhTvmOsuw@`8ByEOl3O;VX#$ z&5o$9dm%CROz+saH@DZK314M#+g3b!6b2@i@m42#rlkQ$hp9u`>DB_6hI(hc77SV> zE);Bgp0yIKFxqIUlS@g}-76l*a`_#8_>|u3HJ-Ui4p*IL_Be*rtqP{sIs;5hW-z}g zmSXw7A#C(kBDxvka3!6W71J2uaA`&!wB`>uAMa|B*Gg#yND|fMK1pRy@aJ>CiYv&e zh8}Amfpq&rez3rw8j;Mz$x?ze1>p*mz6~E0n)V^&I@*To{}?dp;}DkMZb$H z@DWc$(QrB08?kHx4?9wW+*o?FA&sBSqcRWk=oX0pC1mQYn3NR*#$d!q@4w|J$jb38 zBZ!`vcHEdRUGUQKxW?YZ#{xC5^^CqYG)k2gk2G?JLd}4QiHl0|`4Tu?$>g)O)e~sb zACImFM}>|qtKzI^P`o7pm*2cFK{ZMPnr9t%YWtY-RAHr!!)6P_tSo`fAck9wXG%Mr zLrK-sEBc*a!69eSvXkJC zH8p|hby2=X%Z9Lxm+>B_C^y+mmD*?kt5iWg|x-BI3jOd)I zD9K$GoIYH>5`QL7`{J$1ERodId!eB9qvA_aI=pC2#_;8FH3_S+CTu{DP8l2`T6WC2Ra*n!<8* zH&VOlcExgXrXwXxSOpKPKi{hmn++L}n1d<65#< z3g4bZk<{7PMYwpaz0IXfTvEKD+$CUuo1L)WbtTBR>BY6qb!~-mWJi9(V&?`fU(G{B z-G0AFpCpB+rnG`>ISU1udGispO0!6Js&08xmK!mDaFeXIoJ*JEO?Zfj9vdUCaPA@e zTB@+T#gWO!t{4LgEBh_hT*;OM8D#A3@uLSI0;X|M*Vjd%c}I|HsN)1AK$wmMBzr}D zA&xw4_v>?itb)-E?XmoYSHp05gqfDqpv8irH8OuyftvE@4}#kgPlg6xzZdJF98W=4 zh>FI>F(z$sYZF)JPb*ig9hkd7+k&t>+H^$(Rp}N~4}A5Qn=Xrab%=pM0|aTNK9=d{ z>W>R7lDscv0ij0gl^dZlsbojO8)5-$*AdFhG)gpG`8GYu_k}PUto)DQkCB1XY&6vN zfq9WW1;N3QUtEBDTpsVrz)@A06)o}%SE7T$>8C|?txlyWzc`J>f{nXfQnoHxaLi}Q zO&9K-^h@TP@QA=ledc}&0x{_JNg*@CJ19qA4rOFDZ9|xRFjDWh$aj{WRgB;)ZnHG|Jvqvaw+ z9@p@1nw|mfG4M^Ciaems(*f-jswlD1*E@gGcdsJ}Przi9M#%92HmKSJf;xUnjhN zfPAhfAR)5QWw#>Agh}GgZ7vm}lZk{F8{Pn{hT()Tvaya5d=(NB7Dvv&Z!0$mo|O*b!lW&*{}rc#fW$=8z zo){ybHDmIT;=9O$2l3I5E4Ugp(wbwn%hu(UrL)mdRHkt$)n86HMT~u2N|>&>@F)93 z0t{Jzjy8=RZr|T}8tRpHFs{DE8~QTO%W=EyAiKH6nl0_DoZ$+AO3iC{WCC`hu2WN} zO)nOHwZX3|iC#j32nny@BsL6T6Mc^TP(VJNk}|rl2SW?>ecu>0MBfh+oVHxrw-=gv zEN;FrpBwl>aQT>Y1>B#~NHx!qbWvm$S%T0cbw$FMnT83zDoSapsu!=JsL`jEL`Etp zSj;rIqEbR0;i(Tc{77rf@y*h(6%H4Nboje)0)1^%!5Y}z9LCEF-#mvq(-X&@qhSGO zOinTqQORVN(|&U(zZpm6(a6_KLs%)30R+4a#Qg-M3SxIL7%%#dYFZZpuI0+%(T`UX z4}NGBn~XHfpuPnj?=yt$2L{DpWVNm@`L*!UUjMUeI!Kx55p$p0fptM#qcVpz8^k?Lx1DL6V!!3dZXI&-mlH#Qs2@O{V{v+B@;Cp4^;@{mEz) zrMHPrF2km@8@SDQG}LRs;Bj>;jLmIqkne1q?Aj+z0hcnx$R+;md{V4}=cHMy(PLb8 z+e2Zv1s=xgK>WZ{yM%p2|NaP~)f*lEP@}k5B%DfA>k9}ZsT*SNkFqnb#1{;+n&8@d_I96404HkF_ukXB)x>r2Dm-XBNqUyg1|VgP+XiX9Oz92Psoo z4en$$l@-pt?>yKthWtND8~2@ z6%`?`vbLaJ=8$CEEnQ(t1b?5*4s zQW-d_;2VEgMbP_PO;68!-r%Qi5{%17D0~qK3p$&3GQE6HyElJhi(N2Pc6zW`y3SAQ ztBG8D98w&FGXPIC*I<)Zx+)6Ozvkwq3^NLEB8W;OMgkc)$9rP8E z59F5@PA*k7Kt3Rdnu=60fyhPR1CX}>92L2ts% zizHmJlGYUj=9v<_EM_J**TEl4A{s*1tYE2m)->7|7A87pdPiDETAd?5WYibJZ6ZAd z)X5$ob^}PKQR#=M|=Hab`1F7b8~0F z4~bV^VMPG}`K9&Ag(1=9q&81L%w|bgSOqWZt_^8btBohpQwj?8)=`e1Vzdot5tF7JJhPJ`w=;U3{0?SM4q?vB_3@Cf4Djw!B7 zndHXcJ;>8XFWo~;0el}QgjHZkg{@JRlZS;)IH0Zm#y9!Vbglg+^6A3y&>#lr(O6*- zN5R&F7pR74?VE|ErLJy>#}lt`JVWzk=I&N5Z9FE(Q(n&-XtuXwo~wa*%ILDPEIn9? zML9n0Ip?*lwEq4n+()N!w_?j8TVYL|epmS=_W5LuAR;158C1%5)m73-@9rurb~s67 z_1v89uXP~eb_l#|&QrB-%8MvYPk*-IJJ#gswzQI#Y`S(i^~5xS$16=GL9No{D0OFf zdvkN^jisTku0FR8w9OMQ?Ko`##{%e2G@1?0m(9z4>h0IsiXpPKeu~M(TL{27n_cv= z-qgTlI+$U+Ejz%?Ps2VR$Q~9J7F!A5-md>mkjr(29(1F(yTf9>H(ajfu*YMwqi`UE zf|cHp0i&ch2NjfO(0{8-_kd`obaT*nAfx=So48TiaW1dhGZ6LK?a3T!sSpaxq7J4R z!KOBg{nAlC7s`Va!!^n`&0CE%a*jw;frt?FrJc(KUkzj~SG(Rfo}GsVH6(aE?A|Y= zCkjm(Zg?7i#N^1|?HtM-zm($3ToA&6Vh#sVM%Jj$O@Wu!1UNl|xVOK{VbW3TN3dDB z?Ly#i*6vKGo>zMCBw<}=HcyS^Tz4s zl4_8zbLW0Jr~WkmLMLt;WK?ljaWb&S12wWnGgG$P)JP22h^u)k-^Bn{g#;(_)<)q1 zvDWUSE9Tq-lcvu;;d>sPHrKFy9uLpWd_#&RA>m#M?dQ-BW;+qBAUwO)~!s36gn3#g8)@MZXlTb2o3=s+Cn%x!tybLo>To4C@% zw=i?40w^$NEoO+|8wnJ98VQ_U!EZ%*mzJwaU4M zejOvC^;I!@jbuuRQTw?0H z8OIX5!hq};jzBx-C3apV-oCk!v3BG1`edxl5rmH(%P%TEdobaAo~(0U@YdyX!z#!d zV)BWw??*UNLCUXwf+PL(#;{dR3tu24ZPKX=H?tS9@?6qjPr}anOJ#;l9G1-!G(&x^ z?*0HoB`PJ$8QUG?P5H{HI8$1ah8l(h$CQ?DoDWExZl^hTPOv*vUuc;L*My=8tkcV& zqO!@b;gE}PahXylKz~lt9b-qrXKTboQZkz_al9@0IAVCN-;_>kKZqcVB++z%E<8Ea z0C zUk8Vc*oP+u!5U;vDUGR>*|qtlOwp}og#~2b0KQi0-K5#N>+C_*29xd2B%NZZF+1{u z2|-2x1nW^;W_Xf)T9~rBd5{?KAWzvgoEFI~gEFAH)>YER!K$pJ7p`)9|+XS9&^+a*4Oe!c(VhxnD7$Dzb zSR$8VYaB-(#vlh$)}aHY26wJ@`B@Q7EeiZYg|s(14W?D0*~QQN?1aNHpDf{onrSfW zM@CnpX#N-z%?$HwSYKY=-Q`=QX9M1MfP&xIqa*sp=Y4cOHI2rmcDc($%3Bd1X+)*s zJSA?Dvui^iSy==K5JZn{j=t_a`d&}A5%%iB1Z`7SYw_&D)n$aEZ(zP-pvUFqg^rI- zQej5EVbkbTkTS4)hCQ6~Y1$JM1(Z_UFpno;UyALmek8rLAMjC3bRa}n>12_R zQd|Hge7yW@gs@4jW|u;cu99i`i*1&FL-U*&N9YUCHrXk&ssCzvO5O ztx{5v7j4?!s@K0AD?uc7*R~c)X7U*-@bL?5XL_PT+=+T!>X8!b*YN3qs+MGCn04Cv z_Wq{OIz7AyWq^u`^ed=kYJNJY;&2tQAQx`vv-Zn0~HXwifxw5N>>C7SaGIe*~tul3S#iMv{iOuSJZ6Tg7b`kENg#A{RlK&){LP0crt z5A<|k>}whGn7SHNFJ1qF0dq~H0BxD95KxKv*8X<7U zZV0W?yU273nz|~Xw0;UDD*5OGJlIzbgH;goIqR+B;``DTdL3DKVW(YXop!-AKTn5h=hsNi7riU@$c6jZIkFwv6)$F?ZNJsL> zi>AXU2^L~2JywPIP+qw$R`6y!PX>>phkg^fcM&T^8os&E*xtLCXo&e_4d!Vz=ot|~ z`bk48!5TgZZNmfIBZkvE=boSEE(ROv!J-W|qR1B}J&=}VX!NRlCJ0C-nG0as4;z{oS{aO% z%|w-2WNFY$0bV5pB-1=OR)02gse|nhN~k$vNCT;eK~dtrV76LT7(^J)Q;tK2bV_D>*Y}Mz_iQN1h@lH3B>}638!$XYW=G$CnUL3pgE)|C*Kb% z1RL85f4L?8V{5GvFg_YLjR0P22tMFW%`L^InXA%2Z4eLv^0)@@k3H_gZRQ+Tr-#Ab z!U}KEPMWLL8PZdx!kkyH=DYX`bF;imL~njkFy%=-S9hu~ImWeFw4lF^9qW;MrLHNb zt`HY{y|%hMswNhzs~h(Sci0gub8#_BZvg9U$j~y7{L)2x4q8hBll$qs%T~}aE`pn0 zkNSms(Cq_}jycyW;{D#+Ylx8bQs-%rCXb5~`MFEWs?jhTv1QJBu1-NUh!ERjsVg+P z)Xl7OEAq4Qm?)87Q}5M=HjCl>a6gxfmSolUBorkf(nn+Y2{{Bxs{E_Pb!SWI17S~;orwDyGoxi=IZ zQBd^s_c&c2ch7N&y+15*Q)>cfb%sfpy0$PHtdvt%1Ta(JG!<_O%-46G!AV}akI$Y5 zvF)-u^AK|+qbT`h5uhkZDay(!sj4f4-_kBmec-CZ`1VFOBjedKr<=B0J|v`vNU+oA zBicg*Py=QoZbd-4Fr4!NWn25_sC}hw_>esi$L-i0Da9q7RG)Bl)qjb4 z?w6G+Ht{j_Xw}wPr8~RD2LQJ(t5a=gZfwku=cu1K#tzHq2nh>MxJ=NiLcn!T(wfO{ z<|-{h;pZ;Cjmr0ChAC?^EpU7vx14olKKmA(DN^($NNfU6nv!bZHtu}wd<5R{!-vnB zp(|^JD&=eG15&%{SFWG~YT>hZn8esYn@Wb|CcuKa*d8&cSOo^xCEABI8n-F6HdHjr z0!n;*#?GXh=`BK9lz?LaD!V>e9SNWiI|Ph4l!PmpiK)cRB(LeqmZLmAjTHSSLPq+IV48SZk)3wr+tvdvpX zk6c4x13I*_eH5V(6>Z%qX#2W7E-81r>$$`xzTrVeWwqd`prMc!$r+?~7s_@V9jQv! zQ2IacM5Up8$nHyGv0NICt_{y86XEy*wF=FR(P(fB*Fv`+ zxeWj2IQ+PqCh1e3Rz(DgQY>b!c69H83=9&zi)?2t+omz<-dr7eXCo3O)LBuYK}I)1#S-uO>)+?kiT{@6_Qs?7kJ!EYjg!H5r!cu-R^J^*)#pv4Vb-3 zk7OjAsYEe5%JT7uwmr;FIxQL@ny+pqkPHqKM1j%HC`M||4&B#eXx(IE5-3c|QQKKz z@*MJi8X)5 zXraOPWKQ>itM*=Hiy0z}lw&Xx72U187>5tmYs$@#_X=pe*WnR2XM2Ud`Ny9^Mf>bQ zSJc8A)g$Dnmc;H?-&3oDSk1WXlF*awxM*OS5%HF6#dIuAY9}^jI!kO8*$>Zx3cP{?BhzQY_8C*MxvM02!NM27S|3hk5DZ;Br};n~X|K|) z`-a_F`Dk#MGn`#a@pw%GFR| zH3O?6u8zk#p@##WAk_Cn$~bfEFElu%xZEnqy~MT$jlQZeKx^KC(5RIj9vmL{j^c2f zD-=@-6ho(cUqy;;?GX>+HK-SrsdrqS9;1rYB{}qZg1|jY>YM+G22ySBscp0p5|vH& zx8-IRuo-w+De`wvM11=Da#TZCNiH6RkFN#u7Y>|rNnV_KC*2tAl`Zqbdf>)ETISSJ2>I%xhT+6E& zqlptm8X=7YAp{Sg1MHg5#XJChKK0a&H33B_z8XOZv~Z>_7ZrPb)8AVb01OMQErMuI zGLdBD&xe|~2FJEh;TXQ{aZ|iFQ&3mc^u|$vx_Y&Wv-T8aK6?h(&v(i43 z6^rPri1BHj1h5qm@z%M2Hz9by=_SD~m-9)k*`$4|pX)9Ex5!le;Yay{SX#yP(63%G z*h1RZkFI8em1PJsXC>>fi2?{75VVfFu(%Ix?RH9wXoyKmc_zQrh688zNFX77DV=YS zcC{lvH@Wlq#B24mgriHMAf=mf{mVvTYq8CEyH>7axd_ti>9Bp8s5($F8`# zcJqNnf!f|^p*w>$RIJcw8z=9cy0^sA(TO3PuQ1qo?El(%apW@+g@ zV}WC84zMX9^*2{6Ov=O%s8`<=;7TIvP;ocI_UCINoLG3UIgs)4(_G56+bduUTQKD0 zQtJl>I=^y)inW9`vwda@`hsy}&I30Q(zg$v^2w#dvv+l&q$_ES8$yWS&X)3goqx@fM;l1oa)NWTtxpv#708TQ;DH z#C;43RE(6|YV(DODTP}~OsuIz&|Bz&69%*hTSIa}!TWu#G}|%KQoRw62tR~??1iY7 z8VE$7bY5MSLw~BfR(ni-8d(Hz>;)2cJ}8itn)OmZN-Q=!MFIG|Ur6=P!EDSP_Q z5B7vqx8~Y>-yIwPMOeYt?rXyp7MU-C;p!oU8in zLg&>}M4Fikjj>T^@>p%6u`msM7c=l6@D8O!;FtMEaZf9@^R;r{UWP86N8oE!SiN~F%fTzg33u;D!3|d* z%$T;aA|4hFYe8kBGw&Zp@JF_adQJfe0i+rpuNv07M>yQh7bZSbegnrE5OKo@Y;8|e zRN@7nY&mb$Z$BK8RlvafNFaRCiv&2xNmdp8_I1$l=p_XkW>H5+_-8KOpyOCfVE1k2 z5fgV@-0k6V{yOUZoMiBO1BbRV+PfNoZK)JOLR0%%S-j#>V$yXTyg{6zo?{@87d>YH z7S77LUZeB*S#x0~L`fjnu=mL(9gv*vAg(7eJqdumFI}v-I5t(?%wRY9flU{5!0Un! z@&X65+J)e%IV`ofJ>nuC6JcTj6JW!S7>2cg9MX$8S*bQ(7y;01#YVb09SxB~!W8oa zPIxW2ovW)J<Ulm<#6mKK8vcxAFrf=43_A+v7$c z?+WZwARt>>>UM&0!sIRIgF}GCR>5W`FmEz%Sq^S@XL}L(WFJ3RJoTiQh?KCvWf!a# z3PeNU#309H3U)YhmpK@8xK*u%JFv7k^r%k?P0txCh&qa=gMXhk0&`Fqx#GsTQ<->P zFk!9`bZ$p{QW4;X@(3hTIbvO(5PB(_twMuiGfxBZXl1ER3JaKXV89pNy~qgA*Ww}b zM}Y@fwr!?`c7L2Oo}g_1ssmaSFh&g$2>AbH?{G^k4B{hqp1eIc} zvC+4%1K;fomZOu?x3#pl(bczo`I1i9(!%cUg8|HPe@>VY%<%g+CNLxY-7y{>Iw2=J z5qUcuJAL3%5qUN++x@j7^6X&t->-OWW2q~zZ>L80T2PoyLEp)aPRty*G5>EL0>6ET zX@G&sr1bTSb@(lv)PSP&U{(f3FdGM>2AEC&5Css@7RTlF@U_Ex|R6`ZZ~=|t{+ z(8<#&*yvc;THUoq*O^X0o=#BT!B|&cPJ|z*SV8BFEpUmvosGS&-ES=hD!bcftZ$)r zzajd*=0CPZ3mco+>D$l=n*r?-)YrAt)2EZvw=lFb0yA(hGXJ_gxnEVva)uqP9{<2| zafntsVIkcs{ndxEIa*b4qFzbBM|jI`nH?1lTU8o6jSFd_?kafV6=UruABES9=8X)_ z&O}{rTx!+0srMXKR(sF4=PayGotjZC^I2pDbkEKL2sb>$sPp z6%%y1dNM|3<6te_5F!%HcuKeGL;q$mA=Ae!c6o@1uFK^mXDx2nnk9#~cVfWdySL~h zNeDVGmY>T8lF=Vw1kMM0V~B_}4lv5AFI&@xBZh{v&flKPr zV|vx@aRXIJW)`5|&wcP3l;Et?X5 z2oDbikGdg)nDdcm*L%IM%SV%yLvp@kR*9~{@i1)i07dpH??xf{KTqI zL9aGO_~{T8qMa7pd+`#tWKVywd~#DZTcWv?)@wf6FSjZC75TX- zFZD}Z%Dso|Ga|DE$!M~vIdUV#$t*I^7dae(-P7pUb@#D?8Mxy*@lGP)OCetukInNQExqc-Qp7%y)J_l~Svx{U(G@W?3Z_5)!LEt-DG`!Lopd%l$!ASRkqq(_0! za}PdLy&ryw!~PKN*xL2RU(h>Xa&RzCl)}`Y;F+!O)5oaT$>X!cf@J8}(a~}99n?K}EWGI_@L#~rGOe6k?nv*`z`l4_*+TRylQf}^q)oIA~dUeU?W{Z+@ zKRjO6a3i87Q?8=z#$y+D&7@M*jc;t3!As66&&lzNw7)E~aej9gh2au@xFPumrglH1 zm5gHVR|;yoAzF;2!^&|e+=vf3 z3$er+qSx&+S@j3>1DN;G<>m32=J4csHPpqKLnP+SnA4pivZ>U}pN`eGf6tlir+#C? z=I9+X*Z1s`y)_Q8SOe#js7j(Z-q*t`ZV8yvbo<0BA;d)L;2J4H<30nKPDVImI+TXl z2p8X^68SWq2F?}29o3Q6GGCEiR3px36His2Z6Rwot2o?D@E#{wajSYf8$x%PXqFho zt+AQhnYu|^FKx?Mt^FSQ^#clL5NE429(4N&a(#5awuhA(Mr5LyYw#KkWt37mMK;q~ z7QhM$<;$&Gm!>7Rx zuXZ?)oU2lz{JYmQ2RPYxy(Vo5kF2=G9$^mDC)pRPE=J$Q6}4SixrJ9C7{z*gi*-pN}5jzAWD}O^^=WF~5bwKXJ(X zd$e;0RsI;y?{UH%o}rVse`9wC8t#tJ)A8%r>fayc7Z4N@5~7ka*0r&;wKT9((Gk@* zrW3LNhJIrULpm`%0DTzSIn#&&sKQnkzzjMTc6S8<5W#wnNE9p;EsXDg0+@;69s>P> zE$*(lmqiWy+gT0pPsro$`adN7A0+xid;u}RyW8Kjg7G&Lbl(i%u!5zCn4px7)t@rc z2`Ymb=;`U{fRpmhws!jFVipFLV1|2mb`SFInq*^aWoKyvz?=KlCD(R%ZIj7AfnVpeNO2_H99}LWl?DzLo{_RR2Lo^-a_fm{3^Z<0! zH&+6R++V|gk5OqDSlI7x0A^rhqra;gfU0+P0N|rOBcQ_H5%6E8zDLdf)bPKY(#Br@ zULE&s7iRj!KZODR6abq0#>SXN@~$y|xu>$R1)qhj@t^K`C&ORb1T!++8&%lY#@0^2 zNXO<*bCNoLeZN=0oj!lZ^gqdaSMs0a{j2I<4E4_f{(C#I0b0GQ>dt0>nE(g<(@b}# z{xlN{BmGZiVh4WRweNQ`G5xKXSQvjc6AJ^w{SCkjO!ORJpzdGI^qYEq_D{xtdQ9?v z$&{GEjK2{TVHPmsA3W&4%9QvlEG+G8)xeDR-4B@Q-gJP=-B}v2N6N)`M;qmSV_E-a%EkDLntvvw|Aun0{}bg>m$JlXL#s#n>bYoL z>6Np}rUDCPHYGiGmLHi!5KN#TV*QpZCO_}R#XeVN=BEfz=W;I7LR5ccrQ`YVqkENyR!ooG{iv2RkuH2(86t%%pr+-7$x%-b z?$Lr9W*F4IV>(SVXizEy=NW94ojH!)o-<}+jJ-M??jye0h`-x)MSQY_cCC$@r)W<` zu&;;Z!#Lv4f)1BtEgSuC(^=h=26tgW-(65OSXM?S+dxWX1TALdX5=6`UUaqf4UMV(4IsM_;YEaEzGPf#FYWk@`RZz&2{ zb|V_zVA3**Vo!o1ofhimG*Qfd@lcn-wlMv9`6r6XsUQqIk}P(83UZ7=cq~owoEI(N zGD{5Txps*fdu;_;Zg&|qW;7(0(?g>V3@hpgZwa7N!@P!-9VPWwn3bo-YSs1DThR!L zXww)~8n#V>acavljZNM$$mJIsGb9PXJtxg!0&ev@+owD*@-f_4x?hlWV+}sTZjSk_J8jm`}19`I+L+`Dx$Vh8Tt^ zD3A@TYp^zz!t;yupwfpumyfJjkv&HrA{6MCh+F1|ez%N#*f&J>*x~&$YZqTweZLA6 zIsaST?VXqV6fX>A-GhK9Hl-fwF8J_2h89e-bqbH%^%7)$v=WNRHT(+5KsBC<8GPis z37`HvKBEU{C8Z=|%FZWW5uMzYZz5&Bh$B+D#d6Z}Dt_?~6ynen%ubNl6dr2Z=tIw)2+d2{F=u;%=Hp*5OJ9@Bn zR#vx2o`P~U-aEB2hj+YHWIYBV^%Y8=1oIP-ct3(vya^U*JL%j9^orp3 zsZ!^4!6j1NadPu=Djii1YPONLGI#lK`1rZkX4YDnJlF9OHd`gmWch{Hp4H-kH92~o zJwCRkeYb1ZbQsU>Z=2)5=@|81N%p7}TMp2QugQFsgDkXrE3ky^gW;gXy~jz)Pn^%v zT0(^#bF|h|5wr4dMYtsHpq*?jdI zyJ};6N3vJ*dg9qIp(wX)ZIY20Dv8eH=ya*zOzhDdRt8nFnKNUW52lF;TNJCjWAf&O zxhaBq<(v$8KWHY>D`hf1N}QHD&KQ2-!FQY?e(~td zu4agaBI0^N5QEv^uAr9FOFZ8Ee4U9h62fN`{yGz^vZ{}2E8Y*AOqTPI?vy>@Ezv)E zBj2jAnv~=6#!S0L!W$WL@VRhV2ooc+0C!k5i!An>@bQdJmu(XHS@h)$@=l_bl9lSg zW0JP`!WMrRf=*-BR;2RQHj

M=6YI{Wj4vOPs4qcxn8FR*A* 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 z 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

h?`%$CsDV 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%0D>mP(x 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 z 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

O7i$?uCFF#a5J`y9@_FR) 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Ņb6tEBM>lqSy~(_Q5&_idb@dwlWR`BijE2$ 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

  • BWPw|ePWCsgJg*%5+$g9Aci8TG92(&!YL;Ei;I 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 Q-cII?Kk&(iI)4QIUqONg-v9sr literal 0 HcmV?d00001 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_ */