diff --git a/.travis.yml b/.travis.yml index c7e751b7..aaf133ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ before_install: script: - mkdir build - cd build - - cmake .. -DBUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release -DLIBPRESSIO_HAS_SZ=OFF -DLIBPRESSIO_HAS_ZFP=OFF -DBUILD_DOCS=ON + - cmake .. -DCMAKE_BUILD_TYPE=Release -DLIBPRESSIO_HAS_SZ=OFF -DLIBPRESSIO_HAS_ZFP=OFF -DBUILD_DOCS=ON - cmake --build . - cmake --build . --target docs - ctest diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d7aa203..7cda2cb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) -project(libpressio VERSION "0.22.0" LANGUAGES CXX C) +project(libpressio VERSION "0.23.0" LANGUAGES CXX C) #correct was to set a default build type # https://blog.kitware.com/cmake-and-the-default-build-type/ @@ -19,8 +19,6 @@ if(NOT LIBPRESSIO_CXX_VERSION) set_property(CACHE LIBPRESSIO_CXX_VERSION PROPERTY STRINGS 11 14 17) endif() -enable_testing() -include(CTestCustom.cmake) include(CTest) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -250,8 +248,7 @@ install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpressio) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/pressio_version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpressio) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpressio.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pkgconfig) -option(BUILD_TESTS "build the test cases and examples" OFF) -if(BUILD_TESTS) +if(BUILD_TESTING) add_subdirectory(test) endif() @@ -273,6 +270,7 @@ if(BUILD_DOCS) doxygen_add_docs( docs ${PROJECT_SOURCE_DIR}/README.md + ${PROJECT_SOURCE_DIR}/docs ${PROJECT_SOURCE_DIR}/include COMMENT "Generate Documenation" ) diff --git a/CTestConfig.cmake b/CTestConfig.cmake new file mode 100644 index 00000000..47b3ca8e --- /dev/null +++ b/CTestConfig.cmake @@ -0,0 +1,2 @@ +set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --show-leak-kinds=all --track-origins=yes") +set(MEMORYCHECK_SUPPRESSIONS_FILE "${CMAKE_SOURCE_DIR}/test/valgrind.supp") diff --git a/CTestCustom.cmake b/CTestCustom.cmake deleted file mode 100644 index 95fe3c4c..00000000 --- a/CTestCustom.cmake +++ /dev/null @@ -1,2 +0,0 @@ -set(MEMORYCHECK_SANITIZER_OPTIONS "--leak-checks=full") -set(MEMORYCHECK_SUPPRESSIONS_FILE "${CMAKE_SOURCE_DIR}/test/valgrind.supp") diff --git a/README.md b/README.md index 07f06867..3e6fcfea 100644 --- a/README.md +++ b/README.md @@ -15,21 +15,20 @@ Libpressio unconditionally requires: + `cmake` version `3.13` or later (3.14 required for python bindings) + either: - + `gcc-7.4` or later - + `clang-7.0.0` or later using either `libc++` or `libstdc++` + + `gcc-4.8.5` or later + + `clang-7.0.0` or later using either `libc++` or `libstdc++`. Beware that system libraries may need to be recompiled with `libc++` if using `libc++` Libpressio additionally optionally requires: -+ `zfp` commit `e8edaced12f139ddf16167987ded15e5da1b98da` or later and its dependencies to provide the SZ plugin -+ `sz` commit `7b7463411f02be4700d13aac6737a6a9662806b4` or later and its dependencies to provide the ZFP plugin -+ `sz` commit `7b7463411f02be4700d13aac6737a6a9662806b4` or later and its dependencies to provide the ZFP plugin -+ `numpy` version `1.14.5` or later and its dependencies to provide the python bindings + `Doxygen` version 1.8.15 or later to generate documentation + `HDF5` version 1.10.0 or later for HDF5 data support -+ `swig` version 3.0.12 or later for python support + `ImageMagick` version 6.9.7 or later for ImageMagick image support. Version 7 or later supports additional data types. + `blosc` version 1.14.2 for lossless compressor support via blosc + `boost` version 1.53 to compile on a c++14 or earlier compiler ++ `numpy` version `1.14.5` or later and its dependencies to provide the python bindings ++ `swig` version 3.0.12 or later for python support ++ `sz` commit `7b7463411f02be4700d13aac6737a6a9662806b4` or later and its dependencies to provide the SZ plugin ++ `zfp` commit `e8edaced12f139ddf16167987ded15e5da1b98da` or later and its dependencies to provide the ZFP plugin You can also use the provided `Dockerfile`s in `./docker` to get a working libpressio install. Doing so requires installing `docker` version 17.05 or higher or other build tool that supports this version of Dockerfile syntax or later. @@ -40,11 +39,11 @@ LibPressio uses cmake to configure build options. See CMake documentation to se + `CMAKE_INSTALL_PREFIX` - install the library to a local directory prefix + `BUILD_DOCS` - build the project documentation -+ `BUILD_TESTS` - build the test cases ++ `BUILD_TESTING` - build the test cases ## Building and Installing LibPressio -To build and install the library only. +To build and tests and install the library only. ```bash BUILD_DIR=build @@ -52,6 +51,7 @@ mkdir $BUILD_DIR cd $BUILD_DIR cmake .. make +make test make install ``` @@ -89,13 +89,13 @@ make make install ``` -To build the test cases +To disable building the test cases ``` BUILD_DIR=build mkdir $BUILD_DIR cd $BUILD_DIR -cmake .. -DBUILD_TESTS=ON +cmake .. -DBUILD_TESTING=OFF make ctest . ``` @@ -173,6 +173,9 @@ main(int argc, char* argv[]) More examples can be found in `test/` +For information on writing a compressor plugin see [Writing a Compressor Plugin](@ref writingacompressor) +For information on writing a metrics plugin see [Writing a Compressor Plugin](@ref writingametric) + ## Option Names LibPressio uses a key-value system to refer to configuration settings. diff --git a/docs/BuiltInModules.md b/docs/BuiltInModules.md new file mode 100644 index 00000000..02501e40 --- /dev/null +++ b/docs/BuiltInModules.md @@ -0,0 +1,17 @@ +# Built-in Modules {#builtins} + +Libpression provides a number of builtin compressor and metrics modules. + +## Compressor Plugins + ++ `sz` -- the SZ error bounded lossy compressor ++ `zfp` -- the ZFP error bounded lossy compressor ++ `mgard` -- the MGARD error bounded lossy compressor ++ `blosc` -- the blosc lossless compressor ++ `magick` -- the ImageMagick image compression/decompression library + +## Metrics Plugins + ++ `time` -- time information on each compressor API ++ `error_stat` -- statistics on the difference between the uncompressed and decompressed values that can be computed in one pass in linear time. ++ `size` -- information on the size of the compressed and decompressed data diff --git a/docs/WritingACompressorPlugin.md b/docs/WritingACompressorPlugin.md new file mode 100644 index 00000000..5ff63e8f --- /dev/null +++ b/docs/WritingACompressorPlugin.md @@ -0,0 +1,166 @@ +# Writing a Compressor Plugin {#writingacompressor} + +Libpressio supports adding custom compressor plugins. + +To create a compressor plugin, simply create a subclass of `libpressio_compressor_plugin` that implements the compressor functions that you are interested in, and register the plugin with libpressio. + +For example, let's create a compressor plugin that preforms a log transform as a preprocessing step to compression, and does a exponential transformation as a post processing step to decompression. Some scientific data compresses much better in the log domain than in the normal domain. + +First you will need to include several headers. + +```cpp +#include //for exp and log +#include "libpressio_ext/cpp/data.h" //for access to pressio_data structures +#include "libpressio_ext/cpp/compressor.h" //for the libpressio_compressor_plugin class +#include "libpressio_ext/cpp/options.h" // for access to pressio_options +#include "libpressio_ext/cpp/pressio.h" //for the plugin registries +``` + +First we are going to delegate most of the methods to the underlying compressor. +To do so, we are going to do this in one of the most naive was possible and accept the compressor as a constructor argument. +Then we are going to provide overrides that pass each of the methods to the underlying compressor. + +Notice the function `check_error`. +Since we are using composition rather than inheritance, we need to propagate error messages to our wrapper. +The `check_error` function simply check for the error condition in the underlying function and propagates the error if these is one. + +Also notice that we are using the `_impl` versions of the various methods. +This is because the base class is doing some work to provide metrics functionality and basic error checking that we want to use. + +```cpp +class log_transform : public libpressio_compressor_plugin { + public: + log_transform(): compressor(nullptr) {} + log_transform(pressio_compressor&& comp): compressor(std::move(comp)) {} + + + //TODO compress and decompress, see below + + + //getting and setting options/configuration + pressio_options get_options_impl() const override { + auto options = compressor.plugin->get_options(); + options.set("log:compressor", (void*)&compressor); + return options; + } + int set_options_impl(pressio_options const& options) override { + //if the user hasn't set the compressor yet, fail + if(!compressor) return invalid_compressor(); + int rc = check_error(compressor.plugin->set_options(options)); + + //try to extract the compressor plugin from the option + void* tmp; + if(options.get("log:compressor", &tmp) == pressio_options_key_set) { + compressor = std::move(*(pressio_compressor*)tmp); + } + + return rc; + } + pressio_options get_configuration_impl() const override { + //if the user hasn't set the compressor yet, fail + if(!compressor) return pressio_options(); + return compressor.plugin->get_configuration(); + } + int check_options_impl(pressio_options const& options) override { + //if the user hasn't set the compressor yet, fail + if(!compressor) return invalid_compressor(); + return check_error(compressor.plugin->check_options(options)); + } + + //getting version information + const char* prefix() const override { + return "log"; + } + const char* version() const override { + if(!compressor) return ""; + return compressor.plugin->version(); + } + int major_version() const override { + if(!compressor) return -1; + return compressor.plugin->major_version(); + } + int minor_version() const override { + if(!compressor) return -1; + return compressor.plugin->minor_version(); + } + int patch_version() const override { + if(!compressor) return -1; + return compressor.plugin->patch_version(); + } + + private: + int check_error(int rc) { + if(rc) { + set_error( + compressor.plugin->error_code(), + compressor.plugin->error_msg() + ); + } + return rc; + } + int invalid_compressor() { return set_error(-1, "compressor must be set"); }; + pressio_compressor compressor; +}; +``` +Now to the harder part, writing compress and decompress. + + +First we can write our log and exponential transform functions. + +```cpp +namespace { + struct log_fn{ + template + pressio_data operator()(T* begin, T* end) { + pressio_data log_data = pressio_data::clone(*input); + auto output_it = reinterpret_cast(log_data.data()); + std::transform(begin, end, output_it, [](T i){ return std::log(i); }); + return log_data; + } + pressio_data const* input; + }; + + struct exp_fn{ + template + pressio_data operator()(T* begin, T* end) { + pressio_data log_data = pressio_data::clone(*output); + auto output_it = reinterpret_cast(log_data.data()); + std::transform(begin, end, output_it, [](T i){ return std::exp(i); }); + return log_data; + } + pressio_data const* output; + }; +} +``` + +We will use these methods using the `pressio_data_for_each` API to preform the transform +Now, we can write compress and decompress: + + +```cpp + //compress and decompress + int compress_impl(pressio_data const* input, pressio_data* output) override { + if(!compressor) return invalid_compressor(); + pressio_data log_input = pressio_data_for_each(*input, log_fn{input}); + return check_error(compressor.plugin->compress(&log_input, output)); + } + + int decompress_impl(pressio_data const* input, pressio_data* output) override { + if(!compressor) return invalid_compressor(); + int rc = compressor.plugin->decompress(input, output); + *output = pressio_data_for_each(*output, exp_fn{output}); + return check_error(rc); + } +``` + +We finally register the library with libpressio: + + +```cpp +static pressio_register X(compressor_plugins(), "log", [](){ return std::make_unique();}); +``` + +High quality compressor modules may be accepted into libpressio. Contributed modules should be placed in to +the `src/plugins/compressors/` directory and added to the main CMakeLists.txt. If the compressor plugin +requires an external dependency, it should be hidden behind a configuration option. + diff --git a/docs/WritingAMetricsPlugin.md b/docs/WritingAMetricsPlugin.md new file mode 100644 index 00000000..e7305e73 --- /dev/null +++ b/docs/WritingAMetricsPlugin.md @@ -0,0 +1,84 @@ +# Writing a User Metrics Plugin {#writingametric} + +libpressio supports adding custom metrics plugins. + + +To create a metrics plugin, simply create a subclass of `libpressio_metrics_plugin` that implements the check that you are interested in, and register the plugin with libpressio. + +For example, let's create a plugin that counts the number of compressions of each data type that the user preforms. + +First we will include a number of required headers: + +```cpp +//required for all plugins +#include "libpressio_ext/cpp/metrics.h" // provides the libpressio_metrics_plugin +#include "libpressio_ext/cpp/options.h" // provides pressio_options and related methods +#include "libpressio_ext/cpp/pressio.h" // for the plugin registry + +//required for this plugin +#include "libpressio_ext/cpp/data.h" // to be able to access ->dtype() +#include //for make_unique (in c++14 or later) +#include //for the map that counts what data type was used + +``` + +Next, we need to write our class. Since we want to count the number of data buffers of each type that we compress, we will hook the `begin_compress` method. Alternatively we could also hook the `end_compress` method. Once we have the counts, we report them out using the `get_metrics_results` function. We do this like so: + +```cpp +class counting_metric: public libpressio_metrics_plugin { + counting_metric() { + //operator[] is non-const, so explicits instantiate each of the values we need + counts[pressio_int8_dtype] = 0; + counts[pressio_int16_dtype] = 0; + counts[pressio_int32_dtype] = 0; + counts[pressio_int64_dtype] = 0; + counts[pressio_uint8_dtype] = 0; + counts[pressio_uint16_dtype] = 0; + counts[pressio_uint32_dtype] = 0; + counts[pressio_uint64_dtype] = 0; + counts[pressio_float_dtype] = 0; + counts[pressio_double_dtype] = 0; + counts[pressio_byte_dtype] = 0; + } + + //increment the count at the beginning of each compress + void begin_compress(pressio_data const* input, pressio_data const*) override { + counts[input->dtype()]++; + } + + //return an options structure containing the metrics we care about + //notice how the namespaced matches the name of the plugin that is registered below + pressio_options get_metrics_results() const override { + pressio_options opts; + opts.set("counts:int8", counts.at(pressio_int8_dtype)); + opts.set("counts:int16", counts.at(pressio_int16_dtype)); + opts.set("counts:int32", counts.at(pressio_int32_dtype)); + opts.set("counts:int64", counts.at(pressio_int64_dtype)); + opts.set("counts:uint8", counts.at(pressio_uint8_dtype)); + opts.set("counts:uint16", counts.at(pressio_uint16_dtype)); + opts.set("counts:uint32", counts.at(pressio_uint32_dtype)); + opts.set("counts:uint64", counts.at(pressio_uint64_dtype)); + opts.set("counts:float", counts.at(pressio_float_dtype)); + opts.set("counts:double", counts.at(pressio_double_dtype)); + opts.set("counts:byte", counts.at(pressio_byte_dtype)); + return opts; + } + + std::map counts; +}; +``` + +Finally, we will register the plugin in the under the names "counts" in the metrics plugging registry + +```cpp +static pressio_register X(metrics_plugins(), "counts", [](){ return std::make_unique(); }); +``` + +Then a user of the library can then ask libpressio to construct their new plugin as normal. +But what if our metrics modules takes arguments? +Instead of registering it directly, the user can instantiate it manually and combine it with others from the library using the `make_m_composite` method. + +If your metric is suitably general and well implemented, you can contribute it back to libpressio. +Metrics should be added to the `src/plugins/metrics/` directory and to the main `CMakeLists.txt`. If the metric requires additional dependencies beyond the standard library, it should be hidden behind a configuration flag that enables its use and disabled by default. + +This full example can be found in the `test/test_regsiter_metrics.cc` file, and the full documentation of the allowed hooks and their arguments can be found in the documentation for `libpressio_metrics_plugin`. diff --git a/include/libpressio_ext/compat/std_compat.h b/include/libpressio_ext/compat/std_compat.h index 99fce1d3..9ca47a96 100644 --- a/include/libpressio_ext/compat/std_compat.h +++ b/include/libpressio_ext/compat/std_compat.h @@ -1,9 +1,14 @@ /** - * \file this header contains a couple of C++ standard algorithm replacements if + * \file + * \brief internal portability header + * \details this header contains a couple of C++ standard algorithm replacements if * the provided standard library doesn't have them. We prefer the standard - * library versions if they exist + * library versions if they exist. Use of any of these functions outside of + * libpressio may is NOT ALLOWED */ +///@cond INTERNAL + // // functions in this file are adapted from libc++-v8.0.0 whose license is // reproduced below @@ -228,3 +233,5 @@ template } // namespace compat #endif /*end header guard*/ + +///@endcond diff --git a/include/libpressio_ext/compressors/blosc.h b/include/libpressio_ext/compressors/blosc.h index f202d05f..747db06c 100644 --- a/include/libpressio_ext/compressors/blosc.h +++ b/include/libpressio_ext/compressors/blosc.h @@ -1 +1,5 @@ +/** + * \file + * \brief Includes definitions needed to use the BLOSC pressio compressor + */ #include diff --git a/include/libpressio_ext/compressors/magick.h b/include/libpressio_ext/compressors/magick.h new file mode 100644 index 00000000..e19612c1 --- /dev/null +++ b/include/libpressio_ext/compressors/magick.h @@ -0,0 +1,5 @@ +/** + * \file + * \brief Includes definitions needed to use the ImageMagick pressio compressor + */ +#include diff --git a/include/libpressio_ext/cpp/compressor.h b/include/libpressio_ext/cpp/compressor.h index 02294032..6420554e 100644 --- a/include/libpressio_ext/cpp/compressor.h +++ b/include/libpressio_ext/cpp/compressor.h @@ -2,6 +2,7 @@ #define LIBPRESSIO_COMPRESSOR_IMPL_H #include #include +#include "metrics.h" /*!\file * \brief an extension header for adding compressor plugins to libpressio @@ -33,26 +34,29 @@ class libpressio_compressor_plugin { * \see pressio_options_set_userptr to set an data value, include an \c include/ext/\.h to define the structure used * \see pressio_options_set_string to set a string value */ - struct pressio_options* get_options() const; + struct pressio_options get_options() const; /** get the compile time configuration of a compressor * * \see pressio_compressor_get_configuration for the semantics this function should obey */ - struct pressio_options* get_configuration() const; + struct pressio_options get_configuration() const; /** sets a set of options for the compressor * \param[in] options to set for configuration of the compressor * \see pressio_compressor_set_options for the semantics this function should obey */ - int set_options(struct pressio_options const* options); + int set_options(struct pressio_options const& options); /** compresses a pressio_data buffer * \see pressio_compressor_compress for the semantics this function should obey */ - int compress(const pressio_data *input, struct pressio_data* output); + int compress(struct pressio_data const*input, struct pressio_data* output); /** decompress a pressio_data buffer * \see pressio_compressor_decompress for the semantics this function should obey */ - int decompress(const pressio_data *input, struct pressio_data* output); + int decompress(struct pressio_data const*input, struct pressio_data* output); + + /** get the prefix used by this compressor for options */ + virtual const char* prefix() const=0; /** get a version string for the compressor * \see pressio_compressor_version for the semantics this function should obey */ @@ -74,15 +78,15 @@ class libpressio_compressor_plugin { * \returns a pressio_options structure containing the metrics returned by the provided metrics plugin * \see libpressio_metricsplugin for how to compute results */ - struct pressio_options* get_metrics_results() const; + struct pressio_options get_metrics_results() const; /** * \returns the configured libpressio_metricsplugin plugin */ - struct pressio_metrics* get_metrics() const; + struct pressio_metrics get_metrics() const; /** * \param[in] plugin the configured libpressio_metricsplugin plugin to use */ - void set_metrics(struct pressio_metrics* plugin); + void set_metrics(struct pressio_metrics& plugin); /** get the error message for the last error * \returns an implementation specific c-style error message for the last error @@ -98,7 +102,7 @@ class libpressio_compressor_plugin { * * \see pressio_compressor_check_options for semantics this function obeys * */ - int check_options(struct pressio_options const*); + int check_options(struct pressio_options const&); protected: /** @@ -121,17 +125,17 @@ class libpressio_compressor_plugin { * \see pressio_options_set_userptr to set an data value, include an \c include/ext/\.h to define the structure used * \see pressio_options_set_string to set a string value */ - virtual struct pressio_options* get_options_impl() const=0; + virtual struct pressio_options get_options_impl() const=0; /** get a set of compile-time configurations for the compressor. * * \see pressio_compressor_get_configuration for the semantics this function should obey */ - virtual struct pressio_options* get_configuration_impl() const=0; + virtual struct pressio_options get_configuration_impl() const=0; /** sets a set of options for the compressor * \param[in] options to set for configuration of the compressor * \see pressio_compressor_set_options for the semantics this function should obey */ - virtual int set_options_impl(struct pressio_options const* options)=0; + virtual int set_options_impl(struct pressio_options const& options)=0; /** compresses a pressio_data buffer * \see pressio_compressor_compress for the semantics this function should obey */ @@ -146,14 +150,14 @@ class libpressio_compressor_plugin { * * \see pressio_compressor_check_options for semantics this function obeys * */ - virtual int check_options_impl(struct pressio_options const*); + virtual int check_options_impl(struct pressio_options const&); private: struct { int code; std::string msg; } error; - struct pressio_metrics* metrics_plugin; + pressio_metrics metrics_plugin; }; /** @@ -177,6 +181,11 @@ struct pressio_compressor { */ pressio_compressor& operator=(pressio_compressor&& compressor)=default; + /** \returns true if the plugin is set */ + operator bool() const { + return bool(plugin); + } + /** * pointer to the implementation */ diff --git a/include/libpressio_ext/cpp/data.h b/include/libpressio_ext/cpp/data.h index b86b8a34..72b6c14f 100644 --- a/include/libpressio_ext/cpp/data.h +++ b/include/libpressio_ext/cpp/data.h @@ -231,6 +231,7 @@ struct pressio_data { * \returns a l-value reference to the object moved into */ pressio_data& operator=(pressio_data && rhs) noexcept { + if(deleter!=nullptr) deleter(data_ptr,metadata_ptr); data_dtype = rhs.data_dtype, data_ptr = compat::exchange(rhs.data_ptr, nullptr), metadata_ptr = compat::exchange(rhs.metadata_ptr, nullptr), @@ -375,65 +376,65 @@ struct pressio_data { * it should have the signature \code template f(T* input_begin, T* input_end) \endcode */ template -ReturnType pressio_data_for_each(pressio_data const* data, Function&& f) +ReturnType pressio_data_for_each(pressio_data const& data, Function&& f) { - switch(data->dtype()) + switch(data.dtype()) { case pressio_double_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_float_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_uint8_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_uint16_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_uint32_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_uint64_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_int8_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_int16_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_int32_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_int64_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements() + static_cast(data.data()), + static_cast(data.data()) + data.num_elements() ); case pressio_byte_dtype: default: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->size_in_bytes() + static_cast(data.data()), + static_cast(data.data()) + data.size_in_bytes() ); } } @@ -447,75 +448,75 @@ ReturnType pressio_data_for_each(pressio_data const* data, Function&& f) * it should have the signature \code template U f(T* input_begin, T* input_end, T* input2_begin) where U is some type\endcode */ template -ReturnType pressio_data_for_each(pressio_data const* data, pressio_data const* data2, Function&& f) +ReturnType pressio_data_for_each(pressio_data const& data, pressio_data const& data2, Function&& f) { - switch(data->dtype()) + switch(data.dtype()) { case pressio_double_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_float_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_uint8_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_uint16_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_uint32_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_uint64_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_int8_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_int16_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_int32_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); case pressio_int64_dtype: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->num_elements(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.num_elements(), + static_cast(data2.data()) ); default: return std::forward(f)( - static_cast(data->data()), - static_cast(data->data()) + data->size_in_bytes(), - static_cast(data2->data()) + static_cast(data.data()), + static_cast(data.data()) + data.size_in_bytes(), + static_cast(data2.data()) ); } } diff --git a/include/libpressio_ext/cpp/metrics.h b/include/libpressio_ext/cpp/metrics.h index 55e61d19..858e320c 100644 --- a/include/libpressio_ext/cpp/metrics.h +++ b/include/libpressio_ext/cpp/metrics.h @@ -49,18 +49,18 @@ class libpressio_metrics_plugin { * called at the end of get_configuration * \param [in] ret the return value from the underlying compressor get_options command */ - virtual void end_get_configuration(struct pressio_options const* ret); + virtual void end_get_configuration(struct pressio_options const& ret); /** * called at the beginning of set_options * \param [in] options the value passed in to set_options */ - virtual void begin_set_options(struct pressio_options const* options); + virtual void begin_set_options(struct pressio_options const& options); /** * called at the end of set_options * \param [in] options the value passed in to set_options * \param [in] rc the return value from the underlying compressor set_options command */ - virtual void end_set_options(struct pressio_options const* options, int rc); + virtual void end_set_options(struct pressio_options const& options, int rc); /** * called at the beginning of compress @@ -92,7 +92,7 @@ class libpressio_metrics_plugin { /** * \returns a pressio_options structure containing the metrics returned by the provided metrics plugin */ - virtual struct pressio_options* get_metrics_results() const=0; + virtual struct pressio_options get_metrics_results() const=0; }; /** @@ -111,7 +111,7 @@ struct pressio_metrics { operator bool() const { return plugin.get() != nullptr; } private: - std::unique_ptr plugin; + std::shared_ptr plugin; }; /** diff --git a/src/plugins/compressors/blosc_plugin.cc b/src/plugins/compressors/blosc_plugin.cc index 38b7e5b2..33df9d52 100644 --- a/src/plugins/compressors/blosc_plugin.cc +++ b/src/plugins/compressors/blosc_plugin.cc @@ -4,6 +4,7 @@ #include #include "libpressio_ext/cpp/data.h" #include "libpressio_ext/cpp/compressor.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/cpp/pressio.h" #include "pressio_options.h" #include "pressio_data.h" @@ -12,33 +13,30 @@ class blosc_plugin: public libpressio_compressor_plugin { public: - struct pressio_options* get_options_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_integer(options, "blosc:clevel", clevel); - pressio_options_set_integer(options, "blosc:numinternalthreads", numinternalthreads); - pressio_options_set_integer(options, "blosc:doshuffle", doshuffle); - pressio_options_set_uinteger(options, "blosc:blocksize", blocksize); - pressio_options_set_string(options, "blosc:compressor", compressor.c_str()); + struct pressio_options get_options_impl() const override { + struct pressio_options options; + options.set("blosc:clevel", clevel); + options.set("blosc:numinternalthreads", numinternalthreads); + options.set("blosc:doshuffle", doshuffle); + options.set("blosc:blocksize", blocksize); + options.set("blosc:compressor", compressor); return options; } - struct pressio_options* get_configuration_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_integer(options, "pressio:thread_safe", pressio_thread_safety_multiple); + struct pressio_options get_configuration_impl() const override { + struct pressio_options options; + options.set("pressio:thread_safe", static_cast(pressio_thread_safety_multiple)); return options; } - int set_options_impl(struct pressio_options const* options) override { - pressio_options_get_integer(options, "blosc:clevel", &clevel); - pressio_options_get_integer(options, "blosc:numinternalthreads", &numinternalthreads); - pressio_options_get_integer(options, "blosc:doshuffle", &doshuffle); - - unsigned int tmp_blocksize; - pressio_options_get_uinteger(options, "blosc:blocksize", &tmp_blocksize); - blocksize = tmp_blocksize; + int set_options_impl(struct pressio_options const& options) override { + options.get("blosc:clevel", &clevel); + options.get("blosc:numinternalthreads", &numinternalthreads); + options.get("blosc:doshuffle", &doshuffle); + options.get("blosc:blocksize", &blocksize); const char* tmp = nullptr; - pressio_options_get_string(options, "blosc:compressor", &tmp); + pressio_options_get_string(&options, "blosc:compressor", &tmp); compressor = tmp; free((void*)tmp); @@ -122,6 +120,11 @@ class blosc_plugin: public libpressio_compressor_plugin { return BLOSC_VERSION_STRING; } + const char* prefix() const override { + return "blosc"; + } + + private: int internal_error(int rc) { std::stringstream ss; ss << "interal error " << rc; return set_error(1, ss.str()); } int reshape_error() { return set_error(2, "failed to reshape array after compression"); } @@ -129,7 +132,7 @@ class blosc_plugin: public libpressio_compressor_plugin { int clevel; int numinternalthreads = 1; int doshuffle = BLOSC_NOSHUFFLE; - size_t blocksize = 0; + unsigned int blocksize = 0; std::string compressor{BLOSC_BLOSCLZ_COMPNAME}; }; diff --git a/src/plugins/compressors/compressor_base.cc b/src/plugins/compressors/compressor_base.cc index cf18c4d6..d481cce9 100644 --- a/src/plugins/compressors/compressor_base.cc +++ b/src/plugins/compressors/compressor_base.cc @@ -5,6 +5,7 @@ #include #include "libpressio_ext/cpp/compressor.h" #include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" #include "pressio_options_iter.h" #include "pressio_options.h" @@ -31,27 +32,24 @@ int libpressio_compressor_plugin::error_code() const { return error.code; } -std::set get_keys(struct pressio_options const* options) { - std::set keys; - struct pressio_options_iter* iter = pressio_options_get_iter(options); - while(pressio_options_iter_has_value(iter)) - { - const char* key = pressio_options_iter_get_key(iter); - keys.emplace(key); - pressio_options_iter_next(iter); +namespace { + std::set get_keys(struct pressio_options const& options, std::string const& prefix) { + std::set keys; + for (auto const& option : options) { + if(option.first.find(prefix) == 0) + keys.emplace(option.first); + } + return keys; } - pressio_options_iter_free(iter); - return keys; } -int libpressio_compressor_plugin::check_options(struct pressio_options const* options) { +int libpressio_compressor_plugin::check_options(struct pressio_options const& options) { - if(metrics_plugin) (*metrics_plugin)->begin_check_options(options); + if(metrics_plugin) metrics_plugin->begin_check_options(&options); - struct pressio_options* my_options = get_options(); - auto my_keys = get_keys(my_options); - pressio_options_free(my_options); - auto keys = get_keys(options); + struct pressio_options my_options = get_options(); + auto my_keys = get_keys(my_options, prefix()); + auto keys = get_keys(options, prefix()); std::set extra_keys; std::set_difference( std::begin(keys), std::end(keys), @@ -68,57 +66,57 @@ int libpressio_compressor_plugin::check_options(struct pressio_options const* op } auto ret = check_options_impl(options); - if(metrics_plugin) (*metrics_plugin)->end_check_options(options, ret); + if(metrics_plugin) metrics_plugin->end_check_options(&options, ret); return ret; } -struct pressio_options* libpressio_compressor_plugin::get_configuration() const { - if(metrics_plugin) (*metrics_plugin)->begin_get_configuration(); +struct pressio_options libpressio_compressor_plugin::get_configuration() const { + if(metrics_plugin) metrics_plugin->begin_get_configuration(); auto ret = get_configuration_impl(); - if(metrics_plugin) (*metrics_plugin)->end_get_configuration(ret); + if(metrics_plugin) metrics_plugin->end_get_configuration(ret); return ret; } -struct pressio_options* libpressio_compressor_plugin::get_options() const { - if(metrics_plugin) (*metrics_plugin)->begin_get_options(); +struct pressio_options libpressio_compressor_plugin::get_options() const { + if(metrics_plugin) metrics_plugin->begin_get_options(); auto ret = get_options_impl(); - if(metrics_plugin) (*metrics_plugin)->end_get_options(ret); + if(metrics_plugin) metrics_plugin->end_get_options(&ret); return ret; } -int libpressio_compressor_plugin::set_options(struct pressio_options const* options) { - if(metrics_plugin) (*metrics_plugin)->begin_set_options(options); +int libpressio_compressor_plugin::set_options(struct pressio_options const& options) { + if(metrics_plugin) metrics_plugin->begin_set_options(options); auto ret = set_options_impl(options); - if(metrics_plugin) (*metrics_plugin)->end_set_options(options, ret); + if(metrics_plugin) metrics_plugin->end_set_options(options, ret); return ret; } int libpressio_compressor_plugin::compress(const pressio_data *input, struct pressio_data* output) { - if(metrics_plugin) (*metrics_plugin)->begin_compress(input, output); + if(metrics_plugin) metrics_plugin->begin_compress(input, output); auto ret = compress_impl(input, output); - if(metrics_plugin) (*metrics_plugin)->end_compress(input, output, ret); + if(metrics_plugin) metrics_plugin->end_compress(input, output, ret); return ret; } int libpressio_compressor_plugin::decompress(const pressio_data *input, struct pressio_data* output) { - if(metrics_plugin) (*metrics_plugin)->begin_decompress(input, output); + if(metrics_plugin) metrics_plugin->begin_decompress(input, output); auto ret = decompress_impl(input, output); - if(metrics_plugin) (*metrics_plugin)->end_decompress(input, output, ret); + if(metrics_plugin) metrics_plugin->end_decompress(input, output, ret); return ret; } -int libpressio_compressor_plugin::check_options_impl(struct pressio_options const *) { return 0;} +int libpressio_compressor_plugin::check_options_impl(struct pressio_options const &) { return 0;} -struct pressio_options* libpressio_compressor_plugin::get_metrics_results() const { - return (*metrics_plugin)->get_metrics_results(); +struct pressio_options libpressio_compressor_plugin::get_metrics_results() const { + return metrics_plugin->get_metrics_results(); } -struct pressio_metrics* libpressio_compressor_plugin::get_metrics() const { +struct pressio_metrics libpressio_compressor_plugin::get_metrics() const { return metrics_plugin; } -void libpressio_compressor_plugin::set_metrics(struct pressio_metrics* plugin) { +void libpressio_compressor_plugin::set_metrics(pressio_metrics& plugin) { metrics_plugin = plugin; } diff --git a/src/plugins/compressors/magick++.cc b/src/plugins/compressors/magick++.cc index 46b3b124..9adecc77 100644 --- a/src/plugins/compressors/magick++.cc +++ b/src/plugins/compressors/magick++.cc @@ -7,6 +7,7 @@ #include "libpressio_ext/cpp/data.h" #include "libpressio_ext/cpp/compressor.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/cpp/pressio.h" #include "pressio_data.h" #include "pressio_compressor.h" @@ -50,32 +51,32 @@ class magick_plugin: public libpressio_compressor_plugin { }; - struct pressio_options* get_configuration_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_integer(options, "pressio:thread_safe", pressio_thread_safety_multiple); + struct pressio_options get_configuration_impl() const override { + struct pressio_options options; + options.set( "pressio:thread_safe", static_cast(pressio_thread_safety_multiple)); return options; } - struct pressio_options* get_options_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_string(options, "magick:samples_magick", samples_magick.c_str()); - pressio_options_set_string(options, "magick:compressed_magick", compressed_magick.c_str()); - pressio_options_set_uinteger(options, "magick:quality", quality); + struct pressio_options get_options_impl() const override { + struct pressio_options options; + options.set("magick:samples_magick", samples_magick.c_str()); + options.set("magick:compressed_magick", compressed_magick.c_str()); + options.set("magick:quality", quality); return options; } - int set_options_impl(struct pressio_options const* options) override { + int set_options_impl(struct pressio_options const& options) override { const char* tmp = nullptr; - pressio_options_get_string(options, "magick:samples_magick", &tmp); + options.get("magick:samples_magick", &tmp); samples_magick = tmp; free((void*)tmp); - pressio_options_get_string(options, "magick:compressed_magick", &tmp); + options.get("magick:compressed_magick", &tmp); compressed_magick = tmp; free((void*)tmp); - pressio_options_get_uinteger(options, "magick:quality", &quality); + options.get("magick:quality", &quality); return 0; } @@ -215,6 +216,10 @@ class magick_plugin: public libpressio_compressor_plugin { return MagickCore::GetMagickVersion(&unused); } + const char* prefix() const override { + return "magick"; + } + private: int invalid_dimensions(size_t n_dims) { diff --git a/src/plugins/compressors/mgard_plugin.cc b/src/plugins/compressors/mgard_plugin.cc index c0fe3606..ae6d3677 100644 --- a/src/plugins/compressors/mgard_plugin.cc +++ b/src/plugins/compressors/mgard_plugin.cc @@ -39,20 +39,20 @@ get_converted(pressio_option const& arg) class mgard_plugin: public libpressio_compressor_plugin { - struct pressio_options* get_configuration_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_integer(options, "pressio:thread_safe", pressio_thread_safety_single); + struct pressio_options get_configuration_impl() const override { + struct pressio_options options; + pressio_options_set_integer(&options, "pressio:thread_safe", pressio_thread_safety_single); return options; } - struct pressio_options * get_options_impl () const override { - struct pressio_options* options = pressio_options_new(); + struct pressio_options get_options_impl () const override { + struct pressio_options options; - auto set_if_set = [options](const char* key, pressio_option_type type, pressio_option const& option) { + auto set_if_set = [&options](const char* key, pressio_option_type type, pressio_option const& option) { if(option.has_value()) { - options->set(key, option); + options.set(key, option); } else { - options->set_type(key, type); + options.set_type(key, type); } }; set_if_set("mgard:tolerance", pressio_option_double_type, tolerance); @@ -63,10 +63,10 @@ class mgard_plugin: public libpressio_compressor_plugin { return options; }; - int set_options_impl (struct pressio_options const *options) override { + int set_options_impl (struct pressio_options const& options) override { auto set_fn = [options](const char* key, pressio_option& option_out) { - if(options->key_status(key) == pressio_options_key_set) { - option_out = options->get(key); + if(options.key_status(key) == pressio_options_key_set) { + option_out = options.get(key); } }; set_fn("mgard:tolerance", tolerance); @@ -145,6 +145,11 @@ class mgard_plugin: public libpressio_compressor_plugin { return "0.0.0.2"; } + const char* prefix() const override { + return "mgard"; + } + + private: /** diff --git a/src/plugins/compressors/sz_plugin.cc b/src/plugins/compressors/sz_plugin.cc index d060428c..72592593 100644 --- a/src/plugins/compressors/sz_plugin.cc +++ b/src/plugins/compressors/sz_plugin.cc @@ -7,6 +7,7 @@ #include "libpressio_ext/cpp/data.h" #include "libpressio_ext/cpp/compressor.h" #include "libpressio_ext/cpp/pressio.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/compat/std_compat.h" #include "pressio_data.h" #include "pressio_compressor.h" @@ -27,84 +28,84 @@ class sz_plugin: public libpressio_compressor_plugin { } - struct pressio_options* get_configuration_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_integer(options, "pressio:thread_safe", pressio_thread_safety_serialized); + struct pressio_options get_configuration_impl() const override { + struct pressio_options options; + pressio_options_set_integer(&options, "pressio:thread_safe", pressio_thread_safety_serialized); return options; } - struct pressio_options* get_options_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_type(options, "sz:config_file", pressio_option_charptr_type); - pressio_options_set_type(options, "sz:config_struct", pressio_option_userptr_type); - pressio_options_set_uinteger(options, "sz:max_quant_intervals", confparams_cpr->max_quant_intervals); - pressio_options_set_uinteger(options, "sz:quantization_intervals ", confparams_cpr->quantization_intervals); - pressio_options_set_uinteger(options, "sz:max_range_radius", confparams_cpr->maxRangeRadius); - pressio_options_set_integer(options, "sz:sol_id", confparams_cpr->sol_ID); - pressio_options_set_integer(options, "sz:lossless_compressor", confparams_cpr->losslessCompressor); - pressio_options_set_integer(options, "sz:sample_distance", confparams_cpr->sampleDistance); - pressio_options_set_float(options, "sz:pred_threshold", confparams_cpr->predThreshold); - pressio_options_set_integer(options, "sz:sz_mode", confparams_cpr->szMode); - pressio_options_set_integer(options, "sz:gzip_mode", confparams_cpr->gzipMode); - pressio_options_set_integer(options, "sz:error_bound_mode", confparams_cpr->errorBoundMode); - pressio_options_set_double(options, "sz:abs_err_bound", confparams_cpr->absErrBound); - pressio_options_set_double(options, "sz:rel_err_bound", confparams_cpr->relBoundRatio); - pressio_options_set_double(options, "sz:psnr_err_bound", confparams_cpr->psnr); - pressio_options_set_double(options, "sz:pw_rel_err_bound", confparams_cpr->pw_relBoundRatio); - pressio_options_set_integer(options, "sz:segment_size", confparams_cpr->segment_size); - pressio_options_set_integer(options, "sz:pwr_type", confparams_cpr->pwr_type); - pressio_options_set_integer(options, "sz:snapshot_cmpr_step", confparams_cpr->snapshotCmprStep); - pressio_options_set_integer(options, "sz:accelerate_pw_rel_compression", confparams_cpr->accelerate_pw_rel_compression); - pressio_options_set_type(options, "sz:prediction_mode", pressio_option_int32_type); - pressio_options_set_type(options, "sz:plus_bits", pressio_option_int32_type); - pressio_options_set_type(options, "sz:random_access", pressio_option_int32_type); - pressio_options_set_type(options, "sz:data_type", pressio_option_double_type); - pressio_options_set_string(options, "sz:app", app.c_str()); - pressio_options_set_userptr(options, "sz:user_params", user_params); + struct pressio_options get_options_impl() const override { + struct pressio_options options; + options.set_type("sz:config_file", pressio_option_charptr_type); + options.set_type("sz:config_struct", pressio_option_userptr_type); + options.set("sz:max_quant_intervals", confparams_cpr->max_quant_intervals); + options.set("sz:quantization_intervals ", confparams_cpr->quantization_intervals); + options.set("sz:max_range_radius", confparams_cpr->maxRangeRadius); + options.set("sz:sol_id", confparams_cpr->sol_ID); + options.set("sz:lossless_compressor", confparams_cpr->losslessCompressor); + options.set("sz:sample_distance", confparams_cpr->sampleDistance); + options.set("sz:pred_threshold", confparams_cpr->predThreshold); + options.set("sz:sz_mode", confparams_cpr->szMode); + options.set("sz:gzip_mode", confparams_cpr->gzipMode); + options.set("sz:error_bound_mode", confparams_cpr->errorBoundMode); + options.set("sz:abs_err_bound", confparams_cpr->absErrBound); + options.set("sz:rel_err_bound", confparams_cpr->relBoundRatio); + options.set("sz:psnr_err_bound", confparams_cpr->psnr); + options.set("sz:pw_rel_err_bound", confparams_cpr->pw_relBoundRatio); + options.set("sz:segment_size", confparams_cpr->segment_size); + options.set("sz:pwr_type", confparams_cpr->pwr_type); + options.set("sz:snapshot_cmpr_step", confparams_cpr->snapshotCmprStep); + options.set("sz:accelerate_pw_rel_compression", confparams_cpr->accelerate_pw_rel_compression); + options.set_type("sz:prediction_mode", pressio_option_int32_type); + options.set_type("sz:plus_bits", pressio_option_int32_type); + options.set_type("sz:random_access", pressio_option_int32_type); + options.set_type("sz:data_type", pressio_option_double_type); + options.set("sz:app", app.c_str()); + options.set("sz:user_params", user_params); return options; } - int set_options_impl(struct pressio_options const* options) override { + int set_options_impl(struct pressio_options const& options) override { struct sz_params* sz_param; const char* config_file; - if(pressio_options_get_string(options, "sz:config_file", &config_file) == pressio_options_key_set) { + if(options.get("sz:config_file", &config_file) == pressio_options_key_set) { SZ_Finalize(); SZ_Init(config_file); - } else if (pressio_options_get_userptr(options, "sz:config_struct", (void**)&sz_param) == pressio_options_key_set) { + } else if (options.get("sz:config_struct", (void**)&sz_param) == pressio_options_key_set) { SZ_Finalize(); SZ_Init_Params(sz_param); } - pressio_options_get_uinteger(options, "sz:max_quant_intervals", &confparams_cpr->max_quant_intervals); - pressio_options_get_uinteger(options, "sz:quantization_intervals ", &confparams_cpr->quantization_intervals); - pressio_options_get_uinteger(options, "sz:max_range_radius", &confparams_cpr->maxRangeRadius); - pressio_options_get_integer(options, "sz:sol_id", &confparams_cpr->sol_ID); - pressio_options_get_integer(options, "sz:lossless_compressor", &confparams_cpr->losslessCompressor); - pressio_options_get_integer(options, "sz:sample_distance", &confparams_cpr->sampleDistance); - pressio_options_get_float(options, "sz:pred_threshold", &confparams_cpr->predThreshold); - pressio_options_get_integer(options, "sz:sz_mode", &confparams_cpr->szMode); - pressio_options_get_integer(options, "sz:gzip_mode", &confparams_cpr->gzipMode); - pressio_options_get_integer(options, "sz:error_bound_mode", &confparams_cpr->errorBoundMode); - pressio_options_get_double(options, "sz:abs_err_bound", &confparams_cpr->absErrBound); - pressio_options_get_double(options, "sz:rel_err_bound", &confparams_cpr->relBoundRatio); - pressio_options_get_double(options, "sz:psnr_err_bound", &confparams_cpr->psnr); - pressio_options_get_double(options, "sz:pw_rel_err_bound", &confparams_cpr->pw_relBoundRatio); - pressio_options_get_integer(options, "sz:segment_size", &confparams_cpr->segment_size); - pressio_options_get_integer(options, "sz:pwr_type", &confparams_cpr->pwr_type); - pressio_options_get_integer(options, "sz:snapshot_cmpr_step", &confparams_cpr->snapshotCmprStep); - pressio_options_get_integer(options, "sz:prediction_mode", &confparams_cpr->predictionMode); - pressio_options_get_integer(options, "sz:accelerate_pw_rel_compression", &confparams_cpr->accelerate_pw_rel_compression); - pressio_options_get_integer(options, "sz:plus_bits", &confparams_cpr->plus_bits); - pressio_options_get_integer(options, "sz:random_access", &confparams_cpr->randomAccess); - pressio_options_get_integer(options, "sz:data_type", &confparams_cpr->dataType); + options.get("sz:max_quant_intervals", &confparams_cpr->max_quant_intervals); + options.get("sz:quantization_intervals ", &confparams_cpr->quantization_intervals); + options.get("sz:max_range_radius", &confparams_cpr->maxRangeRadius); + options.get("sz:sol_id", &confparams_cpr->sol_ID); + options.get("sz:lossless_compressor", &confparams_cpr->losslessCompressor); + options.get("sz:sample_distance", &confparams_cpr->sampleDistance); + options.get("sz:pred_threshold", &confparams_cpr->predThreshold); + options.get("sz:sz_mode", &confparams_cpr->szMode); + options.get("sz:gzip_mode", &confparams_cpr->gzipMode); + options.get("sz:error_bound_mode", &confparams_cpr->errorBoundMode); + options.get("sz:abs_err_bound", &confparams_cpr->absErrBound); + options.get("sz:rel_err_bound", &confparams_cpr->relBoundRatio); + options.get("sz:psnr_err_bound", &confparams_cpr->psnr); + options.get("sz:pw_rel_err_bound", &confparams_cpr->pw_relBoundRatio); + options.get("sz:segment_size", &confparams_cpr->segment_size); + options.get("sz:pwr_type", &confparams_cpr->pwr_type); + options.get("sz:snapshot_cmpr_step", &confparams_cpr->snapshotCmprStep); + options.get("sz:prediction_mode", &confparams_cpr->predictionMode); + options.get("sz:accelerate_pw_rel_compression", &confparams_cpr->accelerate_pw_rel_compression); + options.get("sz:plus_bits", &confparams_cpr->plus_bits); + options.get("sz:random_access", &confparams_cpr->randomAccess); + options.get("sz:data_type", &confparams_cpr->dataType); const char* tmp_app; - if(pressio_options_get_string(options, "sz:app", &tmp_app) == pressio_options_key_set) + if(pressio_options_get_string(&options, "sz:app", &tmp_app) == pressio_options_key_set) { app = tmp_app; free((void*)tmp_app); } - pressio_options_get_userptr(options, "sz:user_params", &user_params); + pressio_options_get_userptr(&options, "sz:user_params", &user_params); return 0; } @@ -178,6 +179,11 @@ class sz_plugin: public libpressio_compressor_plugin { return sz_version.c_str(); } + const char* prefix() const override { + return "sz"; + } + + private: static int libpressio_type_to_sz_type(pressio_dtype type) { switch(type) diff --git a/src/plugins/compressors/zfp_plugin.cc b/src/plugins/compressors/zfp_plugin.cc index fbe114b2..0fada9d1 100644 --- a/src/plugins/compressors/zfp_plugin.cc +++ b/src/plugins/compressors/zfp_plugin.cc @@ -2,6 +2,7 @@ #include #include "libpressio_ext/cpp/data.h" #include "libpressio_ext/cpp/compressor.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/cpp/pressio.h" #include "pressio_options.h" #include "pressio_data.h" @@ -25,71 +26,71 @@ class zfp_plugin: public libpressio_compressor_plugin { zfp_stream_close(zfp); } - struct pressio_options* get_options_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_uinteger(options, "zfp:minbits", zfp->minbits); - pressio_options_set_uinteger(options, "zfp:maxbits", zfp->maxbits); - pressio_options_set_uinteger(options, "zfp:maxprec", zfp->maxprec); - pressio_options_set_integer(options, "zfp:minexp", zfp->minexp); - pressio_options_set_integer(options, "zfp:execution", zfp_stream_execution(zfp)); - pressio_options_set_uinteger(options, "zfp:omp_threads", zfp_stream_omp_threads(zfp)); - pressio_options_set_uinteger(options, "zfp:omp_chunk_size", zfp_stream_omp_chunk_size(zfp)); - pressio_options_set_type(options, "zfp:precision", pressio_option_uint32_type); - pressio_options_set_type(options, "zfp:accuracy", pressio_option_double_type); - pressio_options_set_type(options, "zfp:rate", pressio_option_double_type); - pressio_options_set_type(options, "zfp:type", pressio_option_uint32_type); - pressio_options_set_type(options, "zfp:dims", pressio_option_int32_type); - pressio_options_set_type(options, "zfp:wra", pressio_option_int32_type); - pressio_options_set_type(options, "zfp:mode", pressio_option_uint32_type); + struct pressio_options get_options_impl() const override { + struct pressio_options options; + options.set("zfp:minbits", zfp->minbits); + options.set("zfp:maxbits", zfp->maxbits); + options.set("zfp:maxprec", zfp->maxprec); + options.set("zfp:minexp", zfp->minexp); + options.set("zfp:execution", static_cast(zfp_stream_execution(zfp))); + options.set("zfp:omp_threads", zfp_stream_omp_threads(zfp)); + options.set("zfp:omp_chunk_size", zfp_stream_omp_chunk_size(zfp)); + options.set_type("zfp:precision", pressio_option_uint32_type); + options.set_type("zfp:accuracy", pressio_option_double_type); + options.set_type("zfp:rate", pressio_option_double_type); + options.set_type("zfp:type", pressio_option_uint32_type); + options.set_type("zfp:dims", pressio_option_int32_type); + options.set_type("zfp:wra", pressio_option_int32_type); + options.set_type("zfp:mode", pressio_option_uint32_type); return options; } - struct pressio_options* get_configuration_impl() const override { - struct pressio_options* options = pressio_options_new(); - pressio_options_set_integer(options, "pressio:thread_safe", pressio_thread_safety_multiple); + struct pressio_options get_configuration_impl() const override { + struct pressio_options options; + pressio_options_set_integer(&options, "pressio:thread_safe", pressio_thread_safety_multiple); return options; } - int set_options_impl(struct pressio_options const* options) override { + int set_options_impl(struct pressio_options const& options) override { //precision, accuracy, and expert mode settings unsigned int mode, precision; double tolerance, rate; - if(pressio_options_get_uinteger(options, "zfp:mode", &mode) == pressio_options_key_set) { + if(options.get("zfp:mode", &mode) == pressio_options_key_set) { zfp_stream_set_mode(zfp, mode); - } else if(pressio_options_get_uinteger(options, "zfp:precision", &precision) == pressio_options_key_set) { + } else if(options.get("zfp:precision", &precision) == pressio_options_key_set) { zfp_stream_set_precision(zfp, precision); - } else if (pressio_options_get_double(options, "zfp:accuracy", &tolerance) == pressio_options_key_set) { + } else if (options.get("zfp:accuracy", &tolerance) == pressio_options_key_set) { zfp_stream_set_accuracy(zfp, tolerance); - } else if (pressio_options_get_double(options, "zfp:rate", &rate) == pressio_options_key_set) { + } else if (options.get("zfp:rate", &rate) == pressio_options_key_set) { unsigned int type, dims; int wra; if( - pressio_options_get_uinteger(options, "zfp:type", &type) == pressio_options_key_set && - pressio_options_get_uinteger(options, "zfp:dims", &dims) == pressio_options_key_set && - pressio_options_get_integer(options, "zfp:wra", &wra) == pressio_options_key_set) { + options.get("zfp:type", &type) == pressio_options_key_set && + options.get("zfp:dims", &dims) == pressio_options_key_set && + options.get("zfp:wra", &wra) == pressio_options_key_set) { zfp_stream_set_rate(zfp, rate, (zfp_type)type, dims, wra); } else { return invalid_rate(); } } else { - pressio_options_get_uinteger(options, "zfp:minbits", &zfp->minbits); - pressio_options_get_uinteger(options, "zfp:maxbits", &zfp->maxbits); - pressio_options_get_uinteger(options, "zfp:maxprec", &zfp->maxprec); - pressio_options_get_integer(options, "zfp:minexp", &zfp->minexp); + options.get("zfp:minbits", &zfp->minbits); + options.get("zfp:maxbits", &zfp->maxbits); + options.get("zfp:maxprec", &zfp->maxprec); + options.get("zfp:minexp", &zfp->minexp); } unsigned int execution; - if(pressio_options_get_uinteger(options, "zfp:execution", &execution) == pressio_options_key_set) { + if(options.get("zfp:execution", &execution) == pressio_options_key_set) { zfp_stream_set_execution(zfp, (zfp_exec_policy)execution); } if(zfp_stream_execution(zfp) == zfp_exec_omp) { unsigned int threads; - if(pressio_options_get_uinteger(options, "zfp:omp_threads", &threads) == pressio_options_key_set) { + if(options.get("zfp:omp_threads", &threads) == pressio_options_key_set) { zfp_stream_set_omp_threads(zfp, threads); } unsigned int chunk_size; - if(pressio_options_get_uinteger(options, "zfp:omp_chunk_size", &chunk_size) == pressio_options_key_set) { + if(options.get("zfp:omp_chunk_size", &chunk_size) == pressio_options_key_set) { zfp_stream_set_omp_chunk_size(zfp, chunk_size); } } @@ -175,6 +176,11 @@ class zfp_plugin: public libpressio_compressor_plugin { return ZFP_VERSION_STRING; } + const char* prefix() const override { + return "zfp"; + } + + private: int invalid_type() { return set_error(1, "invalid_type");} int invalid_dimensions() { return set_error(2, "invalid_dimensions");} diff --git a/src/plugins/metrics/composite.cc b/src/plugins/metrics/composite.cc index d5429f52..bbfde07b 100644 --- a/src/plugins/metrics/composite.cc +++ b/src/plugins/metrics/composite.cc @@ -2,6 +2,7 @@ #include #include "pressio_options.h" #include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/compat/std_compat.h" class composite_plugin : public libpressio_metrics_plugin { @@ -33,13 +34,13 @@ class composite_plugin : public libpressio_metrics_plugin { } } - void begin_set_options(struct pressio_options const* options) override { + void begin_set_options(struct pressio_options const& options) override { for (auto& plugin : plugins) { plugin->begin_set_options(options); } } - void end_set_options(struct pressio_options const* options, int rc) override { + void end_set_options(struct pressio_options const& options, int rc) override { for (auto& plugin : plugins) { plugin->end_set_options(options, rc); } @@ -69,14 +70,13 @@ class composite_plugin : public libpressio_metrics_plugin { } } - struct pressio_options* get_metrics_results() const override { - struct pressio_options* metrics_result = pressio_options_new(); + struct pressio_options get_metrics_results() const override { + struct pressio_options metrics_result; for (auto const& plugin : plugins) { - auto plugin_options = plugin->get_metrics_results(); - auto tmp = pressio_options_merge(metrics_result, plugin_options); - pressio_options_free(plugin_options); - pressio_options_free(metrics_result); - metrics_result = tmp; + pressio_options plugin_options = plugin->get_metrics_results(); + auto tmp = pressio_options_merge(&metrics_result, &plugin_options); + metrics_result = std::move(*tmp); + pressio_options_free(tmp); } set_composite_metrics(metrics_result); @@ -84,22 +84,22 @@ class composite_plugin : public libpressio_metrics_plugin { } private: - void set_composite_metrics(struct pressio_options* opt) const { + void set_composite_metrics(struct pressio_options& opt) const { //compression_rate { unsigned int compression_time, uncompressed_size; - if(pressio_options_get_uinteger(opt, "time:compress", &compression_time) == pressio_options_key_set && - pressio_options_get_uinteger(opt, "size:uncompressed_size", &uncompressed_size) == pressio_options_key_set) { - pressio_options_set_double(opt, "composite:compression_rate", static_cast(uncompressed_size)/compression_time); + if(opt.get("time:compress", &compression_time) == pressio_options_key_set && + opt.get("size:uncompressed_size", &uncompressed_size) == pressio_options_key_set) { + opt.set("composite:compression_rate", static_cast(uncompressed_size)/compression_time); } } //decompression_rate { unsigned int decompression_time, uncompressed_size; - if (pressio_options_get_uinteger(opt, "time:decompress", &decompression_time) == pressio_options_key_set && - pressio_options_get_uinteger(opt, "size:uncompressed_size", &uncompressed_size) == pressio_options_key_set) { - pressio_options_set_double(opt, "composite:decompression_rate", static_cast(uncompressed_size)/decompression_time); + if (opt.get( "time:decompress", &decompression_time) == pressio_options_key_set && + opt.get("size:uncompressed_size", &uncompressed_size) == pressio_options_key_set) { + opt.set("composite:decompression_rate", static_cast(uncompressed_size)/decompression_time); } } diff --git a/src/plugins/metrics/error_stat.cc b/src/plugins/metrics/error_stat.cc index b5e5ee4e..e3eaaeeb 100644 --- a/src/plugins/metrics/error_stat.cc +++ b/src/plugins/metrics/error_stat.cc @@ -3,6 +3,7 @@ #include "pressio_options.h" #include "libpressio_ext/cpp/data.h" #include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/cpp/pressio.h" #include "libpressio_ext/compat/std_compat.h" @@ -96,39 +97,38 @@ class error_stat_plugin : public libpressio_metrics_plugin { public: void begin_compress(const struct pressio_data * input, struct pressio_data const * ) override { - input_data = pressio_data_new_clone(input); + input_data = pressio_data::clone(*input); } void end_decompress(struct pressio_data const*, struct pressio_data const* output, int ) override { - err_metrics = pressio_data_for_each(input_data, output, compute_metrics{}); - pressio_data_free(input_data); + err_metrics = pressio_data_for_each(input_data, *output, compute_metrics{}); } - struct pressio_options* get_metrics_results() const override { - pressio_options* opt = pressio_options_new(); + struct pressio_options get_metrics_results() const override { + pressio_options opt; if(err_metrics) { - pressio_options_set_double(opt, "error_stat:psnr", (*err_metrics).psnr); - pressio_options_set_double(opt, "error_stat:mse", (*err_metrics).mse); - pressio_options_set_double(opt, "error_stat:rmse", (*err_metrics).rmse); - pressio_options_set_double(opt, "error_stat:value_mean", (*err_metrics).value_mean); - pressio_options_set_double(opt, "error_stat:value_std", (*err_metrics).value_std); - pressio_options_set_double(opt, "error_stat:value_min", (*err_metrics).value_min); - pressio_options_set_double(opt, "error_stat:value_max", (*err_metrics).value_max); - pressio_options_set_double(opt, "error_stat:value_range", (*err_metrics).value_range); - pressio_options_set_double(opt, "error_stat:min_error", (*err_metrics).min_error); - pressio_options_set_double(opt, "error_stat:max_error", (*err_metrics).max_error); - pressio_options_set_double(opt, "error_stat:min_rel_error", (*err_metrics).min_rel_error); - pressio_options_set_double(opt, "error_stat:max_rel_error", (*err_metrics).max_rel_error); - pressio_options_set_double(opt, "error_stat:average_difference", (*err_metrics).average_difference); - pressio_options_set_double(opt, "error_stat:average_error", (*err_metrics).average_error); - pressio_options_set_double(opt, "error_stat:difference_range", (*err_metrics).difference_range); - pressio_options_set_double(opt, "error_stat:error_range", (*err_metrics).error_range); + opt.set("error_stat:psnr", (*err_metrics).psnr); + opt.set("error_stat:mse", (*err_metrics).mse); + opt.set("error_stat:rmse", (*err_metrics).rmse); + opt.set("error_stat:value_mean", (*err_metrics).value_mean); + opt.set("error_stat:value_std", (*err_metrics).value_std); + opt.set("error_stat:value_min", (*err_metrics).value_min); + opt.set("error_stat:value_max", (*err_metrics).value_max); + opt.set("error_stat:value_range", (*err_metrics).value_range); + opt.set("error_stat:min_error", (*err_metrics).min_error); + opt.set("error_stat:max_error", (*err_metrics).max_error); + opt.set("error_stat:min_rel_error", (*err_metrics).min_rel_error); + opt.set("error_stat:max_rel_error", (*err_metrics).max_rel_error); + opt.set("error_stat:average_difference", (*err_metrics).average_difference); + opt.set("error_stat:average_error", (*err_metrics).average_error); + opt.set("error_stat:difference_range", (*err_metrics).difference_range); + opt.set("error_stat:error_range", (*err_metrics).error_range); } return opt; } private: - struct pressio_data* input_data; + pressio_data input_data = pressio_data::empty(pressio_byte_dtype, {}); compat::optional err_metrics; }; diff --git a/src/plugins/metrics/metrics_base.cc b/src/plugins/metrics/metrics_base.cc index c0e93387..02e4ad6e 100644 --- a/src/plugins/metrics/metrics_base.cc +++ b/src/plugins/metrics/metrics_base.cc @@ -6,15 +6,15 @@ void libpressio_metrics_plugin::end_check_options(struct pressio_options const*, } void libpressio_metrics_plugin::begin_get_configuration() { } -void libpressio_metrics_plugin::end_get_configuration(struct pressio_options const*) { +void libpressio_metrics_plugin::end_get_configuration(struct pressio_options const&) { } void libpressio_metrics_plugin::begin_get_options() { } void libpressio_metrics_plugin::end_get_options(struct pressio_options const*) { } -void libpressio_metrics_plugin::begin_set_options(struct pressio_options const*) { +void libpressio_metrics_plugin::begin_set_options(struct pressio_options const&) { } -void libpressio_metrics_plugin::end_set_options(struct pressio_options const*, int) { +void libpressio_metrics_plugin::end_set_options(struct pressio_options const&, int) { } void libpressio_metrics_plugin::begin_compress(const struct pressio_data *, struct pressio_data const *) { } diff --git a/src/plugins/metrics/size.cc b/src/plugins/metrics/size.cc index c2be0736..995bbcb9 100644 --- a/src/plugins/metrics/size.cc +++ b/src/plugins/metrics/size.cc @@ -2,6 +2,7 @@ #include "pressio_options.h" #include "libpressio_ext/cpp/metrics.h" #include "libpressio_ext/cpp/pressio.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/compat/std_compat.h" class size_plugin : public libpressio_metrics_plugin { @@ -18,22 +19,22 @@ class size_plugin : public libpressio_metrics_plugin { decompressed_size = pressio_data_get_bytes(output); } - struct pressio_options* get_metrics_results() const override { - pressio_options* opt = pressio_options_new(); + struct pressio_options get_metrics_results() const override { + pressio_options opt; auto set_or_double = [&opt](const char* key, compat::optional size) { if(size) { - pressio_options_set_double(opt, key, *size); + opt.set(key, *size); } else { - pressio_options_set_type(opt, key, pressio_option_double_type); + opt.set_type(key, pressio_option_double_type); } }; auto set_or_size_t = [&opt](const char* key, compat::optional size) { if(size) { - pressio_options_set_uinteger(opt, key, *size); + opt.set(key, static_cast(*size)); } else { - pressio_options_set_type(opt, key, pressio_option_uint32_type); + opt.set_type(key, pressio_option_uint32_type); } }; diff --git a/src/plugins/metrics/time.cc b/src/plugins/metrics/time.cc index af240f3c..4fb7a6f5 100644 --- a/src/plugins/metrics/time.cc +++ b/src/plugins/metrics/time.cc @@ -1,6 +1,7 @@ #include #include "pressio_options.h" #include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" #include "libpressio_ext/cpp/pressio.h" #include "libpressio_ext/compat/std_compat.h" @@ -44,17 +45,17 @@ class time_plugin : public libpressio_metrics_plugin { get_configuration->begin = high_resolution_clock::now(); } - void end_get_configuration(struct pressio_options const* ) override { + void end_get_configuration(struct pressio_options const& ) override { get_configuration->end = high_resolution_clock::now(); } - void begin_set_options(struct pressio_options const* ) override { + void begin_set_options(struct pressio_options const& ) override { set_options = time_range(); set_options->begin = high_resolution_clock::now(); } - void end_set_options(struct pressio_options const* , int ) override { + void end_set_options(struct pressio_options const& , int ) override { set_options->end = high_resolution_clock::now(); } @@ -76,14 +77,14 @@ class time_plugin : public libpressio_metrics_plugin { decompress->end = high_resolution_clock::now(); } - struct pressio_options* get_metrics_results() const override { - struct pressio_options* opt = pressio_options_new(); + struct pressio_options get_metrics_results() const override { + struct pressio_options opt; auto set_or = [&opt](const char* key, timer time) { if(time) { - pressio_options_set_uinteger(opt, key, time->elapsed()); + opt.set(key, time->elapsed()); } else { - pressio_options_set_type(opt, key, pressio_option_uint32_type); + opt.set_type(key, pressio_option_uint32_type); } }; diff --git a/src/pressio_compressor.cc b/src/pressio_compressor.cc index e87d1678..554ddac7 100644 --- a/src/pressio_compressor.cc +++ b/src/pressio_compressor.cc @@ -4,13 +4,13 @@ extern "C" { struct pressio_options* pressio_compressor_get_configuration(struct pressio_compressor const* compressor) { - return compressor->plugin->get_configuration(); + return new pressio_options(compressor->plugin->get_configuration()); } struct pressio_options* pressio_compressor_get_options(struct pressio_compressor const* compressor) { - return compressor->plugin->get_options(); + return new pressio_options(compressor->plugin->get_options()); } int pressio_compressor_set_options(struct pressio_compressor* compressor, struct pressio_options const * options) { - return compressor->plugin->set_options(options); + return compressor->plugin->set_options(*options); } int pressio_compressor_compress(struct pressio_compressor* compressor, const pressio_data *input, struct pressio_data * output) { return compressor->plugin->compress(input, output); @@ -37,19 +37,19 @@ const char* pressio_compressor_error_msg(struct pressio_compressor const* compre return compressor->plugin->error_msg(); } int pressio_compressor_check_options(struct pressio_compressor* compressor, struct pressio_options const * options) { - return compressor->plugin->check_options(options); + return compressor->plugin->check_options(*options); } struct pressio_options* pressio_compressor_get_metrics_results(struct pressio_compressor const* compressor) { - return compressor->plugin->get_metrics_results(); + return new pressio_options(compressor->plugin->get_metrics_results()); } struct pressio_metrics* pressio_compressor_get_metrics(struct pressio_compressor const* compressor) { - return compressor->plugin->get_metrics(); + return new pressio_metrics(compressor->plugin->get_metrics()); } void pressio_compressor_set_metrics(struct pressio_compressor* compressor, struct pressio_metrics* plugin) { - return compressor->plugin->set_metrics(plugin); + return compressor->plugin->set_metrics(*plugin); } void pressio_compressor_release(struct pressio_compressor* compressor) { diff --git a/src/pressio_data.cc b/src/pressio_data.cc index 493aadce..ef578276 100644 --- a/src/pressio_data.cc +++ b/src/pressio_data.cc @@ -1,11 +1,8 @@ -#include #include #include -#include #include #include #include -#include #include #include "pressio_data.h" #include "multi_dimensional_iterator.h" diff --git a/src/pressio_metrics.cc b/src/pressio_metrics.cc index ebdbbe65..4dc5f85c 100644 --- a/src/pressio_metrics.cc +++ b/src/pressio_metrics.cc @@ -1,5 +1,6 @@ #include "pressio_metrics.h" #include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" extern "C" { @@ -8,7 +9,7 @@ void pressio_metrics_free(struct pressio_metrics* metrics) { } struct pressio_options* pressio_metrics_get_results(struct pressio_metrics const* metrics) { - return (*metrics)->get_metrics_results(); + return new pressio_options((*metrics)->get_metrics_results()); } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 908e9e20..55c1f9d8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -58,6 +58,9 @@ if(LIBPRESSIO_HAS_SZ) add_executable(metrics metrics.c make_input_data.cc) target_link_libraries(metrics libpressio) add_test(metrics_test metrics) + + add_gtest(test_register_metrics.cc make_input_data.cc) + add_gtest(test_register_compressor.cc make_input_data.cc) endif() diff --git a/test/magick_basic.cc b/test/magick_basic.cc index a8e17efd..1f58c217 100644 --- a/test/magick_basic.cc +++ b/test/magick_basic.cc @@ -56,8 +56,8 @@ int main(int argc, char *argv[]) exit(pressio_compressor_error_code(compressor)); } - pressio_options* options = pressio_compressor_get_metrics_results(compressor); - std::cout << *options << std::endl; + pressio_options* metric_results = pressio_compressor_get_metrics_results(compressor); + std::cout << *metric_results << std::endl; //recompress the data if(pressio_compressor_compress(compressor, decompressed_data, recompressed_data)) { @@ -68,11 +68,13 @@ int main(int argc, char *argv[]) //free the input, decompressed, and compressed data + pressio_data_free(recompressed_data); pressio_data_free(decompressed_data); pressio_data_free(compressed_data); pressio_data_free(input_data); //free options and the library + pressio_options_free(metric_results); pressio_options_free(magick_options); pressio_metrics_free(metrics); pressio_compressor_release(compressor); diff --git a/test/sz_cpp.cc b/test/sz_cpp.cc index 2e7f1931..99886dcc 100644 --- a/test/sz_cpp.cc +++ b/test/sz_cpp.cc @@ -8,18 +8,22 @@ int main(int argc, char *argv[]) { pressio library; auto compressor = library.get_compressor("sz"); - pressio_options* options = compressor->get_options(); - options->set("sz:error_bound_mode", ABS); - options->set("sz:abs_err_bound", 0.5); + const char* metrics_ids[] = {"time"}; + auto metrics = pressio_metrics(library.get_metrics(std::begin(metrics_ids), std::end(metrics_ids))); + + compressor->set_metrics(metrics); + pressio_options options = compressor->get_options(); + options.set("sz:error_bound_mode", ABS); + options.set("sz:abs_err_bound", 0.5); if(compressor->check_options(options)) { - std::cerr << library.err_msg() << std::endl; - exit(library.err_code()); + std::cerr << compressor->error_msg() << std::endl; + exit(compressor->error_code()); } if(compressor->set_options(options)) { - std::cerr << library.err_msg() << std::endl; - exit(library.err_code()); + std::cerr << compressor->error_msg() << std::endl; + exit(compressor->error_code()); } double* rawinput_data = make_input_data(); @@ -41,7 +45,10 @@ int main(int argc, char *argv[]) exit(library.err_code()); } - delete options; + auto metrics_results = compressor->get_metrics_results(); + for (auto const& metric : metrics_results) { + std::cout << metric.second << std::endl; + } return 0; } diff --git a/test/test_pressio_data.cc b/test/test_pressio_data.cc index 95ab371c..15c7eda4 100644 --- a/test/test_pressio_data.cc +++ b/test/test_pressio_data.cc @@ -48,7 +48,7 @@ struct accumulator { TEST_F(PressioDataTests, ForEach) { pressio_data* d = pressio_data_new_nonowning(pressio_int32_dtype, data.data(), 2, dims); - auto result = pressio_data_for_each(d, accumulator{}); + auto result = pressio_data_for_each(*d, accumulator{}); EXPECT_EQ(result, static_cast(std::accumulate(std::begin(data), std::end(data), 0))); pressio_data_free(d); diff --git a/test/test_register_compressor.cc b/test/test_register_compressor.cc new file mode 100644 index 00000000..d5456ff0 --- /dev/null +++ b/test/test_register_compressor.cc @@ -0,0 +1,152 @@ +#include "gtest/gtest.h" +#include +#include "make_input_data.h" + +#include +#include "libpressio_ext/cpp/data.h" +#include "libpressio_ext/cpp/compressor.h" +#include "libpressio_ext/cpp/options.h" +#include "libpressio_ext/cpp/pressio.h" +#include "libpressio_ext/compressors/sz.h" + +namespace { + struct log_fn{ + template + pressio_data operator()(T* begin, T* end) { + pressio_data log_data = pressio_data::clone(*input); + auto output_it = reinterpret_cast(log_data.data()); + std::transform(begin, end, output_it, [](T i){ return std::log(i); }); + return log_data; + } + pressio_data const* input; + }; + + struct exp_fn{ + template + pressio_data operator()(T* begin, T* end) { + pressio_data log_data = pressio_data::clone(*output); + auto output_it = reinterpret_cast(log_data.data()); + std::transform(begin, end, output_it, [](T i){ return std::exp(i); }); + return log_data; + } + pressio_data const* output; + }; +} + +class log_transform : public libpressio_compressor_plugin { + public: + log_transform(): compressor(nullptr) {} + log_transform(pressio_compressor&& comp): compressor(std::move(comp)) {} + + + //compress and decompress + int compress_impl(pressio_data const* input, pressio_data* output) override { + if(!compressor) return invalid_compressor(); + pressio_data log_input = pressio_data_for_each(*input, log_fn{input}); + return check_error(compressor.plugin->compress(&log_input, output)); + } + + int decompress_impl(pressio_data const* input, pressio_data* output) override { + if(!compressor) return invalid_compressor(); + int rc = compressor.plugin->decompress(input, output); + *output = pressio_data_for_each(*output, exp_fn{output}); + return check_error(rc); + } + + //getting and setting options/configuration + pressio_options get_options_impl() const override { + auto options = compressor.plugin->get_options(); + options.set("log:compressor", (void*)&compressor); + return options; + } + int set_options_impl(pressio_options const& options) override { + if(!compressor) return invalid_compressor(); + int rc = check_error(compressor.plugin->set_options(options)); + void* tmp; + if(options.get("log:compressor", &tmp) == pressio_options_key_set) { + compressor = std::move(*(pressio_compressor*)tmp); + } + return rc; + } + pressio_options get_configuration_impl() const override { + if(!compressor) return pressio_options(); + return compressor.plugin->get_configuration(); + } + int check_options_impl(pressio_options const& options) override { + if(!compressor) return invalid_compressor(); + return check_error(compressor.plugin->check_options(options)); + } + + //getting version information + const char* prefix() const override { + return "log"; + } + const char* version() const override { + return compressor.plugin->version(); + } + int major_version() const override { + return compressor.plugin->major_version(); + } + int minor_version() const override { + return compressor.plugin->minor_version(); + } + int patch_version() const override { + return compressor.plugin->patch_version(); + } + + private: + int check_error(int rc) { + if(rc) { + set_error( + compressor.plugin->error_code(), + compressor.plugin->error_msg() + ); + } + return rc; + } + int invalid_compressor() { return set_error(-1, "compressor must be set"); }; + pressio_compressor compressor; +}; + +static pressio_register X(compressor_plugins(), "log", [](){ return std::make_unique();}); + +TEST(ExternalPlugin, TestLogCompressor) { + pressio library; + + auto sz_compressor = library.get_compressor("sz"); + auto log_compressor = std::make_unique(std::move(sz_compressor)); + auto options = log_compressor->get_options(); + options.set("sz:error_bound_mode", ABS); + options.set("sz:abs_err_bound", 0.5); + + if(log_compressor->check_options(options)) { + std::cerr << log_compressor->error_msg() << std::endl; + exit(log_compressor->error_code()); + } + + if(log_compressor->set_options(options)) { + std::cerr << log_compressor->error_msg() << std::endl; + exit(log_compressor->error_code()); + } + + double* rawinput_data = make_input_data(); + //providing a smaller than expected buffer to save time during testing + std::vector dims{30,30,30}; + + auto input = pressio_data::move(pressio_double_dtype, rawinput_data, dims, pressio_data_libc_free_fn, nullptr); + + auto compressed = pressio_data::empty(pressio_byte_dtype, {}); + + auto decompressed = pressio_data::empty(pressio_double_dtype, dims); + + if(log_compressor->compress(&input, &compressed)) { + std::cerr << library.err_msg() << std::endl; + exit(library.err_code()); + } + + if(log_compressor->decompress(&compressed, &decompressed)) { + std::cerr << library.err_msg() << std::endl; + exit(library.err_code()); + } +} + diff --git a/test/test_register_metrics.cc b/test/test_register_metrics.cc new file mode 100644 index 00000000..e7d2569b --- /dev/null +++ b/test/test_register_metrics.cc @@ -0,0 +1,109 @@ +#include "gtest/gtest.h" +#include +#include "make_input_data.h" + +#include +#include "libpressio_ext/cpp/data.h" +#include "libpressio_ext/cpp/metrics.h" +#include "libpressio_ext/cpp/options.h" +#include "libpressio_ext/cpp/pressio.h" +#include "libpressio_ext/compressors/sz.h" + +class counting_metric: public libpressio_metrics_plugin { + public: + counting_metric() { + //operator[] is non-const, so explicits instantiate each of the values we need + counts[pressio_int8_dtype] = 0; + counts[pressio_int16_dtype] = 0; + counts[pressio_int32_dtype] = 0; + counts[pressio_int64_dtype] = 0; + counts[pressio_uint8_dtype] = 0; + counts[pressio_uint16_dtype] = 0; + counts[pressio_uint32_dtype] = 0; + counts[pressio_uint64_dtype] = 0; + counts[pressio_float_dtype] = 0; + counts[pressio_double_dtype] = 0; + counts[pressio_byte_dtype] = 0; + } + + private: + void begin_compress(pressio_data const* input, pressio_data const*) override { + counts[input->dtype()]++; + } + + pressio_options get_metrics_results() const override { + pressio_options opts; + opts.set("mycounts:int8", counts.at(pressio_int8_dtype)); + opts.set("mycounts:int16", counts.at(pressio_int16_dtype)); + opts.set("mycounts:int32", counts.at(pressio_int32_dtype)); + opts.set("mycounts:int64", counts.at(pressio_int64_dtype)); + opts.set("mycounts:uint8", counts.at(pressio_uint8_dtype)); + opts.set("mycounts:uint16", counts.at(pressio_uint16_dtype)); + opts.set("mycounts:uint32", counts.at(pressio_uint32_dtype)); + opts.set("mycounts:uint64", counts.at(pressio_uint64_dtype)); + opts.set("mycounts:float", counts.at(pressio_float_dtype)); + opts.set("mycounts:double", counts.at(pressio_double_dtype)); + opts.set("mycounts:byte", counts.at(pressio_byte_dtype)); + return opts; + } + + std::map counts; +}; + +//register the plugin in the under the names counts +static pressio_register X(metrics_plugins(), "mycounts", [](){ return compat::make_unique(); }); + +TEST(ExternalPlugin, TestMetricCounts) { + pressio library; + + //test the new one and the old ones + const char* metrics_ids[] = {"mycounts", "size"}; + pressio_metrics metrics = library.get_metrics(std::begin(metrics_ids), std::end(metrics_ids)); + + + auto compressor = library.get_compressor("sz"); + compressor->set_metrics(metrics); + auto options = compressor->get_options(); + options.set("sz:error_bound_mode", ABS); + options.set("sz:abs_err_bound", 0.5); + + + if(compressor->check_options(options)) { + std::cerr << compressor->error_msg() << std::endl; + exit(compressor->error_code()); + } + + if(compressor->set_options(options)) { + std::cerr << compressor->error_msg() << std::endl; + exit(compressor->error_code()); + } + + double* rawinput_data = make_input_data(); + //providing a smaller than expected buffer to save time during testing + std::vector dims{30,30,30}; + + auto input = pressio_data::move(pressio_double_dtype, rawinput_data, dims, pressio_data_libc_free_fn, nullptr); + + auto compressed = pressio_data::empty(pressio_byte_dtype, {}); + + auto decompressed = pressio_data::empty(pressio_double_dtype, dims); + + if(compressor->compress(&input, &compressed)) { + std::cerr << library.err_msg() << std::endl; + exit(library.err_code()); + } + + if(compressor->decompress(&compressed, &decompressed)) { + std::cerr << library.err_msg() << std::endl; + exit(library.err_code()); + } + + auto metrics_results = compressor->get_metrics_results(); + + unsigned int count; + metrics_results.get("mycounts:double", &count); + EXPECT_EQ(count, 1); + + metrics_results.get("mycounts:float", &count); + EXPECT_EQ(count, 0); +}