From 9cdb0e76571ae8827f20bbf618fd5dd5a1a16866 Mon Sep 17 00:00:00 2001 From: Manuel Guenther <manuel.guenther@idiap.ch> Date: Wed, 13 Aug 2014 17:13:50 +0200 Subject: [PATCH] Reverted some modifications for which we now found a better solution. --- bob/io/base/bobskin.cpp | 121 +++++-- bob/io/base/bobskin.h | 17 +- bob/io/base/codec.cpp | 3 +- bob/io/base/{csv.cpp => cpp/CSVFile.cpp} | 90 +++-- bob/io/base/cpp/CodecRegistry.cpp | 22 +- bob/io/base/cpp/File.cpp | 10 + .../{hdf5plugin.cpp => cpp/HDF5ArrayFile.cpp} | 68 +++- bob/io/base/cpp/HDF5Attribute.cpp | 22 +- bob/io/base/cpp/HDF5Dataset.cpp | 25 +- bob/io/base/cpp/HDF5File.cpp | 4 +- bob/io/base/cpp/HDF5Group.cpp | 15 +- bob/io/base/cpp/HDF5Types.cpp | 114 +++---- bob/io/base/cpp/HDF5Utils.cpp | 15 +- bob/io/base/{torch3.cpp => cpp/T3File.cpp} | 113 ++++--- .../{tensor.cpp => cpp/TensorArrayFile.cpp} | 58 +++- bob/io/base/cpp/TensorFile.cpp | 31 +- bob/io/base/cpp/TensorFile.h | 19 +- bob/io/base/cpp/TensorFileHeader.cpp | 67 ++-- bob/io/base/cpp/TensorFileHeader.h | 11 +- bob/io/base/cpp/array.cpp | 134 ++++++++ bob/io/base/cpp/array_type.cpp | 126 +++++++ bob/io/base/cpp/blitz_array.cpp | 69 ++-- bob/io/base/cpp/reorder.cpp | 288 ++++++++++++++++ bob/io/base/{ => cpp}/utils.cpp | 29 +- bob/io/base/file.cpp | 87 ++++- bob/io/base/hdf5.cpp | 1 - .../bob.io.base}/CodecRegistry.h | 12 +- bob/io/base/include/bob.io.base/File.h | 39 ++- bob/io/base/include/bob.io.base/HDF5Dataset.h | 1 - bob/io/base/include/bob.io.base/HDF5File.h | 3 +- bob/io/base/include/bob.io.base/HDF5Group.h | 8 +- bob/io/base/include/bob.io.base/HDF5Types.h | 26 +- bob/io/base/include/bob.io.base/HDF5Utils.h | 4 +- bob/io/base/include/bob.io.base/api.h | 306 ++--------------- bob/io/base/include/bob.io.base/array.h | 173 +++++++++- bob/io/base/include/bob.io.base/array_type.h | 162 +++++++++ bob/io/base/include/bob.io.base/array_utils.h | 50 ++- bob/io/base/include/bob.io.base/blitz_array.h | 43 ++- bob/io/base/include/bob.io.base/reorder.h | 94 ++++++ bob/io/base/include/bob.io.base/utils.h | 105 ++++++ bob/io/base/main.cpp | 114 +------ bob/io/base/plugin.h | 39 --- bob/io/base/reorder.cpp | 317 ------------------ bob/io/base/typeinfo.cpp | 251 -------------- setup.py | 31 +- 45 files changed, 1855 insertions(+), 1482 deletions(-) rename bob/io/base/{csv.cpp => cpp/CSVFile.cpp} (73%) create mode 100644 bob/io/base/cpp/File.cpp rename bob/io/base/{hdf5plugin.cpp => cpp/HDF5ArrayFile.cpp} (70%) rename bob/io/base/{torch3.cpp => cpp/T3File.cpp} (68%) rename bob/io/base/{tensor.cpp => cpp/TensorArrayFile.cpp} (56%) create mode 100644 bob/io/base/cpp/array.cpp create mode 100644 bob/io/base/cpp/array_type.cpp create mode 100644 bob/io/base/cpp/reorder.cpp rename bob/io/base/{ => cpp}/utils.cpp (52%) rename bob/io/base/{cpp => include/bob.io.base}/CodecRegistry.h (86%) create mode 100644 bob/io/base/include/bob.io.base/array_type.h create mode 100644 bob/io/base/include/bob.io.base/reorder.h create mode 100644 bob/io/base/include/bob.io.base/utils.h delete mode 100644 bob/io/base/plugin.h delete mode 100644 bob/io/base/reorder.cpp delete mode 100644 bob/io/base/typeinfo.cpp diff --git a/bob/io/base/bobskin.cpp b/bob/io/base/bobskin.cpp index 8a23c66..494bdaf 100644 --- a/bob/io/base/bobskin.cpp +++ b/bob/io/base/bobskin.cpp @@ -5,46 +5,129 @@ * @brief Implementation of our bobskin class */ -#define BOB_IO_BASE_MODULE #include "bobskin.h" #include <stdexcept> -bobskin::bobskin(PyObject* array, int dtype) { +bobskin::bobskin(PyObject* array, bob::io::base::array::ElementType eltype) { if (!PyArray_CheckExact(array)) { PyErr_SetString(PyExc_TypeError, "input object to bobskin constructor is not (exactly) a numpy.ndarray"); throw std::runtime_error("error is already set"); } - if (!BobIoTypeinfo_SignedSetWithStrides(&m_type, dtype, - PyArray_NDIM((PyArrayObject*)array), - PyArray_DIMS((PyArrayObject*)array), - PyArray_STRIDES((PyArrayObject*)array))) { - throw std::runtime_error("error is already set"); - } + m_type.set<npy_intp>(eltype, PyArray_NDIM((PyArrayObject*)array), + PyArray_DIMS((PyArrayObject*)array), + PyArray_STRIDES((PyArrayObject*)array)); m_ptr = PyArray_DATA((PyArrayObject*)array); } -bobskin::bobskin(PyArrayObject* array, int dtype) { +bobskin::bobskin(PyArrayObject* array, bob::io::base::array::ElementType eltype) { - if (!BobIoTypeinfo_SignedSetWithStrides(&m_type, dtype, - PyArray_NDIM((PyArrayObject*)array), - PyArray_DIMS((PyArrayObject*)array), - PyArray_STRIDES((PyArrayObject*)array))) { - throw std::runtime_error("error is already set"); - } + m_type.set<npy_intp>(eltype, PyArray_NDIM((PyArrayObject*)array), + PyArray_DIMS((PyArrayObject*)array), + PyArray_STRIDES((PyArrayObject*)array)); m_ptr = PyArray_DATA((PyArrayObject*)array); } +static bob::io::base::array::ElementType signed_integer_type(int bits) { + switch(bits) { + case 8: + return bob::io::base::array::t_int8; + case 16: + return bob::io::base::array::t_int16; + case 32: + return bob::io::base::array::t_int32; + case 64: + return bob::io::base::array::t_int64; + default: + PyErr_Format(PyExc_TypeError, "unsupported signed integer element type with %d bits", bits); + } + return bob::io::base::array::t_unknown; +} + +static bob::io::base::array::ElementType unsigned_integer_type(int bits) { + switch(bits) { + case 8: + return bob::io::base::array::t_uint8; + case 16: + return bob::io::base::array::t_uint16; + case 32: + return bob::io::base::array::t_uint32; + case 64: + return bob::io::base::array::t_uint64; + default: + PyErr_Format(PyExc_TypeError, "unsupported unsigned signed integer element type with %d bits", bits); + } + return bob::io::base::array::t_unknown; +} + +static bob::io::base::array::ElementType num_to_type (int num) { + switch(num) { + case NPY_BOOL: + return bob::io::base::array::t_bool; + + //signed integers + case NPY_BYTE: + return signed_integer_type(NPY_BITSOF_CHAR); + case NPY_SHORT: + return signed_integer_type(NPY_BITSOF_SHORT); + case NPY_INT: + return signed_integer_type(NPY_BITSOF_INT); + case NPY_LONG: + return signed_integer_type(NPY_BITSOF_LONG); + case NPY_LONGLONG: + return signed_integer_type(NPY_BITSOF_LONGLONG); + + //unsigned integers + case NPY_UBYTE: + return unsigned_integer_type(NPY_BITSOF_CHAR); + case NPY_USHORT: + return unsigned_integer_type(NPY_BITSOF_SHORT); + case NPY_UINT: + return unsigned_integer_type(NPY_BITSOF_INT); + case NPY_ULONG: + return unsigned_integer_type(NPY_BITSOF_LONG); + case NPY_ULONGLONG: + return unsigned_integer_type(NPY_BITSOF_LONGLONG); + + //floats + case NPY_FLOAT32: + return bob::io::base::array::t_float32; + case NPY_FLOAT64: + return bob::io::base::array::t_float64; +#ifdef NPY_FLOAT128 + case NPY_FLOAT128: + return bob::io::base::array::t_float128; +#endif + + //complex + case NPY_COMPLEX64: + return bob::io::base::array::t_complex64; + case NPY_COMPLEX128: + return bob::io::base::array::t_complex128; +#ifdef NPY_COMPLEX256 + case NPY_COMPLEX256: + return bob::io::base::array::t_complex256; +#endif + + default: + PyErr_Format(PyExc_TypeError, "unsupported NumPy element type (%d)", num); + } + + return bob::io::base::array::t_unknown; +} + bobskin::bobskin(PyBlitzArrayObject* array) { - if (!BobIoTypeinfo_SignedSetWithStrides(&m_type, array->type_num, - array->ndim, array->shape, array->stride)) { + bob::io::base::array::ElementType eltype = num_to_type(array->type_num); + if (eltype == bob::io::base::array::t_unknown) { throw std::runtime_error("error is already set"); } + m_type.set<Py_ssize_t>(num_to_type(array->type_num), array->ndim, + array->shape, array->stride); m_ptr = array->data; } @@ -60,8 +143,8 @@ void bobskin::set(boost::shared_ptr<interface>) { throw std::runtime_error("error is already set"); } -void bobskin::set (const BobIoTypeinfo&) { - PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (const type-information&) implemented - DEBUG ME!"); +void bobskin::set (const bob::io::base::array::typeinfo&) { + PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (const typeinfo&) implemented - DEBUG ME!"); throw std::runtime_error("error is already set"); } diff --git a/bob/io/base/bobskin.h b/bob/io/base/bobskin.h index a503562..7e69132 100644 --- a/bob/io/base/bobskin.h +++ b/bob/io/base/bobskin.h @@ -10,8 +10,13 @@ #define PYTHON_BOB_IO_BOBSKIN_H #include <Python.h> + #include <bob.io.base/array.h> -#include <bob.blitz/cppapi.h> + +extern "C" { +#include <bob.blitz/capi.h> +} + /** * Wraps a PyArrayObject such that we can access it from bob::io @@ -23,12 +28,12 @@ class bobskin: public bob::io::base::array::interface { /** * @brief Builds a new skin from an array like object */ - bobskin(PyObject* array, int dtype); + bobskin(PyObject* array, bob::io::base::array::ElementType eltype); /** * @brief Builds a new skin from a numpy array object */ - bobskin(PyArrayObject* array, int dtype); + bobskin(PyArrayObject* array, bob::io::base::array::ElementType eltype); /** * @brief Builds a new skin around a blitz array object @@ -55,12 +60,12 @@ class bobskin: public bob::io::base::array::interface { * @brief Re-allocates this interface taking into consideration new * requirements. The internal memory should be considered uninitialized. */ - virtual void set (const BobIoTypeinfo& req); + virtual void set (const bob::io::base::array::typeinfo& req); /** * @brief Type information for this interface. */ - virtual const BobIoTypeinfo& type() const { return m_type; } + virtual const bob::io::base::array::typeinfo& type() const { return m_type; } /** * @brief Borrows a reference from the underlying memory. This means @@ -80,7 +85,7 @@ class bobskin: public bob::io::base::array::interface { private: //representation - BobIoTypeinfo m_type; ///< type information + bob::io::base::array::typeinfo m_type; ///< type information void* m_ptr; ///< pointer to the data }; diff --git a/bob/io/base/codec.cpp b/bob/io/base/codec.cpp index 767fd20..bfc3eb9 100644 --- a/bob/io/base/codec.cpp +++ b/bob/io/base/codec.cpp @@ -7,9 +7,8 @@ #define BOB_IO_BASE_MODULE #include <bob.io.base/api.h> -#include "cpp/CodecRegistry.h" -int PyBobIoCodec_Register (const char* extension, const char* description, BobIoFileFactory factory) { +int PyBobIoCodec_Register (const char* extension, const char* description, bob::io::base::file_factory_t factory) { boost::shared_ptr<bob::io::base::CodecRegistry> instance = bob::io::base::CodecRegistry::instance(); diff --git a/bob/io/base/csv.cpp b/bob/io/base/cpp/CSVFile.cpp similarity index 73% rename from bob/io/base/csv.cpp rename to bob/io/base/cpp/CSVFile.cpp index 7932ad8..1200523 100644 --- a/bob/io/base/csv.cpp +++ b/bob/io/base/cpp/CSVFile.cpp @@ -8,10 +8,6 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> -#include <bob.io.base/File.h> - #include <sstream> #include <fstream> #include <string> @@ -24,6 +20,8 @@ #include <boost/shared_array.hpp> #include <boost/algorithm/string.hpp> +#include <bob.io.base/CodecRegistry.h> + typedef boost::tokenizer<boost::escaped_list_separator<char> > Tokenizer; class CSVFile: public bob::io::base::File { @@ -64,16 +62,16 @@ class CSVFile: public bob::io::base::File { return; } - m_arrayset_type.dtype = NPY_FLOAT64; + m_arrayset_type.dtype = bob::io::base::array::t_float64; m_arrayset_type.nd = 1; m_arrayset_type.shape[0] = entries; - BobIoTypeinfo_UpdateStrides(&m_arrayset_type); + m_arrayset_type.update_strides(); m_array_type = m_arrayset_type; m_array_type.nd = 2; m_array_type.shape[0] = m_pos.size(); m_array_type.shape[1] = entries; - BobIoTypeinfo_UpdateStrides(&m_array_type); + m_array_type.update_strides(); } CSVFile(const char* path, char mode): @@ -118,11 +116,11 @@ class CSVFile: public bob::io::base::File { return m_filename.c_str(); } - virtual const BobIoTypeinfo& type() const { + virtual const bob::io::base::array::typeinfo& type() const { return m_arrayset_type; } - virtual const BobIoTypeinfo& type_all() const { + virtual const bob::io::base::array::typeinfo& type_all() const { return m_array_type; } @@ -138,7 +136,7 @@ class CSVFile: public bob::io::base::File { if (m_newfile) throw std::runtime_error("uninitialized CSV file cannot be read"); - if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_array_type)) buffer.set(m_array_type); + if (!buffer.type().is_compatible(m_array_type)) buffer.set(m_array_type); //read contents std::string line; @@ -158,7 +156,7 @@ class CSVFile: public bob::io::base::File { if (m_newfile) throw std::runtime_error("uninitialized CSV file cannot be read"); - if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_arrayset_type)) + if (!buffer.type().is_compatible(m_arrayset_type)) buffer.set(m_arrayset_type); if (index >= m_pos.size()) { @@ -186,12 +184,12 @@ class CSVFile: public bob::io::base::File { virtual size_t append (const bob::io::base::array::interface& buffer) { - const BobIoTypeinfo& type = buffer.type(); + const bob::io::base::array::typeinfo& type = buffer.type(); if (m_newfile) { - if (type.nd != 1 || type.dtype != NPY_FLOAT64) { + if (type.nd != 1 || type.dtype != bob::io::base::array::t_float64) { boost::format m("cannot append %s to file '%s' - CSV files only accept 1D double precision float arrays"); - m % BobIoTypeinfo_Str(&type) % m_filename; + m % type.str() % m_filename; throw std::runtime_error(m.str()); } m_pos.clear(); @@ -203,9 +201,9 @@ class CSVFile: public bob::io::base::File { else { //check compatibility - if (!BobIoTypeinfo_IsCompatible(&m_arrayset_type, &buffer.type())) { + if (!m_arrayset_type.is_compatible(buffer.type())) { boost::format m("CSV file '%s' only accepts arrays of type %s"); - m % m_filename % BobIoTypeinfo_Str(&m_arrayset_type); + m % m_filename % m_arrayset_type.str(); throw std::runtime_error(m.str()); } @@ -217,19 +215,19 @@ class CSVFile: public bob::io::base::File { for (size_t k=1; k<type.shape[0]; ++k) m_file << *(p++) << ","; m_file << *(p++); m_array_type.shape[0] = m_pos.size(); - BobIoTypeinfo_UpdateStrides(&m_array_type); + m_array_type.update_strides(); return (m_pos.size()-1); } virtual void write (const bob::io::base::array::interface& buffer) { - const BobIoTypeinfo& type = buffer.type(); + const bob::io::base::array::typeinfo& type = buffer.type(); if (m_newfile) { - if (type.nd != 2 || type.dtype != NPY_FLOAT64) { + if (type.nd != 2 || type.dtype != bob::io::base::array::t_float64) { boost::format m("cannot write %s to file '%s' - CSV files only accept a single 2D double precision float array as input"); - m % BobIoTypeinfo_Str(&type) % m_filename; + m % type.str() % m_filename; throw std::runtime_error(m.str()); } const double* p = static_cast<const double*>(buffer.ptr()); @@ -243,7 +241,7 @@ class CSVFile: public bob::io::base::File { m_arrayset_type = type; m_arrayset_type.nd = 1; m_arrayset_type.shape[0] = type.shape[1]; - BobIoTypeinfo_UpdateStrides(&m_arrayset_type); + m_arrayset_type.update_strides(); m_array_type = type; m_newfile = false; return; @@ -258,8 +256,8 @@ class CSVFile: public bob::io::base::File { std::fstream m_file; std::string m_filename; bool m_newfile; - BobIoTypeinfo m_array_type; - BobIoTypeinfo m_arrayset_type; + bob::io::base::array::typeinfo m_array_type; + bob::io::base::array::typeinfo m_arrayset_type; std::vector<std::streampos> m_pos; ///< dictionary of line starts static std::string s_codecname; @@ -269,10 +267,48 @@ class CSVFile: public bob::io::base::File { std::string CSVFile::s_codecname = "bob.csv"; /** - * Registration method: use an unique name. Copy the definition to "plugin.h" - * and then call it on "main.cpp" to register the codec. + * From this point onwards we have the registration procedure. If you are + * looking at this file for a coding example, just follow the procedure bellow, + * minus local modifications you may need to apply. + */ + +/** + * This defines the factory method F that can create codecs of this type. + * + * Here are the meanings of the mode flag that should be respected by your + * factory implementation: + * + * 'r': opens for reading only - no modifications can occur; it is an + * error to open a file that does not exist for read-only operations. + * 'w': opens for reading and writing, but truncates the file if it + * exists; it is not an error to open files that do not exist with + * this flag. + * 'a': opens for reading and writing - any type of modification can + * occur. If the file does not exist, this flag is effectively like + * 'w'. + * + * Returns a newly allocated File object that can read and write data to the + * file using a specific backend. + * + * @note: This method can be static. */ -boost::shared_ptr<bob::io::base::File> - make_csv_file (const char* path, char mode) { +static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { return boost::make_shared<CSVFile>(path, mode); } + +/** + * Takes care of codec registration per se. + */ +static bool register_codec() { + + boost::shared_ptr<bob::io::base::CodecRegistry> instance = + bob::io::base::CodecRegistry::instance(); + + instance->registerExtension(".csv", "Comma-Separated Values", &make_file); + instance->registerExtension(".txt", "Comma-Separated Values", &make_file); + + return true; + +} + +static bool codec_registered = register_codec(); diff --git a/bob/io/base/cpp/CodecRegistry.cpp b/bob/io/base/cpp/CodecRegistry.cpp index 483215e..229d580 100644 --- a/bob/io/base/cpp/CodecRegistry.cpp +++ b/bob/io/base/cpp/CodecRegistry.cpp @@ -7,16 +7,15 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.core/logging.h> - -#include "CodecRegistry.h" - #include <vector> #include <boost/filesystem.hpp> #include <boost/format.hpp> +#include <bob.io.base/CodecRegistry.h> + +#include <bob/core/logging.h> + boost::shared_ptr<bob::io::base::CodecRegistry> bob::io::base::CodecRegistry::instance() { static boost::shared_ptr<bob::io::base::CodecRegistry> s_instance(new CodecRegistry()); return s_instance; @@ -33,7 +32,7 @@ const char* bob::io::base::CodecRegistry::getDescription(const char* ext) { return it->second.c_str(); } -void bob::io::base::CodecRegistry::deregisterFactory(BobIoFileFactory factory) { +void bob::io::base::CodecRegistry::deregisterFactory(bob::io::base::file_factory_t factory) { std::vector<std::string> to_remove; for (auto it = s_extension2codec.begin(); it != s_extension2codec.end(); ++it) { @@ -48,7 +47,7 @@ void bob::io::base::CodecRegistry::deregisterFactory(BobIoFileFactory factory) { } void bob::io::base::CodecRegistry::registerExtension(const char* extension, - const char* description, BobIoFileFactory codec) { + const char* description, bob::io::base::file_factory_t codec) { auto it = s_extension2codec.find(extension); @@ -59,8 +58,7 @@ void bob::io::base::CodecRegistry::registerExtension(const char* extension, else if (!s_ignore) { boost::format m("extension already registered: %s - ignoring second registration with description `%s'"); m % extension % description; - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << m.str() << std::endl; + bob::core::error << m.str() << std::endl; throw std::runtime_error(m.str()); } @@ -73,13 +71,13 @@ bool bob::io::base::CodecRegistry::isRegistered(const char* ext) { return (s_extension2codec.find(lower_extension) != s_extension2codec.end()); } -BobIoFileFactory bob::io::base::CodecRegistry::findByExtension (const char* ext) { +bob::io::base::file_factory_t bob::io::base::CodecRegistry::findByExtension (const char* ext) { std::string extension(ext); std::string lower_extension = extension; std::transform(extension.begin(), extension.end(), lower_extension.begin(), ::tolower); - std::map<std::string, BobIoFileFactory>::iterator it = + std::map<std::string, bob::io::base::file_factory_t >::iterator it = s_extension2codec.find(lower_extension); if (it == s_extension2codec.end()) { @@ -92,7 +90,7 @@ BobIoFileFactory bob::io::base::CodecRegistry::findByExtension (const char* ext) } -BobIoFileFactory bob::io::base::CodecRegistry::findByFilenameExtension +bob::io::base::file_factory_t bob::io::base::CodecRegistry::findByFilenameExtension (const char* filename) { return findByExtension(boost::filesystem::path(filename).extension().c_str()); diff --git a/bob/io/base/cpp/File.cpp b/bob/io/base/cpp/File.cpp new file mode 100644 index 0000000..bbdfedf --- /dev/null +++ b/bob/io/base/cpp/File.cpp @@ -0,0 +1,10 @@ +/** + * @date Tue Oct 25 23:25:46 2011 +0200 + * @author Andre Anjos <andre.anjos@idiap.ch> + * + * Copyright (C) Idiap Research Institute, Martigny, Switzerland + */ + +#include <bob.io.base/File.h> + +bob::io::base::File::~File() { } diff --git a/bob/io/base/hdf5plugin.cpp b/bob/io/base/cpp/HDF5ArrayFile.cpp similarity index 70% rename from bob/io/base/hdf5plugin.cpp rename to bob/io/base/cpp/HDF5ArrayFile.cpp index 5982adf..8a9aa97 100644 --- a/bob/io/base/hdf5plugin.cpp +++ b/bob/io/base/cpp/HDF5ArrayFile.cpp @@ -7,15 +7,13 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> -#include <bob.io.base/File.h> -#include <bob.io.base/HDF5File.h> - #include <boost/make_shared.hpp> #include <boost/filesystem.hpp> #include <boost/format.hpp> +#include <bob.io.base/CodecRegistry.h> +#include <bob.io.base/HDF5File.h> + /** * Read and write arrays in HDF5 format */ @@ -67,11 +65,11 @@ class HDF5ArrayFile: public bob::io::base::File { return m_filename.c_str(); } - virtual const BobIoTypeinfo& type_all () const { + virtual const bob::io::base::array::typeinfo& type_all () const { return m_type_array; } - virtual const BobIoTypeinfo& type () const { + virtual const bob::io::base::array::typeinfo& type () const { return m_type_arrayset; } @@ -91,7 +89,7 @@ class HDF5ArrayFile: public bob::io::base::File { throw std::runtime_error(f.str()); } - if(!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_type_array)) buffer.set(m_type_array); + if(!buffer.type().is_compatible(m_type_array)) buffer.set(m_type_array); m_file.read_buffer(m_path, 0, buffer.type(), buffer.ptr()); } @@ -104,7 +102,7 @@ class HDF5ArrayFile: public bob::io::base::File { throw std::runtime_error(f.str()); } - if(!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_type_arrayset)) buffer.set(m_type_arrayset); + if(!buffer.type().is_compatible(m_type_arrayset)) buffer.set(m_type_arrayset); m_file.read_buffer(m_path, index, buffer.type(), buffer.ptr()); } @@ -154,8 +152,8 @@ class HDF5ArrayFile: public bob::io::base::File { bob::io::base::HDF5File m_file; std::string m_filename; - BobIoTypeinfo m_type_array; ///< type for reading all data at once - BobIoTypeinfo m_type_arrayset; ///< type for reading data by sub-arrays + bob::io::base::array::typeinfo m_type_array; ///< type for reading all data at once + bob::io::base::array::typeinfo m_type_arrayset; ///< type for reading data by sub-arrays size_t m_size_arrayset; ///< number of arrays in arrayset mode std::string m_path; ///< default path to use bool m_newfile; ///< path check optimization @@ -167,11 +165,32 @@ class HDF5ArrayFile: public bob::io::base::File { std::string HDF5ArrayFile::s_codecname = "bob.hdf5"; /** - * Registration method: use an unique name. Copy the definition to "plugin.h" - * and then call it on "main.cpp" to register the codec. + * From this point onwards we have the registration procedure. If you are + * looking at this file for a coding example, just follow the procedure bellow, + * minus local modifications you may need to apply. + */ + +/** + * This defines the factory method F that can create codecs of this type. + * + * Here are the meanings of the mode flag that should be respected by your + * factory implementation: + * + * 'r': opens for reading only - no modifications can occur; it is an + * error to open a file that does not exist for read-only operations. + * 'w': opens for reading and writing, but truncates the file if it + * exists; it is not an error to open files that do not exist with + * this flag. + * 'a': opens for reading and writing - any type of modification can + * occur. If the file does not exist, this flag is effectively like + * 'w'. + * + * Returns a newly allocated File object that can read and write data to the + * file using a specific backend. + * + * @note: This method can be static. */ -boost::shared_ptr<bob::io::base::File> - make_hdf5_file (const char* path, char mode) { +static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { bob::io::base::HDF5File::mode_t h5mode; if (mode == 'r') h5mode = bob::io::base::HDF5File::in; @@ -182,3 +201,22 @@ boost::shared_ptr<bob::io::base::File> return boost::make_shared<HDF5ArrayFile>(path, h5mode); } + +/** + * Takes care of codec registration per se. + */ +static bool register_codec() { + static const char* description = "Hierarchical Data Format v5 (default)"; + + boost::shared_ptr<bob::io::base::CodecRegistry> instance = + bob::io::base::CodecRegistry::instance(); + + instance->registerExtension(".h5", description, &make_file); + instance->registerExtension(".hdf5", description, &make_file); + instance->registerExtension(".hdf", description, &make_file); + + return true; + +} + +static bool codec_registered = register_codec(); diff --git a/bob/io/base/cpp/HDF5Attribute.cpp b/bob/io/base/cpp/HDF5Attribute.cpp index 2d42802..e701ace 100644 --- a/bob/io/base/cpp/HDF5Attribute.cpp +++ b/bob/io/base/cpp/HDF5Attribute.cpp @@ -7,12 +7,11 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.core/logging.h> +#include <boost/format.hpp> -#include <bob.io.base/HDF5Attribute.h> +#include <bob/core/logging.h> -#include <boost/format.hpp> +#include <bob.io.base/HDF5Attribute.h> static std::runtime_error status_error(const char* f, herr_t s) { boost::format m("call to HDF5 C-function %s() returned error %d. HDF5 error statck follows:\n%s"); @@ -32,9 +31,8 @@ static void delete_h5dataspace (hid_t* p) { if (*p >= 0) { herr_t err = H5Sclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Sclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Sclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -64,9 +62,8 @@ static void delete_h5type (hid_t* p) { if (*p >= 0) { herr_t err = H5Tclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Tclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Tclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -102,9 +99,8 @@ static void delete_h5attribute (hid_t* p) { if (*p >= 0) { herr_t err = H5Aclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Aclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Aclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; diff --git a/bob/io/base/cpp/HDF5Dataset.cpp b/bob/io/base/cpp/HDF5Dataset.cpp index 3e4b93d..59b2093 100644 --- a/bob/io/base/cpp/HDF5Dataset.cpp +++ b/bob/io/base/cpp/HDF5Dataset.cpp @@ -7,13 +7,12 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.core/logging.h> - #include <boost/format.hpp> #include <boost/make_shared.hpp> #include <boost/shared_array.hpp> +#include <bob/core/logging.h> + #include <bob.io.base/HDF5Utils.h> #include <bob.io.base/HDF5Group.h> #include <bob.io.base/HDF5Dataset.h> @@ -31,9 +30,8 @@ static void delete_h5dataset (hid_t* p) { if (*p >= 0) { herr_t err = H5Dclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Dclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Dclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -63,9 +61,8 @@ static void delete_h5datatype (hid_t* p) { if (*p >= 0) { herr_t err = H5Tclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Tclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Tclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -89,9 +86,8 @@ static void delete_h5plist (hid_t* p) { if (*p >= 0) { herr_t err = H5Pclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Pclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Pclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -113,9 +109,8 @@ static void delete_h5dataspace (hid_t* p) { if (*p >= 0) { herr_t err = H5Sclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Sclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Sclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; diff --git a/bob/io/base/cpp/HDF5File.cpp b/bob/io/base/cpp/HDF5File.cpp index 3f838b4..549069f 100644 --- a/bob/io/base/cpp/HDF5File.cpp +++ b/bob/io/base/cpp/HDF5File.cpp @@ -7,10 +7,10 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/HDF5File.h> #include <boost/format.hpp> +#include <bob.io.base/HDF5File.h> + static unsigned int getH5Access (bob::io::base::HDF5File::mode_t v) { switch(v) { case 0: return H5F_ACC_RDONLY; diff --git a/bob/io/base/cpp/HDF5Group.cpp b/bob/io/base/cpp/HDF5Group.cpp index 486b7ea..aab9166 100644 --- a/bob/io/base/cpp/HDF5Group.cpp +++ b/bob/io/base/cpp/HDF5Group.cpp @@ -7,15 +7,14 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.core/logging.h> - #include <boost/make_shared.hpp> #include <boost/shared_array.hpp> #include <boost/filesystem.hpp> #include <boost/format.hpp> #include <boost/algorithm/string.hpp> +#include <bob/core/logging.h> + #include <bob.io.base/HDF5Group.h> #include <bob.io.base/HDF5Utils.h> @@ -26,9 +25,8 @@ static void delete_h5g (hid_t* p) { if (*p >= 0) { herr_t err = H5Gclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Gclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Gclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -313,9 +311,8 @@ static void delete_h5plist (hid_t* p) { if (*p >= 0) { herr_t err = H5Pclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Pclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Pclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; diff --git a/bob/io/base/cpp/HDF5Types.cpp b/bob/io/base/cpp/HDF5Types.cpp index e628d52..16795bf 100644 --- a/bob/io/base/cpp/HDF5Types.cpp +++ b/bob/io/base/cpp/HDF5Types.cpp @@ -7,11 +7,8 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.core/logging.h> - -#include <sstream> #include <boost/format.hpp> +#include <sstream> #include <boost/make_shared.hpp> /** @@ -27,6 +24,8 @@ #warning Disabling MT locks because Boost < 1.35! #endif +#include <bob/core/logging.h> + #include <bob.io.base/HDF5Types.h> const char* bob::io::base::stringize (hdf5type t) { @@ -214,9 +213,8 @@ static void delete_h5datatype (hid_t* p) { if (*p >= 0) { herr_t err = H5Tclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Tclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Tclose() exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -416,7 +414,7 @@ static bob::io::base::hdf5type get_datatype throw std::runtime_error("cannot handle HDF5 datatype on file using one of the native types supported by this API"); } -bool bob::io::base::HDF5Type::compatible (const BobIoTypeinfo& value) const +bool bob::io::base::HDF5Type::compatible (const bob::io::base::array::typeinfo& value) const { return *this == HDF5Type(value); } @@ -620,9 +618,9 @@ bob::io::base::HDF5Type::HDF5Type(const std::string& value): (const blitz::Array<T,N>& value): \ m_type(E), \ m_shape(value.shape()) { \ - if (N > BOB_BLITZ_MAXDIMS) {\ + if (N > bob::io::base::array::N_MAX_DIMENSIONS_ARRAY) {\ boost::format m("you passed an array with %d dimensions, but this HDF5 API only supports arrays with up to %d dimensions"); \ - m % N % BOB_BLITZ_MAXDIMS; \ + m % N % bob::io::base::array::N_MAX_DIMENSIONS_ARRAY; \ throw std::runtime_error(m.str()); \ } \ } @@ -670,56 +668,53 @@ bob::io::base::HDF5Type::HDF5Type(bob::io::base::hdf5type type, const bob::io::b { } -static bob::io::base::hdf5type array_to_hdf5 (int dtype) { - switch(dtype) { - case NPY_NOTYPE: +static bob::io::base::hdf5type array_to_hdf5 (bob::io::base::array::ElementType eltype) { + switch(eltype) { + case bob::io::base::array::t_unknown: return bob::io::base::unsupported; - case NPY_BOOL: + case bob::io::base::array::t_bool: return bob::io::base::b; - case NPY_INT8: + case bob::io::base::array::t_int8: return bob::io::base::i8; - case NPY_INT16: + case bob::io::base::array::t_int16: return bob::io::base::i16; - case NPY_INT32: + case bob::io::base::array::t_int32: return bob::io::base::i32; - case NPY_INT64: + case bob::io::base::array::t_int64: return bob::io::base::i64; - case NPY_UINT8: + case bob::io::base::array::t_uint8: return bob::io::base::u8; - case NPY_UINT16: + case bob::io::base::array::t_uint16: return bob::io::base::u16; - case NPY_UINT32: + case bob::io::base::array::t_uint32: return bob::io::base::u32; - case NPY_UINT64: + case bob::io::base::array::t_uint64: return bob::io::base::u64; - case NPY_FLOAT32: + case bob::io::base::array::t_float32: return bob::io::base::f32; - case NPY_FLOAT64: + case bob::io::base::array::t_float64: return bob::io::base::f64; -# ifdef NPY_FLOAT128 - case NPY_FLOAT128: + case bob::io::base::array::t_float128: return bob::io::base::f128; -# endif - case NPY_COMPLEX64: + case bob::io::base::array::t_complex64: return bob::io::base::c64; - case NPY_COMPLEX128: + case bob::io::base::array::t_complex128: return bob::io::base::c128; -# ifdef NPY_COMPLEX256 - case NPY_COMPLEX256: + case bob::io::base::array::t_complex256: return bob::io::base::c256; -# endif } throw std::runtime_error("unsupported dtype <=> hdf5 type conversion -- FIXME"); } -bob::io::base::HDF5Type::HDF5Type(const BobIoTypeinfo& ti): +bob::io::base::HDF5Type::HDF5Type(const bob::io::base::array::typeinfo& ti): m_type(array_to_hdf5(ti.dtype)), m_shape(ti.nd, ti.shape) { } -bob::io::base::HDF5Type::HDF5Type(int dtype, const HDF5Shape& extents): - m_type(array_to_hdf5(dtype)), +bob::io::base::HDF5Type::HDF5Type(bob::io::base::array::ElementType eltype, + const HDF5Shape& extents): + m_type(array_to_hdf5(eltype)), m_shape(extents) { } @@ -769,63 +764,56 @@ std::string bob::io::base::HDF5Type::str() const { return retval.str(); } -int bob::io::base::HDF5Type::element_type() const { - +bob::io::base::array::ElementType bob::io::base::HDF5Type::element_type() const { switch (m_type) { case b: - return NPY_BOOL; + return bob::io::base::array::t_bool; case i8: - return NPY_INT8; + return bob::io::base::array::t_int8; case i16: - return NPY_INT16; + return bob::io::base::array::t_int16; case i32: - return NPY_INT32; + return bob::io::base::array::t_int32; case i64: - return NPY_INT64; + return bob::io::base::array::t_int64; case u8: - return NPY_UINT8; + return bob::io::base::array::t_uint8; case u16: - return NPY_UINT16; + return bob::io::base::array::t_uint16; case u32: - return NPY_UINT32; + return bob::io::base::array::t_uint32; case u64: - return NPY_UINT64; + return bob::io::base::array::t_uint64; case f32: - return NPY_FLOAT32; + return bob::io::base::array::t_float32; case f64: - return NPY_FLOAT64; -# ifdef NPY_FLOAT128 + return bob::io::base::array::t_float64; case f128: - return NPY_FLOAT128; -# endif + return bob::io::base::array::t_float128; case c64: - return NPY_COMPLEX64; + return bob::io::base::array::t_complex64; case c128: - return NPY_COMPLEX128; -# ifdef NPY_COMPLEX256 + return bob::io::base::array::t_complex128; case c256: - return NPY_COMPLEX256; -# endif + return bob::io::base::array::t_complex256; case s: throw std::runtime_error("Cannot convert HDF5 string type to an element type to be used in blitz::Array's - FIXME: something is wrong in the logic"); default: break; } - - return NPY_NOTYPE; - + return bob::io::base::array::t_unknown; } -void bob::io::base::HDF5Type::copy_to (BobIoTypeinfo& ti) const { +void bob::io::base::HDF5Type::copy_to (bob::io::base::array::typeinfo& ti) const { ti.dtype = element_type(); ti.nd = shape().n(); - if (ti.nd > (BOB_BLITZ_MAXDIMS+1)) { + if (ti.nd > (BOB_MAX_DIM+1)) { boost::format f("HDF5 type has more (%d) than the allowed maximum number of dimensions (%d)"); - f % ti.nd % (BOB_BLITZ_MAXDIMS+1); + f % ti.nd % (BOB_MAX_DIM+1); throw std::runtime_error(f.str()); } for (size_t i=0; i<ti.nd; ++i) ti.shape[i] = shape()[i]; - BobIoTypeinfo_UpdateStrides(&ti); + ti.update_strides(); } bob::io::base::HDF5Descriptor::HDF5Descriptor(const HDF5Type& type, size_t size, diff --git a/bob/io/base/cpp/HDF5Utils.cpp b/bob/io/base/cpp/HDF5Utils.cpp index f06bd11..b735be4 100644 --- a/bob/io/base/cpp/HDF5Utils.cpp +++ b/bob/io/base/cpp/HDF5Utils.cpp @@ -7,12 +7,11 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.core/logging.h> - #include <boost/format.hpp> #include <boost/make_shared.hpp> +#include <bob/core/logging.h> + #include <bob.io.base/HDF5Utils.h> /** @@ -22,9 +21,8 @@ static void delete_h5file (hid_t* p) { if (*p >= 0) { herr_t err = H5Fclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Fclose(hid=" << *p << ") exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Fclose(hid=" << *p << ") exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; } } delete p; @@ -37,9 +35,8 @@ static void delete_h5p (hid_t* p) { if (*p >= 0) { herr_t err = H5Pclose(*p); if (err < 0) { - auto& error_stream = PyBobCoreLogging_Error(); - error_stream << "H5Pclose(hid=" << *p << ") exited with an error (" << err << "). The stack trace follows:" << std::endl; - error_stream << bob::io::base::format_hdf5_error() << std::endl; + bob::core::error << "H5Pclose(hid=" << *p << ") exited with an error (" << err << "). The stack trace follows:" << std::endl; + bob::core::error << bob::io::base::format_hdf5_error() << std::endl; return; } } diff --git a/bob/io/base/torch3.cpp b/bob/io/base/cpp/T3File.cpp similarity index 68% rename from bob/io/base/torch3.cpp rename to bob/io/base/cpp/T3File.cpp index 5910da8..8380a62 100644 --- a/bob/io/base/torch3.cpp +++ b/bob/io/base/cpp/T3File.cpp @@ -18,11 +18,6 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> -#include <bob.io.base/File.h> -#include <bob.io.base/blitz_array.h> - #include <fstream> #include <boost/filesystem.hpp> #include <boost/make_shared.hpp> @@ -35,6 +30,9 @@ #include <bob.core/check.h> +#include <bob.io.base/CodecRegistry.h> +#include <bob.io.base/blitz_array.h> + static inline size_t get_filesize(const char* filename) { struct stat filestatus; stat(filename, &filestatus); @@ -71,12 +69,12 @@ class T3File: public bob::io::base::File { // are those floats or doubles? if (fsize == (nsamples*framesize*sizeof(float))) { - m_type_array.dtype = NPY_FLOAT32; - m_type_arrayset.dtype = NPY_FLOAT32; + m_type_array.dtype = bob::io::base::array::t_float32; + m_type_arrayset.dtype = bob::io::base::array::t_float32; } else if (fsize == (nsamples*framesize*sizeof(double))) { - m_type_array.dtype = NPY_FLOAT64; - m_type_arrayset.dtype = NPY_FLOAT64; + m_type_array.dtype = bob::io::base::array::t_float64; + m_type_arrayset.dtype = bob::io::base::array::t_float64; } else { boost::format s("Cannot read file '%s', mode = '%c': fsize (%d) != %d*%d*sizeof(float32) nor *sizeof(float64)"); @@ -85,8 +83,8 @@ class T3File: public bob::io::base::File { } size_t shape[2] = {nsamples, framesize}; - BobIoTypeinfo_Set(&m_type_array, m_type_array.dtype, 2, &shape[0]); - BobIoTypeinfo_Set(&m_type_arrayset, m_type_arrayset.dtype, 1, &shape[1]); + m_type_array.set_shape<size_t>(2, &shape[0]); + m_type_arrayset.set_shape<size_t>(1, &shape[1]); m_newfile = false; } @@ -98,11 +96,11 @@ class T3File: public bob::io::base::File { return m_filename.c_str(); } - virtual const BobIoTypeinfo& type_all () const { + virtual const bob::io::base::array::typeinfo& type_all () const { return m_type_array; } - virtual const BobIoTypeinfo& type () const { + virtual const bob::io::base::array::typeinfo& type () const { return m_type_arrayset; } @@ -122,14 +120,14 @@ class T3File: public bob::io::base::File { throw std::runtime_error(f.str()); } - if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_type_array)) buffer.set(m_type_array); + if (!buffer.type().is_compatible(m_type_array)) buffer.set(m_type_array); //open the file, now for reading the contents... std::ifstream ifile(m_filename.c_str(), std::ios::binary|std::ios::in); //skip the first 8 bytes, that contain the header that we already read ifile.seekg(8, std::ios::beg); - ifile.read(static_cast<char*>(buffer.ptr()), BobIoTypeinfo_BufferSize(&buffer.type())); + ifile.read(static_cast<char*>(buffer.ptr()), buffer.type().buffer_size()); } @@ -141,26 +139,26 @@ class T3File: public bob::io::base::File { throw std::runtime_error(f.str()); } - const BobIoTypeinfo& type = buffer.type(); + const bob::io::base::array::typeinfo& type = buffer.type(); - if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_type_arrayset)) buffer.set(m_type_arrayset); + if (!buffer.type().is_compatible(m_type_arrayset)) buffer.set(m_type_arrayset); //open the file, now for reading the contents... std::ifstream ifile(m_filename.c_str(), std::ios::binary|std::ios::in); //skip the first 8 bytes, that contain the header that we already read - ifile.seekg(8 + (index*BobIoTypeinfo_BufferSize(&type)), std::ios::beg); - ifile.read(static_cast<char*>(buffer.ptr()), BobIoTypeinfo_BufferSize(&type)); + ifile.seekg(8 + (index*type.buffer_size()), std::ios::beg); + ifile.read(static_cast<char*>(buffer.ptr()), type.buffer_size()); } virtual size_t append (const bob::io::base::array::interface& buffer) { - const BobIoTypeinfo& info = buffer.type(); + const bob::io::base::array::typeinfo& info = buffer.type(); - if (!m_newfile && !BobIoTypeinfo_IsCompatible(&info, &m_type_arrayset)) { + if (!m_newfile && !info.is_compatible(m_type_arrayset)) { boost::format f("input buffer of type %s cannot be appended to already initialized torch3vision binary file of type %s"); - f % BobIoTypeinfo_Str(&info) % BobIoTypeinfo_Str(&m_type_arrayset); + f % info.str() % m_type_arrayset.str(); throw std::runtime_error(f.str()); } @@ -170,15 +168,15 @@ class T3File: public bob::io::base::File { //can only save uni-dimensional data, so throw if that is not the case if (info.nd != 1) { boost::format m("codec for torch3vision binary files can only save uni-dimensional data, but you passed: %s"); - m % BobIoTypeinfo_Str(&info); + m % info.str(); throw std::runtime_error(m.str()); } //can only save float32 or float64, otherwise, throw. - if ((info.dtype != NPY_FLOAT32) && - (info.dtype != NPY_FLOAT64)) { + if ((info.dtype != bob::io::base::array::t_float32) && + (info.dtype != bob::io::base::array::t_float64)) { boost::format f("cannot have T3 bindata files with type %s - only float32 or float64"); - f % PyBlitzArray_TypenumAsString(info.dtype); + f % bob::io::base::array::stringize(info.dtype); throw std::runtime_error(f.str()); } @@ -207,13 +205,13 @@ class T3File: public bob::io::base::File { throw std::runtime_error(f.str()); } - ofile.write(static_cast<const char*>(buffer.ptr()), BobIoTypeinfo_BufferSize(&info)); + ofile.write(static_cast<const char*>(buffer.ptr()), info.buffer_size()); ofile.close(); //setup new type information ++m_length; size_t shape[2] = {m_length, info.shape[0]}; - BobIoTypeinfo_Set(&m_type_array, m_type_array.dtype, 2, &shape[0]); + m_type_array.set_shape<size_t>(2, &shape[0]); //update the header information on the file ofile.open(m_filename.c_str(), std::ios::binary|std::ios::in|std::ios::out); @@ -232,7 +230,7 @@ class T3File: public bob::io::base::File { virtual void write (const bob::io::base::array::interface& buffer) { m_newfile = true; //force file re-setting - const BobIoTypeinfo& info = buffer.type(); + const bob::io::base::array::typeinfo& info = buffer.type(); if (info.nd == 1) {//just do a normal append append(buffer); @@ -241,10 +239,10 @@ class T3File: public bob::io::base::File { else if (info.nd == 2) { //append every array individually const uint8_t* ptr = static_cast<const uint8_t*>(buffer.ptr()); - BobIoTypeinfo slice_info; - BobIoTypeinfo_Set(&slice_info, info.dtype, 1, &info.shape[1]); + bob::io::base::array::typeinfo slice_info(info.dtype, static_cast<size_t>(1), + &info.shape[1]); for (size_t k=0; k<info.shape[0]; ++k) { - const void* slice_ptr=static_cast<const void*>(ptr+k*BobIoTypeinfo_BufferSize(&slice_info)); + const void* slice_ptr=static_cast<const void*>(ptr+k*slice_info.buffer_size()); bob::io::base::array::blitz_array slice(const_cast<void*>(slice_ptr), slice_info); append(slice); } @@ -253,7 +251,7 @@ class T3File: public bob::io::base::File { else { boost::format f("cannot do single write of torch3vision .bindata file with array with type '%s' - only supports 1D or 2D arrays of types float32 or float64"); - f % BobIoTypeinfo_Str(&info); + f % info.str(); throw std::runtime_error(f.str()); } @@ -263,8 +261,8 @@ class T3File: public bob::io::base::File { std::string m_filename; bool m_newfile; - BobIoTypeinfo m_type_array; - BobIoTypeinfo m_type_arrayset; + bob::io::base::array::typeinfo m_type_array; + bob::io::base::array::typeinfo m_type_arrayset; size_t m_length; static std::string s_codecname; @@ -274,10 +272,47 @@ class T3File: public bob::io::base::File { std::string T3File::s_codecname = "torch3.binary"; /** - * Registration method: use an unique name. Copy the definition to "plugin.h" - * and then call it on "main.cpp" to register the codec. + * From this point onwards we have the registration procedure. If you are + * looking at this file for a coding example, just follow the procedure bellow, + * minus local modifications you may need to apply. + */ + +/** + * This defines the factory method F that can create codecs of this type. + * + * Here are the meanings of the mode flag that should be respected by your + * factory implementation: + * + * 'r': opens for reading only - no modifications can occur; it is an + * error to open a file that does not exist for read-only operations. + * 'w': opens for reading and writing, but truncates the file if it + * exists; it is not an error to open files that do not exist with + * this flag. + * 'a': opens for reading and writing - any type of modification can + * occur. If the file does not exist, this flag is effectively like + * 'w'. + * + * Returns a newly allocated File object that can read and write data to the + * file using a specific backend. + * + * @note: This method can be static. */ -boost::shared_ptr<bob::io::base::File> - make_torch3_file (const char* path, char mode) { +static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { return boost::make_shared<T3File>(path, mode); } + +/** + * Takes care of codec registration per se. + */ +static bool register_codec() { + + boost::shared_ptr<bob::io::base::CodecRegistry> instance = + bob::io::base::CodecRegistry::instance(); + + instance->registerExtension(".bindata", "torch3 binary data format", &make_file); + + return true; + +} + +static bool codec_registered = register_codec(); diff --git a/bob/io/base/tensor.cpp b/bob/io/base/cpp/TensorArrayFile.cpp similarity index 56% rename from bob/io/base/tensor.cpp rename to bob/io/base/cpp/TensorArrayFile.cpp index 8d51dbc..d0cb72d 100644 --- a/bob/io/base/tensor.cpp +++ b/bob/io/base/cpp/TensorArrayFile.cpp @@ -7,11 +7,8 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> -#include <bob.io.base/File.h> - -#include "cpp/TensorFile.h" +#include "TensorFile.h" +#include <bob.io.base/CodecRegistry.h> class TensorArrayFile: public bob::io::base::File { @@ -29,11 +26,11 @@ class TensorArrayFile: public bob::io::base::File { return m_filename.c_str(); } - virtual const BobIoTypeinfo& type_all () const { + virtual const bob::io::base::array::typeinfo& type_all () const { return m_type; } - virtual const BobIoTypeinfo& type () const { + virtual const bob::io::base::array::typeinfo& type () const { return m_type; } @@ -83,7 +80,7 @@ class TensorArrayFile: public bob::io::base::File { private: //representation bob::io::base::TensorFile m_file; - BobIoTypeinfo m_type; + bob::io::base::array::typeinfo m_type; std::string m_filename; static std::string s_codecname; @@ -93,11 +90,32 @@ class TensorArrayFile: public bob::io::base::File { std::string TensorArrayFile::s_codecname = "bob.tensor"; /** - * Registration method: use an unique name. Copy the definition to "plugin.h" - * and then call it on "main.cpp" to register the codec. + * From this point onwards we have the registration procedure. If you are + * looking at this file for a coding example, just follow the procedure bellow, + * minus local modifications you may need to apply. */ -boost::shared_ptr<bob::io::base::File> - make_tensor_file (const char* path, char mode) { + +/** + * This defines the factory method F that can create codecs of this type. + * + * Here are the meanings of the mode flag that should be respected by your + * factory implementation: + * + * 'r': opens for reading only - no modifications can occur; it is an + * error to open a file that does not exist for read-only operations. + * 'w': opens for reading and writing, but truncates the file if it + * exists; it is not an error to open files that do not exist with + * this flag. + * 'a': opens for reading and writing - any type of modification can + * occur. If the file does not exist, this flag is effectively like + * 'w'. + * + * Returns a newly allocated File object that can read and write data to the + * file using a specific backend. + * + * @note: This method can be static. + */ +static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { bob::io::base::TensorFile::openmode _mode; if (mode == 'r') _mode = bob::io::base::TensorFile::in; @@ -108,3 +126,19 @@ boost::shared_ptr<bob::io::base::File> return boost::make_shared<TensorArrayFile>(path, _mode); } + +/** + * Takes care of codec registration per se. + */ +static bool register_codec() { + + boost::shared_ptr<bob::io::base::CodecRegistry> instance = + bob::io::base::CodecRegistry::instance(); + + instance->registerExtension(".tensor", "torch3vision v2.1 tensor files", &make_file); + + return true; + +} + +static bool codec_registered = register_codec(); diff --git a/bob/io/base/cpp/TensorFile.cpp b/bob/io/base/cpp/TensorFile.cpp index d559ba6..66b7216 100644 --- a/bob/io/base/cpp/TensorFile.cpp +++ b/bob/io/base/cpp/TensorFile.cpp @@ -7,10 +7,11 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> #include "TensorFile.h" +#include <bob.io.base/reorder.h> +#include <bob.io.base/array_type.h> + bob::io::base::TensorFile::TensorFile(const std::string& filename, bob::io::base::TensorFile::openmode flag): m_header_init(false), @@ -24,7 +25,7 @@ bob::io::base::TensorFile::TensorFile(const std::string& filename, if(m_stream) { m_header.read(m_stream); - m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); + m_buffer.reset(new char[m_header.m_type.buffer_size()]); m_header_init = true; m_n_arrays_written = m_header.m_n_samples; @@ -39,7 +40,7 @@ bob::io::base::TensorFile::TensorFile(const std::string& filename, m_stream.open(filename.c_str(), std::ios::out | std::ios::in | std::ios::binary); m_header.read(m_stream); - m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); + m_buffer.reset(new char[m_header.m_type.buffer_size()]); m_header_init = true; m_n_arrays_written = m_header.m_n_samples; m_stream.seekp(0, std::ios::end); @@ -52,7 +53,7 @@ bob::io::base::TensorFile::TensorFile(const std::string& filename, m_stream.open(filename.c_str(), std::ios::in | std::ios::binary); if(m_stream) { m_header.read(m_stream); - m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); + m_buffer.reset(new char[m_header.m_type.buffer_size()]); m_header_init = true; m_n_arrays_written = m_header.m_n_samples; @@ -70,7 +71,7 @@ bob::io::base::TensorFile::~TensorFile() { close(); } -void bob::io::base::TensorFile::peek(BobIoTypeinfo& info) const { +void bob::io::base::TensorFile::peek(bob::io::base::array::typeinfo& info) const { info = m_header.m_type; } @@ -82,7 +83,7 @@ void bob::io::base::TensorFile::close() { m_stream.close(); } -void bob::io::base::TensorFile::initHeader(const BobIoTypeinfo& info) { +void bob::io::base::TensorFile::initHeader(const bob::io::base::array::typeinfo& info) { // Check that data have not already been written if (m_n_arrays_written > 0 ) { throw std::runtime_error("cannot init the header of an output stream in which data have already been written"); @@ -94,25 +95,25 @@ void bob::io::base::TensorFile::initHeader(const BobIoTypeinfo& info) { m_header.write(m_stream); // Temporary buffer to help with data transposition... - m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); + m_buffer.reset(new char[m_header.m_type.buffer_size()]); m_header_init = true; } void bob::io::base::TensorFile::write(const bob::io::base::array::interface& data) { - const BobIoTypeinfo& info = data.type(); + const bob::io::base::array::typeinfo& info = data.type(); if (!m_header_init) initHeader(info); else { //checks compatibility with previously written stuff - if (!BobIoTypeinfo_IsCompatible(&m_header.m_type, &info)) + if (!m_header.m_type.is_compatible(info)) throw std::runtime_error("buffer does not conform to expected type"); } - BobIoReorder_RowToCol(data.ptr(), m_buffer.get(), &info); + bob::io::base::row_to_col_order(data.ptr(), m_buffer.get(), info); - m_stream.write(static_cast<const char*>(m_buffer.get()), BobIoTypeinfo_BufferSize(&info)); + m_stream.write(static_cast<const char*>(m_buffer.get()), info.buffer_size()); // increment m_n_arrays_written and m_current_array ++m_current_array; @@ -124,12 +125,12 @@ void bob::io::base::TensorFile::read (bob::io::base::array::interface& buf) { if(!m_header_init) { throw std::runtime_error("TensorFile: header is not initialized"); } - if(!BobIoTypeinfo_IsCompatible(&buf.type(), &m_header.m_type)) buf.set(m_header.m_type); + if(!buf.type().is_compatible(m_header.m_type)) buf.set(m_header.m_type); m_stream.read(reinterpret_cast<char*>(m_buffer.get()), - BobIoTypeinfo_BufferSize(&m_header.m_type)); + m_header.m_type.buffer_size()); - BobIoReorder_ColToRow(m_buffer.get(), buf.ptr(), &m_header.m_type); + bob::io::base::col_to_row_order(m_buffer.get(), buf.ptr(), m_header.m_type); ++m_current_array; } diff --git a/bob/io/base/cpp/TensorFile.h b/bob/io/base/cpp/TensorFile.h index 2c342a4..35d42bf 100644 --- a/bob/io/base/cpp/TensorFile.h +++ b/bob/io/base/cpp/TensorFile.h @@ -10,12 +10,13 @@ #ifndef BOB_IO_TENSORFILE_H #define BOB_IO_TENSORFILE_H -#include "TensorFileHeader.h" - -#include <bob.io.base/blitz_array.h> #include <boost/format.hpp> #include <stdexcept> +#include <bob.io.base/blitz_array.h> + +#include "TensorFileHeader.h" + namespace bob { namespace io { namespace base { /** @@ -93,9 +94,9 @@ namespace bob { namespace io { namespace base { void read (size_t index, bob::io::base::array::interface& data); /** - * Peeks the file and returns the currently set type information + * Peeks the file and returns the currently set typeinfo */ - void peek(BobIoTypeinfo& info) const; + void peek(bob::io::base::array::typeinfo& info) const; /** * Gets the number of samples/arrays written so far @@ -129,7 +130,7 @@ namespace bob { namespace io { namespace base { /** * Initializes the tensor file with the given type and shape. */ - inline void initTensorFile(const BobIoTypeinfo& info) { + inline void initTensorFile(const bob::io::base::array::typeinfo& info) { initHeader(info); } @@ -160,7 +161,7 @@ namespace bob { namespace io { namespace base { * Initializes the header of the (output) stream with the given type * and shape */ - void initHeader(const BobIoTypeinfo& info); + void initHeader(const bob::io::base::array::typeinfo& info); public: @@ -185,7 +186,7 @@ namespace bob { namespace io { namespace base { * multiarrays saved have the same dimensions. */ template <typename T, int D> inline blitz::Array<T,D> read() { - BobIoTypeinfo info; + bob::io::base::array::typeinfo info; peek(info); bob::io::base::array::blitz_array buf(info); read(buf); @@ -194,7 +195,7 @@ namespace bob { namespace io { namespace base { template <typename T, int D> inline blitz::Array<T,D> read(size_t index) { - BobIoTypeinfo info; + bob::io::base::array::typeinfo info; peek(info); bob::io::base::array::blitz_array buf(info); read(index, buf); diff --git a/bob/io/base/cpp/TensorFileHeader.cpp b/bob/io/base/cpp/TensorFileHeader.cpp index 8d8dfee..fb96a13 100644 --- a/bob/io/base/cpp/TensorFileHeader.cpp +++ b/bob/io/base/cpp/TensorFileHeader.cpp @@ -7,11 +7,10 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include "TensorFileHeader.h" -#include <bob.blitz/capi.h> #include <boost/format.hpp> +#include "TensorFileHeader.h" + bob::io::base::detail::TensorFileHeader::TensorFileHeader() : m_tensor_type(bob::io::base::Char), m_type(), @@ -32,28 +31,28 @@ void bob::io::base::detail::TensorFileHeader::read(std::istream& str) { str.seekg(std::ios_base::beg); int val; - str.read(reinterpret_cast<char*>(&val), sizeof(int)); + str.read( reinterpret_cast<char*>(&val), sizeof(int)); m_tensor_type = (bob::io::base::TensorType)val; m_type.dtype = bob::io::base::tensorTypeToArrayType(m_tensor_type); - str.read(reinterpret_cast<char*>(&val), sizeof(int)); + str.read( reinterpret_cast<char*>(&val), sizeof(int)); m_n_samples = (size_t)val; - str.read(reinterpret_cast<char*>(&val), sizeof(int)); - size_t nd = (size_t)val; + int nd; + str.read(reinterpret_cast<char*>(&nd), sizeof(int)); - size_t shape[BOB_BLITZ_MAXDIMS]; + int shape[BOB_MAX_DIM]; - str.read(reinterpret_cast<char*>(&val), sizeof(int)); + str.read( reinterpret_cast<char*>(&val), sizeof(int)); shape[0] = (size_t)val; - str.read(reinterpret_cast<char*>(&val), sizeof(int)); + str.read( reinterpret_cast<char*>(&val), sizeof(int)); shape[1] = (size_t)val; str.read( reinterpret_cast<char*>(&val), sizeof(int)); shape[2] = (size_t)val; str.read( reinterpret_cast<char*>(&val), sizeof(int)); shape[3] = (size_t)val; - BobIoTypeinfo_Set(&m_type, m_type.dtype, nd, shape); + m_type.set_shape(nd, shape); header_ok(); } @@ -65,19 +64,19 @@ void bob::io::base::detail::TensorFileHeader::write(std::ostream& str) const int val; val = (int)m_tensor_type; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); val = (int)m_n_samples; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); val = (int)m_type.nd; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); val = (int)m_type.shape[0]; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); val = (int)m_type.shape[1]; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); val = (int)m_type.shape[2]; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); val = (int)m_type.shape[3]; - str.write(reinterpret_cast<char*>(&val), sizeof(int)); + str.write( reinterpret_cast<char*>(&val), sizeof(int)); } void bob::io::base::detail::TensorFileHeader::header_ok() @@ -101,7 +100,7 @@ void bob::io::base::detail::TensorFileHeader::header_ok() // Check the number of samples and dimensions if( m_type.nd < 1 || m_type.nd > 4) { boost::format m("header for tensor file indicates an unsupported type: %s"); - m % BobIoTypeinfo_Str(&m_type); + m % m_type.str(); throw std::runtime_error(m.str()); } @@ -131,43 +130,43 @@ void bob::io::base::detail::TensorFileHeader::update() } -bob::io::base::TensorType bob::io::base::arrayTypeToTensorType(int dtype) +bob::io::base::TensorType bob::io::base::arrayTypeToTensorType(bob::io::base::array::ElementType eltype) { - switch(dtype) + switch(eltype) { - case NPY_INT8: + case bob::io::base::array::t_int8: return bob::io::base::Char; - case NPY_INT16: + case bob::io::base::array::t_int16: return bob::io::base::Short; - case NPY_INT32: + case bob::io::base::array::t_int32: return bob::io::base::Int; - case NPY_INT64: + case bob::io::base::array::t_int64: return bob::io::base::Long; - case NPY_FLOAT32: + case bob::io::base::array::t_float32: return bob::io::base::Float; - case NPY_FLOAT64: + case bob::io::base::array::t_float64: return bob::io::base::Double; default: throw std::runtime_error("unsupported data type found while converting array type to tensor type"); } } -int bob::io::base::tensorTypeToArrayType(bob::io::base::TensorType tensortype) +bob::io::base::array::ElementType bob::io::base::tensorTypeToArrayType(bob::io::base::TensorType tensortype) { switch(tensortype) { case bob::io::base::Char: - return NPY_INT8; + return bob::io::base::array::t_int8; case bob::io::base::Short: - return NPY_INT16; + return bob::io::base::array::t_int16; case bob::io::base::Int: - return NPY_INT32; + return bob::io::base::array::t_int32; case bob::io::base::Long: - return NPY_INT64; + return bob::io::base::array::t_int64; case bob::io::base::Float: - return NPY_FLOAT32; + return bob::io::base::array::t_float32; case bob::io::base::Double: - return NPY_FLOAT64; + return bob::io::base::array::t_float64; default: throw std::runtime_error("unsupported data type found while converting tensor type to array type"); } diff --git a/bob/io/base/cpp/TensorFileHeader.h b/bob/io/base/cpp/TensorFileHeader.h index 7f3275d..7e852b8 100644 --- a/bob/io/base/cpp/TensorFileHeader.h +++ b/bob/io/base/cpp/TensorFileHeader.h @@ -11,9 +11,10 @@ #ifndef BOB_IO_BASE_TENSORFILEHEADER_H #define BOB_IO_BASE_TENSORFILEHEADER_H -#include <bob.io.base/api.h> -#include <blitz/array.h> #include <fstream> +#include <blitz/array.h> + +#include <bob.io.base/array.h> namespace bob { namespace io { namespace base { @@ -28,8 +29,8 @@ namespace bob { namespace io { namespace base { Double }; - TensorType arrayTypeToTensorType(int dtype); - int tensorTypeToArrayType(bob::io::base::TensorType tensortype); + TensorType arrayTypeToTensorType(bob::io::base::array::ElementType eltype); + bob::io::base::array::ElementType tensorTypeToArrayType(bob::io::base::TensorType tensortype); namespace detail { /** @@ -84,7 +85,7 @@ namespace bob { namespace io { namespace base { //representation TensorType m_tensor_type; ///< array element type - BobIoTypeinfo m_type; ///< the type information + bob::io::base::array::typeinfo m_type; ///< the type information size_t m_n_samples; ///< total number of arrays in the file size_t m_tensor_size; ///< the number of dimensions in each array }; diff --git a/bob/io/base/cpp/array.cpp b/bob/io/base/cpp/array.cpp new file mode 100644 index 0000000..2ffc94d --- /dev/null +++ b/bob/io/base/cpp/array.cpp @@ -0,0 +1,134 @@ +/** + * @date Tue Nov 8 15:34:31 2011 +0100 + * @author Andre Anjos <andre.anjos@idiap.ch> + * + * @brief Some buffer stuff + * + * Copyright (C) Idiap Research Institute, Martigny, Switzerland + */ + +#include <boost/format.hpp> +#include <bob.io.base/array.h> + +bob::io::base::array::typeinfo::typeinfo(): + dtype(bob::io::base::array::t_unknown), + nd(0) +{ +} + +bob::io::base::array::typeinfo::typeinfo(const bob::io::base::array::typeinfo& other): + dtype(other.dtype) +{ + set_shape(other.nd, other.shape); +} + +bob::io::base::array::typeinfo& bob::io::base::array::typeinfo::operator= (const bob::io::base::array::typeinfo& other) { + dtype = other.dtype; + set_shape(other.nd, other.shape); + return *this; +} + +void bob::io::base::array::typeinfo::reset() { + dtype = bob::io::base::array::t_unknown; + nd = 0; +} + +bool bob::io::base::array::typeinfo::is_valid() const { + return (dtype != bob::io::base::array::t_unknown) && (nd > 0) && (nd <= (BOB_MAX_DIM+1)) && has_valid_shape(); +} + +void bob::io::base::array::typeinfo::update_strides() { + switch (nd) { + case 0: + return; + case 1: + stride[0] = 1; + return; + case 2: + stride[1] = 1; + stride[0] = shape[1]; + return; + case 3: + stride[2] = 1; + stride[1] = shape[2]; + stride[0] = shape[1]*shape[2]; + return; + case 4: + stride[3] = 1; + stride[2] = shape[3]; + stride[1] = shape[2]*shape[3]; + stride[0] = shape[1]*shape[2]*shape[3]; + return; + case 5: + stride[4] = 1; + stride[3] = shape[4]; + stride[2] = shape[3]*shape[4]; + stride[1] = shape[2]*shape[3]*shape[4]; + stride[0] = shape[1]*shape[2]*shape[3]*shape[4]; + return; + default: + break; + } + throw std::runtime_error("unsupported number of dimensions"); +} + +size_t bob::io::base::array::typeinfo::size() const { + size_t retval = 1; + for (size_t k=0; k<nd; ++k) retval *= shape[k]; + return retval; +} + +size_t bob::io::base::array::typeinfo::buffer_size() const { + return size()*bob::io::base::array::getElementSize(dtype); +} + +static bool same_shape(size_t nd, const size_t* s1, const size_t* s2) { + for (size_t k=0; k<nd; ++k) if (s1[k] != s2[k]) return false; + return true; +} + +bool bob::io::base::array::typeinfo::is_compatible(const bob::io::base::array::typeinfo& other) const { + return (dtype == other.dtype) && (nd == other.nd) && same_shape(nd, shape, other.shape); +} + +std::string bob::io::base::array::typeinfo::str() const { + boost::format s("dtype: %s (%d); shape: [%s]; size: %d bytes"); + size_t sz = 0; + size_t buf_sz = 0; + if (dtype != bob::io::base::array::t_unknown) { + //otherwise it throws + sz = item_size(); + buf_sz = buffer_size(); + } + s % item_str() % sz; + switch (nd) { + case 0: + s % ""; + break; + case 1: + s % (boost::format("%d") % shape[0]).str(); + break; + case 2: + s % (boost::format("%d,%d") % shape[0] % shape[1]).str(); + break; + case 3: + s % (boost::format("%d,%d,%d") % shape[0] % shape[1] % shape[2]).str(); + break; + case 4: + s % (boost::format("%d,%d,%d,%d") % shape[0] % shape[1] % shape[2] % shape[3]).str(); + break; + default: + s % ">4 dimensions?"; + break; + } + s % buf_sz; + return s.str(); +} + +void bob::io::base::array::typeinfo::reset_shape() { + shape[0] = 0; +} + +bool bob::io::base::array::typeinfo::has_valid_shape() const { + return shape[0] != 0; +} diff --git a/bob/io/base/cpp/array_type.cpp b/bob/io/base/cpp/array_type.cpp new file mode 100644 index 0000000..d42368e --- /dev/null +++ b/bob/io/base/cpp/array_type.cpp @@ -0,0 +1,126 @@ +/** + * @date Sat Apr 9 18:10:10 2011 +0200 + * @author Laurent El Shafey <Laurent.El-Shafey@idiap.ch> + * + * @brief Some type-related array utilities + * + * Copyright (C) Idiap Research Institute, Martigny, Switzerland + */ + +#include <bob.io.base/array_type.h> +#include <boost/format.hpp> + +static const char* t_bool_string = "bool"; +static const char* t_int8_string = "int8"; +static const char* t_int16_string = "int16"; +static const char* t_int32_string = "int32"; +static const char* t_int64_string = "int64"; +static const char* t_uint8_string = "uint8"; +static const char* t_uint16_string = "uint16"; +static const char* t_uint32_string = "uint32"; +static const char* t_uint64_string = "uint64"; +static const char* t_float32_string = "float32"; +static const char* t_float64_string = "float64"; +static const char* t_float128_string = "float128"; +static const char* t_complex64_string = "complex64"; +static const char* t_complex128_string = "complex128"; +static const char* t_complex256_string = "complex256"; +static const char* t_unknown_string = "unknown"; + +size_t bob::io::base::array::getElementSize(ElementType t) { + switch(t) { + case bob::io::base::array::t_bool: + return sizeof(bool); + case bob::io::base::array::t_int8: + return sizeof(int8_t); + case bob::io::base::array::t_int16: + return sizeof(int16_t); + case bob::io::base::array::t_int32: + return sizeof(int32_t); + case bob::io::base::array::t_int64: + return sizeof(int64_t); + case bob::io::base::array::t_uint8: + return sizeof(uint8_t); + case bob::io::base::array::t_uint16: + return sizeof(uint16_t); + case bob::io::base::array::t_uint32: + return sizeof(uint32_t); + case bob::io::base::array::t_uint64: + return sizeof(uint64_t); + case bob::io::base::array::t_float32: + return sizeof(float); + case bob::io::base::array::t_float64: + return sizeof(double); + case bob::io::base::array::t_float128: + return sizeof(long double); + case bob::io::base::array::t_complex64: + return sizeof(std::complex<float>); + case bob::io::base::array::t_complex128: + return sizeof(std::complex<double>); + case bob::io::base::array::t_complex256: + return sizeof(std::complex<long double>); + default: + { + boost::format m("unsupported element type (%d)"); + m % (int)t; + throw std::runtime_error(m.str()); + } + } +} + +const char* bob::io::base::array::stringize(ElementType t) { + switch(t) { + case bob::io::base::array::t_bool: + return t_bool_string; + case bob::io::base::array::t_int8: + return t_int8_string; + case bob::io::base::array::t_int16: + return t_int16_string; + case bob::io::base::array::t_int32: + return t_int32_string; + case bob::io::base::array::t_int64: + return t_int64_string; + case bob::io::base::array::t_uint8: + return t_uint8_string; + case bob::io::base::array::t_uint16: + return t_uint16_string; + case bob::io::base::array::t_uint32: + return t_uint32_string; + case bob::io::base::array::t_uint64: + return t_uint64_string; + case bob::io::base::array::t_float32: + return t_float32_string; + case bob::io::base::array::t_float64: + return t_float64_string; + case bob::io::base::array::t_float128: + return t_float128_string; + case bob::io::base::array::t_complex64: + return t_complex64_string; + case bob::io::base::array::t_complex128: + return t_complex128_string; + case bob::io::base::array::t_complex256: + return t_complex256_string; + default: + return t_unknown_string; + } +} + +bob::io::base::array::ElementType bob::io::base::array::unstringize(const char* s) { + std::string sc(s); + if (sc == t_bool_string) return bob::io::base::array::t_bool; + if (sc == t_int8_string) return bob::io::base::array::t_int8; + if (sc == t_int16_string) return bob::io::base::array::t_int16; + if (sc == t_int32_string) return bob::io::base::array::t_int32; + if (sc == t_int64_string) return bob::io::base::array::t_int64; + if (sc == t_uint8_string) return bob::io::base::array::t_uint8; + if (sc == t_uint16_string) return bob::io::base::array::t_uint16; + if (sc == t_uint32_string) return bob::io::base::array::t_uint32; + if (sc == t_uint64_string) return bob::io::base::array::t_uint64; + if (sc == t_float32_string) return bob::io::base::array::t_float32; + if (sc == t_float64_string) return bob::io::base::array::t_float64; + if (sc == t_float128_string) return bob::io::base::array::t_float128; + if (sc == t_complex64_string) return bob::io::base::array::t_complex64; + if (sc == t_complex128_string) return bob::io::base::array::t_complex128; + if (sc == t_complex256_string) return bob::io::base::array::t_complex256; + return bob::io::base::array::t_unknown; +} diff --git a/bob/io/base/cpp/blitz_array.cpp b/bob/io/base/cpp/blitz_array.cpp index 9439a4c..2bc723a 100644 --- a/bob/io/base/cpp/blitz_array.cpp +++ b/bob/io/base/cpp/blitz_array.cpp @@ -7,10 +7,10 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/blitz_array.h> #include <stdexcept> +#include <bob.io.base/blitz_array.h> + bob::io::base::array::blitz_array::blitz_array(boost::shared_ptr<blitz_array> other) { set(other); } @@ -27,26 +27,21 @@ bob::io::base::array::blitz_array::blitz_array(const interface& other) { set(other); } -bob::io::base::array::blitz_array::blitz_array(const BobIoTypeinfo& info) { +bob::io::base::array::blitz_array::blitz_array(const typeinfo& info) { set(info); } -bob::io::base::array::blitz_array::blitz_array(void* data, const BobIoTypeinfo& info): - m_type(), +bob::io::base::array::blitz_array::blitz_array(void* data, const typeinfo& info): + m_type(info), m_ptr(data), m_is_blitz(false) { - if (!BobIoTypeinfo_Copy(&m_type, &info)) { - throw std::runtime_error("error already set"); - } } bob::io::base::array::blitz_array::~blitz_array() { } void bob::io::base::array::blitz_array::set(boost::shared_ptr<blitz_array> other) { - if (!BobIoTypeinfo_Copy(&m_type, &other->m_type)) { - throw std::runtime_error("error already set"); - } + m_type = other->m_type; m_ptr = other->m_ptr; m_is_blitz = other->m_is_blitz; m_data = other->m_data; @@ -54,13 +49,11 @@ void bob::io::base::array::blitz_array::set(boost::shared_ptr<blitz_array> other void bob::io::base::array::blitz_array::set(const interface& other) { set(other.type()); - memcpy(m_ptr, other.ptr(), BobIoTypeinfo_BufferSize(&m_type)); + memcpy(m_ptr, other.ptr(), m_type.buffer_size()); } void bob::io::base::array::blitz_array::set(boost::shared_ptr<interface> other) { - if (!BobIoTypeinfo_Copy(&m_type, &other->type())) { - throw std::runtime_error("error already set"); - } + m_type = other->type(); m_ptr = other->ptr(); m_is_blitz = false; m_data = other; @@ -112,66 +105,58 @@ static boost::shared_ptr<void> make_array(size_t nd, const size_t* shape, throw std::runtime_error("unsupported number of dimensions -- debug me"); } -void bob::io::base::array::blitz_array::set (const BobIoTypeinfo& req) { - if (BobIoTypeinfo_IsCompatible(&m_type, &req)) return; ///< double-check requirement first! - - //have to go through reallocation - if (!BobIoTypeinfo_Copy(&m_type, &req)) { - throw std::runtime_error("error already set"); - } +void bob::io::base::array::blitz_array::set (const bob::io::base::array::typeinfo& req) { + if (m_type.is_compatible(req)) return; ///< double-check requirement first! + //ok, have to go through reallocation + m_type = req; m_is_blitz = true; - switch (m_type.dtype) { - case NPY_BOOL: + case bob::io::base::array::t_bool: m_data = make_array<bool>(req.nd, req.shape, m_ptr); return; - case NPY_INT8: + case bob::io::base::array::t_int8: m_data = make_array<int8_t>(req.nd, req.shape, m_ptr); return; - case NPY_INT16: + case bob::io::base::array::t_int16: m_data = make_array<int16_t>(req.nd, req.shape, m_ptr); return; - case NPY_INT32: + case bob::io::base::array::t_int32: m_data = make_array<int32_t>(req.nd, req.shape, m_ptr); return; - case NPY_INT64: + case bob::io::base::array::t_int64: m_data = make_array<int64_t>(req.nd, req.shape, m_ptr); return; - case NPY_UINT8: + case bob::io::base::array::t_uint8: m_data = make_array<uint8_t>(req.nd, req.shape, m_ptr); return; - case NPY_UINT16: + case bob::io::base::array::t_uint16: m_data = make_array<uint16_t>(req.nd, req.shape, m_ptr); return; - case NPY_UINT32: + case bob::io::base::array::t_uint32: m_data = make_array<uint32_t>(req.nd, req.shape, m_ptr); return; - case NPY_UINT64: + case bob::io::base::array::t_uint64: m_data = make_array<uint64_t>(req.nd, req.shape, m_ptr); return; - case NPY_FLOAT32: + case bob::io::base::array::t_float32: m_data = make_array<float>(req.nd, req.shape, m_ptr); return; - case NPY_FLOAT64: + case bob::io::base::array::t_float64: m_data = make_array<double>(req.nd, req.shape, m_ptr); return; -# ifdef NPY_FLOAT128 - case NPY_FLOAT128: + case bob::io::base::array::t_float128: m_data = make_array<long double>(req.nd, req.shape, m_ptr); return; -# endif - case NPY_COMPLEX64: + case bob::io::base::array::t_complex64: m_data = make_array<std::complex<float> >(req.nd, req.shape, m_ptr); return; - case NPY_COMPLEX128: + case bob::io::base::array::t_complex128: m_data = make_array<std::complex<double> >(req.nd, req.shape, m_ptr); return; -# ifdef NPY_COMPLEX256 - case NPY_COMPLEX256: + case bob::io::base::array::t_complex256: m_data = make_array<std::complex<long double> >(req.nd, req.shape, m_ptr); return; -# endif default: break; } diff --git a/bob/io/base/cpp/reorder.cpp b/bob/io/base/cpp/reorder.cpp new file mode 100644 index 0000000..cda5ab3 --- /dev/null +++ b/bob/io/base/cpp/reorder.cpp @@ -0,0 +1,288 @@ +/** + * @date Tue Nov 22 11:24:44 2011 +0100 + * @author Andre Anjos <andre.anjos@idiap.ch> + * + * @brief Implementation of row-major/column-major reordering + * + * Copyright (C) Idiap Research Institute, Martigny, Switzerland + */ + +#include <boost/format.hpp> +#include <cstring> //for memcpy + +#include <bob.io.base/reorder.h> + +void bob::io::base::rc2d(size_t& row, size_t& col, const size_t i, const size_t j, + const size_t* shape) { + row = (i * shape[1]) + j; + col = (j * shape[0]) + i; +} + +void bob::io::base::rc3d(size_t& row, size_t& col, const size_t i, const size_t j, + const size_t k, const size_t* shape) { + row = ( (i * shape[1]) + j ) * shape[2] + k; + col = ( (k * shape[1]) + j ) * shape[0] + i; +} + +void bob::io::base::rc4d(size_t& row, size_t& col, const size_t i, const size_t j, + const size_t k, const size_t l, const size_t* shape) { + row = ( ( i * shape[1] + j ) * shape[2] + k ) * shape[3] + l; + col = ( ( l * shape[2] + k ) * shape[1] + j ) * shape[0] + i; +} + +void bob::io::base::row_to_col_order(const void* src_, void* dst_, + const bob::io::base::array::typeinfo& info) { + + size_t dsize = info.item_size(); + + //cast to byte type so we can manipulate the pointers... + const uint8_t* src = static_cast<const uint8_t*>(src_); + uint8_t* dst = static_cast<uint8_t*>(dst_); + + switch(info.nd) { + + case 1: + std::memcpy(dst, src, info.buffer_size()); + break; + + case 2: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) { + size_t row_major, col_major; + bob::io::base::rc2d(row_major, col_major, i, j, info.shape); + row_major *= dsize; + col_major *= dsize; + std::memcpy(&dst[col_major], &src[row_major], dsize); + } + break; + + case 3: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) { + size_t row_major, col_major; + bob::io::base::rc3d(row_major, col_major, i, j, k, info.shape); + row_major *= dsize; + col_major *= dsize; + std::memcpy(&dst[col_major], &src[row_major], dsize); + } + break; + + case 4: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) + for (size_t l=0; l<info.shape[3]; ++l) { + size_t row_major, col_major; + bob::io::base::rc4d(row_major, col_major, i, j, k, l, info.shape); + row_major *= dsize; + col_major *= dsize; + std::memcpy(&dst[col_major], &src[row_major], dsize); + } + break; + + default: + { + boost::format m("row_to_col_order() can only flip arrays with up to %u dimensions - you passed one with %u dimensions"); + m % BOB_MAX_DIM % info.nd; + throw std::runtime_error(m.str()); + } + } +} + +void bob::io::base::col_to_row_order(const void* src_, void* dst_, + const bob::io::base::array::typeinfo& info) { + + size_t dsize = info.item_size(); + + //cast to byte type so we can manipulate the pointers... + const uint8_t* src = static_cast<const uint8_t*>(src_); + uint8_t* dst = static_cast<uint8_t*>(dst_); + + switch(info.nd) { + + case 1: + std::memcpy(dst, src, info.buffer_size()); + break; + + case 2: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) { + size_t row_major, col_major; + bob::io::base::rc2d(row_major, col_major, i, j, info.shape); + row_major *= dsize; + col_major *= dsize; + std::memcpy(&dst[row_major], &src[col_major], dsize); + } + break; + + case 3: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) { + size_t row_major, col_major; + bob::io::base::rc3d(row_major, col_major, i, j, k, info.shape); + row_major *= dsize; + col_major *= dsize; + std::memcpy(&dst[row_major], &src[col_major], dsize); + } + break; + + case 4: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) + for (size_t l=0; l<info.shape[3]; ++l) { + size_t row_major, col_major; + bob::io::base::rc4d(row_major, col_major, i, j, k, l, info.shape); + row_major *= dsize; + col_major *= dsize; + std::memcpy(&dst[row_major], &src[col_major], dsize); + } + break; + + default: + { + boost::format m("col_to_row_order() can only flip arrays with up to %u dimensions - you passed one with %u dimensions"); + m % BOB_MAX_DIM % info.nd; + throw std::runtime_error(m.str()); + } + } +} + +void bob::io::base::row_to_col_order_complex(const void* src_, void* dst_re_, + void* dst_im_, const bob::io::base::array::typeinfo& info) { + + size_t dsize = info.item_size(); + size_t dsize2 = dsize/2; ///< size of each complex component (real, imaginary) + + //cast to byte type so we can manipulate the pointers... + const uint8_t* src = static_cast<const uint8_t*>(src_); + uint8_t* dst_re = static_cast<uint8_t*>(dst_re_); + uint8_t* dst_im = static_cast<uint8_t*>(dst_im_); + + switch(info.nd) { + + case 1: + for (size_t i=0; i<info.shape[0]; ++i) { + std::memcpy(&dst_re[dsize2*i], &src[dsize*i] , dsize2); + std::memcpy(&dst_im[dsize2*i], &src[dsize*i]+dsize2, dsize2); + } + break; + + case 2: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) { + size_t row_major, col_major; + bob::io::base::rc2d(row_major, col_major, i, j, info.shape); + row_major *= dsize; + col_major *= dsize2; + std::memcpy(&dst_re[col_major], &src[row_major] , dsize2); + std::memcpy(&dst_im[col_major], &src[row_major]+dsize2, dsize2); + } + break; + + case 3: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) { + size_t row_major, col_major; + bob::io::base::rc3d(row_major, col_major, i, j, k, info.shape); + row_major *= dsize; + col_major *= dsize2; + std::memcpy(&dst_re[col_major], &src[row_major] , dsize2); + std::memcpy(&dst_im[col_major], &src[row_major]+dsize2, dsize2); + } + break; + + case 4: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) + for (size_t l=0; l<info.shape[3]; ++l) { + size_t row_major, col_major; + bob::io::base::rc4d(row_major, col_major, i, j, k, l, info.shape); + row_major *= dsize; + col_major *= dsize2; + std::memcpy(&dst_re[col_major], &src[row_major] , dsize2); + std::memcpy(&dst_im[col_major], &src[row_major]+dsize2, dsize2); + } + break; + + default: + { + boost::format m("row_to_col_order_complex() can only flip arrays with up to %u dimensions - you passed one with %u dimensions"); + m % BOB_MAX_DIM % info.nd; + throw std::runtime_error(m.str()); + } + } +} + +void bob::io::base::col_to_row_order_complex(const void* src_re_, const void* src_im_, + void* dst_, const bob::io::base::array::typeinfo& info) { + + size_t dsize = info.item_size(); + size_t dsize2 = dsize/2; ///< size of each complex component (real, imaginary) + + //cast to byte type so we can manipulate the pointers... + const uint8_t* src_re = static_cast<const uint8_t*>(src_re_); + const uint8_t* src_im = static_cast<const uint8_t*>(src_im_); + uint8_t* dst = static_cast<uint8_t*>(dst_); + + switch(info.nd) { + + case 1: + for (size_t i=0; i<info.shape[0]; ++i) { + std::memcpy(&dst[dsize*i] , &src_re[dsize2*i], dsize2); + std::memcpy(&dst[dsize*i]+dsize2, &src_im[dsize2*i], dsize2); + } + break; + + case 2: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) { + size_t row_major, col_major; + bob::io::base::rc2d(row_major, col_major, i, j, info.shape); + row_major *= dsize; + col_major *= dsize2; + std::memcpy(&dst[row_major], &src_re[col_major], dsize2); + std::memcpy(&dst[row_major]+dsize2, &src_im[col_major], dsize2); + } + break; + + case 3: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) { + size_t row_major, col_major; + bob::io::base::rc3d(row_major, col_major, i, j, k, info.shape); + row_major *= dsize; + col_major *= dsize2; + std::memcpy(&dst[row_major] , &src_re[col_major], dsize2); + std::memcpy(&dst[row_major]+dsize2, &src_im[col_major], dsize2); + } + break; + + case 4: + for (size_t i=0; i<info.shape[0]; ++i) + for (size_t j=0; j<info.shape[1]; ++j) + for (size_t k=0; k<info.shape[2]; ++k) + for (size_t l=0; l<info.shape[3]; ++l) { + size_t row_major, col_major; + bob::io::base::rc4d(row_major, col_major, i, j, k, l, info.shape); + row_major *= dsize; + col_major *= dsize2; + std::memcpy(&dst[row_major] , &src_re[col_major], dsize2); + std::memcpy(&dst[row_major]+dsize2, &src_im[col_major], dsize2); + } + break; + + default: + { + boost::format m("col_to_row_order_complex() can only flip arrays with up to %u dimensions - you passed one with %u dimensions"); + m % BOB_MAX_DIM % info.nd; + throw std::runtime_error(m.str()); + } + } +} + diff --git a/bob/io/base/utils.cpp b/bob/io/base/cpp/utils.cpp similarity index 52% rename from bob/io/base/utils.cpp rename to bob/io/base/cpp/utils.cpp index 53ebd5f..3467b99 100644 --- a/bob/io/base/utils.cpp +++ b/bob/io/base/cpp/utils.cpp @@ -7,31 +7,24 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> -#include <bob.io.base/File.h> -#include "cpp/CodecRegistry.h" +#include <bob.io.base/CodecRegistry.h> +#include <bob.io.base/utils.h> -boost::shared_ptr<bob::io::base::File> BobIoFile_Open - (const char* filename, char mode) { - - boost::shared_ptr<bob::io::base::CodecRegistry> instance = bob::io::base::CodecRegistry::instance(); - return instance->findByFilenameExtension(filename)(filename, mode); - -} - -boost::shared_ptr<bob::io::base::File> BobIoFile_OpenWithExtension (const char* filename, +boost::shared_ptr<bob::io::base::File> bob::io::base::open (const char* filename, char mode, const char* pretend_extension) { - boost::shared_ptr<bob::io::base::CodecRegistry> instance = bob::io::base::CodecRegistry::instance(); return instance->findByExtension(pretend_extension)(filename, mode); +} +boost::shared_ptr<bob::io::base::File> bob::io::base::open (const char* filename, char mode) { + boost::shared_ptr<bob::io::base::CodecRegistry> instance = bob::io::base::CodecRegistry::instance(); + return instance->findByFilenameExtension(filename)(filename, mode); } -void BobIoFile_Peek (const char* filename, BobIoTypeinfo* info) { - BobIoTypeinfo_Copy(info, &BobIoFile_Open(filename, 'r')->type()); +bob::io::base::array::typeinfo bob::io::base::peek (const char* filename) { + return open(filename, 'r')->type(); } -void BobIoFile_PeekAll (const char* filename, BobIoTypeinfo* info) { - BobIoTypeinfo_Copy(info, &BobIoFile_Open(filename, 'r')->type_all()); +bob::io::base::array::typeinfo bob::io::base::peek_all (const char* filename) { + return open(filename, 'r')->type_all(); } diff --git a/bob/io/base/file.cpp b/bob/io/base/file.cpp index 3f36c38..58d760c 100644 --- a/bob/io/base/file.cpp +++ b/bob/io/base/file.cpp @@ -8,12 +8,14 @@ #define BOB_IO_BASE_MODULE #include "bobskin.h" #include <bob.io.base/api.h> -#include <bob.io.base/File.h> #include <numpy/arrayobject.h> #include <bob.blitz/capi.h> #include <bob.blitz/cleanup.h> #include <stdexcept> +#include <bob.io.base/CodecRegistry.h> +#include <bob.io.base/utils.h> + #define FILETYPE_NAME "File" PyDoc_STRVAR(s_file_str, BOB_EXT_MODULE_PREFIX "." FILETYPE_NAME); @@ -119,10 +121,10 @@ static int PyBobIoFile_Init(PyBobIoFileObject* self, PyObject *args, PyObject* k try { if (pretend_extension) { - self->f = BobIoFile_OpenWithExtension(c_filename, mode, pretend_extension); + self->f = bob::io::base::open(c_filename, mode, pretend_extension); } else { - self->f = BobIoFile_Open(c_filename, mode); + self->f = bob::io::base::open(c_filename, mode); } } catch (std::exception& e) { @@ -191,6 +193,51 @@ static Py_ssize_t PyBobIoFile_Len (PyBobIoFileObject* self) { return retval; } +int PyBobIo_AsTypenum (bob::io::base::array::ElementType type) { + + switch(type) { + case bob::io::base::array::t_bool: + return NPY_BOOL; + case bob::io::base::array::t_int8: + return NPY_INT8; + case bob::io::base::array::t_int16: + return NPY_INT16; + case bob::io::base::array::t_int32: + return NPY_INT32; + case bob::io::base::array::t_int64: + return NPY_INT64; + case bob::io::base::array::t_uint8: + return NPY_UINT8; + case bob::io::base::array::t_uint16: + return NPY_UINT16; + case bob::io::base::array::t_uint32: + return NPY_UINT32; + case bob::io::base::array::t_uint64: + return NPY_UINT64; + case bob::io::base::array::t_float32: + return NPY_FLOAT32; + case bob::io::base::array::t_float64: + return NPY_FLOAT64; +#ifdef NPY_FLOAT128 + case bob::io::base::array::t_float128: + return NPY_FLOAT128; +#endif + case bob::io::base::array::t_complex64: + return NPY_COMPLEX64; + case bob::io::base::array::t_complex128: + return NPY_COMPLEX128; +#ifdef NPY_COMPLEX256 + case bob::io::base::array::t_complex256: + return NPY_COMPLEX256; +#endif + default: + PyErr_Format(PyExc_TypeError, "unsupported Bob/C++ element type (%s)", bob::io::base::array::stringize(type)); + } + + return NPY_NOTYPE; + +} + static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) { if (i < 0) i += self->f->size(); ///< adjust for negative indexing @@ -200,14 +247,15 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) { return 0; } - const BobIoTypeinfo& info = self->f->type(); + const bob::io::base::array::typeinfo& info = self->f->type(); npy_intp shape[NPY_MAXDIMS]; for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k]; - if (info.dtype == NPY_NOTYPE) return 0; ///< failure + int type_num = PyBobIo_AsTypenum(info.dtype); + if (type_num == NPY_NOTYPE) return 0; ///< failure - PyObject* retval = PyArray_SimpleNew(info.nd, shape, info.dtype); + PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num); if (!retval) return 0; auto retval_ = make_safe(retval); @@ -240,17 +288,18 @@ static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, PySliceObject* s self->f->size(), &start, &stop, &step, &slicelength) < 0) return 0; //creates the return array - const BobIoTypeinfo& info = self->f->type(); + const bob::io::base::array::typeinfo& info = self->f->type(); - if (info.dtype == NPY_NOTYPE) return 0; ///< failure + int type_num = PyBobIo_AsTypenum(info.dtype); + if (type_num == NPY_NOTYPE) return 0; ///< failure - if (slicelength <= 0) return PyArray_SimpleNew(0, 0, info.dtype); + if (slicelength <= 0) return PyArray_SimpleNew(0, 0, type_num); npy_intp shape[NPY_MAXDIMS]; shape[0] = slicelength; for (size_t k=0; k<info.nd; ++k) shape[k+1] = info.shape[k]; - PyObject* retval = PyArray_SimpleNew(info.nd+1, shape, info.dtype); + PyObject* retval = PyArray_SimpleNew(info.nd+1, shape, type_num); if (!retval) return 0; auto retval_ = make_safe(retval); @@ -334,14 +383,15 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj // reads the whole file in a single shot - const BobIoTypeinfo& info = self->f->type_all(); + const bob::io::base::array::typeinfo& info = self->f->type_all(); npy_intp shape[NPY_MAXDIMS]; for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k]; - if (info.dtype == NPY_NOTYPE) return 0; ///< failure + int type_num = PyBobIo_AsTypenum(info.dtype); + if (type_num == NPY_NOTYPE) return 0; ///< failure - PyObject* retval = PyArray_SimpleNew(info.nd, shape, info.dtype); + PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num); if (!retval) return 0; auto retval_ = make_safe(retval); @@ -494,12 +544,13 @@ Returns the current position of the newly written array.\n\ " ); -PyObject* PyBobIo_TypeinfoAsTuple (const BobIoTypeinfo& ti) { +PyObject* PyBobIo_TypeInfoAsTuple (const bob::io::base::array::typeinfo& ti) { - if (ti.dtype == NPY_NOTYPE) return 0; + int type_num = PyBobIo_AsTypenum(ti.dtype); + if (type_num == NPY_NOTYPE) return 0; PyObject* retval = Py_BuildValue("NNN", - reinterpret_cast<PyObject*>(PyArray_DescrFromType(ti.dtype)), + reinterpret_cast<PyObject*>(PyArray_DescrFromType(type_num)), PyTuple_New(ti.nd), //shape PyTuple_New(ti.nd) //strides ); @@ -525,12 +576,12 @@ static PyObject* PyBobIoFile_Describe(PyBobIoFileObject* self, PyObject *args, P PyObject* all = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &all)) return 0; - const BobIoTypeinfo* info = 0; + const bob::io::base::array::typeinfo* info = 0; if (all && PyObject_IsTrue(all)) info = &self->f->type_all(); else info = &self->f->type(); /* Now return type description and tuples with shape and strides */ - return PyBobIo_TypeinfoAsTuple(*info); + return PyBobIo_TypeInfoAsTuple(*info); } PyDoc_STRVAR(s_describe_str, "describe"); diff --git a/bob/io/base/hdf5.cpp b/bob/io/base/hdf5.cpp index 1b56fa6..dcb4249 100644 --- a/bob/io/base/hdf5.cpp +++ b/bob/io/base/hdf5.cpp @@ -7,7 +7,6 @@ #define BOB_IO_BASE_MODULE #include <bob.io.base/api.h> -#include <bob.io.base/HDF5File.h> #include <boost/make_shared.hpp> #include <numpy/arrayobject.h> diff --git a/bob/io/base/cpp/CodecRegistry.h b/bob/io/base/include/bob.io.base/CodecRegistry.h similarity index 86% rename from bob/io/base/cpp/CodecRegistry.h rename to bob/io/base/include/bob.io.base/CodecRegistry.h index aa9501e..019bb57 100644 --- a/bob/io/base/cpp/CodecRegistry.h +++ b/bob/io/base/include/bob.io.base/CodecRegistry.h @@ -14,7 +14,7 @@ #include <string> #include <boost/shared_ptr.hpp> -#include <bob.io.base/api.h> +#include <bob.io.base/File.h> namespace bob { namespace io { namespace base { @@ -47,9 +47,9 @@ namespace bob { namespace io { namespace base { public: //object access void registerExtension(const char* extension, const char* description, - BobIoFileFactory factory); + file_factory_t factory); - void deregisterFactory(BobIoFileFactory factory); + void deregisterFactory(file_factory_t factory); void deregisterExtension(const char* ext); /** @@ -58,8 +58,8 @@ namespace bob { namespace io { namespace base { */ const char* getDescription(const char* ext); - BobIoFileFactory findByExtension(const char* ext); - BobIoFileFactory findByFilenameExtension(const char* fn); + file_factory_t findByExtension(const char* ext); + file_factory_t findByFilenameExtension(const char* fn); bool isRegistered(const char* ext); @@ -70,7 +70,7 @@ namespace bob { namespace io { namespace base { // Not implemented CodecRegistry( const CodecRegistry&); - std::map<std::string, BobIoFileFactory> s_extension2codec; + std::map<std::string, file_factory_t> s_extension2codec; std::map<std::string, std::string> s_extension2description; bool s_ignore; ///< shall I ignore double-registrations? diff --git a/bob/io/base/include/bob.io.base/File.h b/bob/io/base/include/bob.io.base/File.h index 1b71c93..e41bccd 100644 --- a/bob/io/base/include/bob.io.base/File.h +++ b/bob/io/base/include/bob.io.base/File.h @@ -11,8 +11,9 @@ #ifndef BOB_IO_BASE_FILE_H #define BOB_IO_BASE_FILE_H -#include <bob.io.base/blitz_array.h> #include <boost/shared_ptr.hpp> +#include <bob.io.base/array.h> +#include <bob.io.base/blitz_array.h> namespace bob { namespace io { namespace base { @@ -24,7 +25,7 @@ namespace bob { namespace io { namespace base { public: //abstract API - virtual ~File() {}; + virtual ~File(); /** * The filename this array codec current points to @@ -32,16 +33,16 @@ namespace bob { namespace io { namespace base { virtual const char* filename() const =0; /** - * The type information of data within this file, if it is supposed to be - * read as as a sequence of arrays + * The typeinfo of data within this file, if it is supposed to be read as + * as a sequence of arrays */ - virtual const BobIoTypeinfo& type() const =0; + virtual const bob::io::base::array::typeinfo& type() const =0; /** - * The type information of data within this file, if it is supposed to be - * read as a single array. + * The typeinfo of data within this file, if it is supposed to be read as + * a single array. */ - virtual const BobIoTypeinfo& type_all() const =0; + virtual const bob::io::base::array::typeinfo& type_all() const =0; /** * The number of arrays available in this file, if it is supposed to be @@ -156,6 +157,28 @@ namespace bob { namespace io { namespace base { }; + /** + * @brief This defines the factory method F that can create codecs. Your + * task, as a codec developer is to create one of such methods for each of + * your codecs and statically register them to the codec registry. + * + * Here are the meanings of the mode flag that should be respected by your + * factory implementation: + * + * 'r': opens for reading only - no modifications can occur; it is an + * error to open a file that does not exist for read-only operations. + * 'w': opens for reading and writing, but truncates the file if it + * exists; it is not an error to open files that do not exist with + * this flag. + * 'a': opens for reading and writing - any type of modification can + * occur. If the file does not exist, this flag is effectively like + * 'w'. + * + * Returns a newly allocated File object that can read and write data to the + * file using a specific backend. + */ + typedef boost::shared_ptr<File> (*file_factory_t) (const char* filename, char mode); + }}} #endif /* BOB_IO_BASE_FILE_H */ diff --git a/bob/io/base/include/bob.io.base/HDF5Dataset.h b/bob/io/base/include/bob.io.base/HDF5Dataset.h index 9059bab..5572410 100644 --- a/bob/io/base/include/bob.io.base/HDF5Dataset.h +++ b/bob/io/base/include/bob.io.base/HDF5Dataset.h @@ -13,7 +13,6 @@ #include <vector> #include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> #include <blitz/array.h> #include <hdf5.h> diff --git a/bob/io/base/include/bob.io.base/HDF5File.h b/bob/io/base/include/bob.io.base/HDF5File.h index 4c80604..31c6594 100644 --- a/bob/io/base/include/bob.io.base/HDF5File.h +++ b/bob/io/base/include/bob.io.base/HDF5File.h @@ -12,9 +12,10 @@ #ifndef BOB_IO_BASE_HDF5FILE_H #define BOB_IO_BASE_HDF5FILE_H -#include <bob.io.base/HDF5Utils.h> #include <boost/format.hpp> +#include <bob.io.base/HDF5Utils.h> + namespace bob { namespace io { namespace base { /** diff --git a/bob/io/base/include/bob.io.base/HDF5Group.h b/bob/io/base/include/bob.io.base/HDF5Group.h index 9071403..9dcd7a6 100644 --- a/bob/io/base/include/bob.io.base/HDF5Group.h +++ b/bob/io/base/include/bob.io.base/HDF5Group.h @@ -10,14 +10,14 @@ #ifndef BOB_IO_BASE_HDF5GROUP_H #define BOB_IO_BASE_HDF5GROUP_H -#include <bob.io.base/HDF5Types.h> -#include <bob.io.base/HDF5Dataset.h> -#include <bob.io.base/HDF5Attribute.h> - #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <hdf5.h> +#include <bob.io.base/HDF5Types.h> +#include <bob.io.base/HDF5Dataset.h> +#include <bob.io.base/HDF5Attribute.h> + namespace bob { namespace io { namespace base { namespace detail { namespace hdf5 { class File; diff --git a/bob/io/base/include/bob.io.base/HDF5Types.h b/bob/io/base/include/bob.io.base/HDF5Types.h index 01c5cc5..d19eab3 100644 --- a/bob/io/base/include/bob.io.base/HDF5Types.h +++ b/bob/io/base/include/bob.io.base/HDF5Types.h @@ -10,6 +10,12 @@ #ifndef BOB_IO_BASE_HDF5TYPES_H #define BOB_IO_BASE_HDF5TYPES_H +#include <vector> +#include <string> +#include <boost/shared_ptr.hpp> +#include <blitz/array.h> +#include <hdf5.h> + /** * Checks if the version of HDF5 installed is greater or equal to some set of * values. (extracted from hdf5-1.8.7) @@ -23,12 +29,6 @@ #include <bob.io.base/array.h> -#include <vector> -#include <string> -#include <boost/shared_ptr.hpp> -#include <blitz/array.h> -#include <hdf5.h> - namespace bob { namespace io { namespace base { /** @@ -340,14 +340,14 @@ namespace bob { namespace io { namespace base { HDF5Type(hdf5type type); /** - * Creates a HDF5Type from an BobIoTypeinfo + * Creates a HDF5Type from an bob::io::base::array::typeinfo */ - HDF5Type(const BobIoTypeinfo& ti); + HDF5Type(const bob::io::base::array::typeinfo& ti); /** * Creates a HDF5Type from a type enumeration and an explicit shape */ - HDF5Type(int dtype, const HDF5Shape& extents); + HDF5Type(bob::io::base::array::ElementType eltype, const HDF5Shape& extents); /** * Creates a HDF5Type from a type enumeration and an explicit shape @@ -400,7 +400,7 @@ namespace bob { namespace io { namespace base { /** * Checks if an existing object is compatible with my type */ - bool compatible (const BobIoTypeinfo& value) const; + bool compatible (const bob::io::base::array::typeinfo& value) const; /** * Returns the HDF5Shape of this type @@ -436,12 +436,12 @@ namespace bob { namespace io { namespace base { * Returns a mapping between the current type and the supported element * types in bob::io::base::array */ - int element_type() const; + bob::io::base::array::ElementType element_type() const; /** - * Copies this type information to a stock BobIoTypeinfo + * Copies this type information to a stock bob::io::base::array::typeinfo */ - void copy_to (BobIoTypeinfo& ti) const; + void copy_to (bob::io::base::array::typeinfo& ti) const; private: //representation diff --git a/bob/io/base/include/bob.io.base/HDF5Utils.h b/bob/io/base/include/bob.io.base/HDF5Utils.h index d380dfd..670430e 100644 --- a/bob/io/base/include/bob.io.base/HDF5Utils.h +++ b/bob/io/base/include/bob.io.base/HDF5Utils.h @@ -27,13 +27,13 @@ #ifndef BOB_IO_BASE_HDF5UTILS_H #define BOB_IO_BASE_HDF5UTILS_H -#include <bob.io.base/HDF5Group.h> - #include <boost/filesystem.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #include <hdf5.h> +#include <bob.io.base/HDF5Group.h> + namespace bob { namespace io { namespace base { namespace detail { namespace hdf5 { /** diff --git a/bob/io/base/include/bob.io.base/api.h b/bob/io/base/include/bob.io.base/api.h index 59b1dbb..001e8d4 100644 --- a/bob/io/base/include/bob.io.base/api.h +++ b/bob/io/base/include/bob.io.base/api.h @@ -13,11 +13,13 @@ #define BOB_IO_BASE_PREFIX "bob.io.base" #define BOB_IO_BASE_FULL_NAME "bob.io.base._library" -/* Maximum number of dimensions supported at this library */ -#define BOB_BLITZ_MAXDIMS 4 - #include <Python.h> + #include <bob.io.base/config.h> +#include <bob.io.base/File.h> +#include <bob.io.base/CodecRegistry.h> +#include <bob.io.base/HDF5File.h> + #include <boost/shared_ptr.hpp> /******************* @@ -27,37 +29,12 @@ /* Enum defining entries in the function table */ enum _PyBobIo_ENUM{ PyBobIo_APIVersion_NUM = 0, - // C/C++ Type Information - BobIoTypeinfo_Init_NUM, - BobIoTypeinfo_Copy_NUM, - BobIoTypeinfo_Set_NUM, - BobIoTypeinfo_SetWithStrides_NUM, - BobIoTypeinfo_SignedSet_NUM, - BobIoTypeinfo_SignedSetWithStrides_NUM, - BobIoTypeinfo_Reset_NUM, - BobIoTypeinfo_IsValid_NUM, - BobIoTypeinfo_HasValidShape_NUM, - BobIoTypeinfo_ResetShape_NUM, - BobIoTypeinfo_UpdateStrides_NUM, - BobIoTypeinfo_Size_NUM, - BobIoTypeinfo_BufferSize_NUM, - BobIoTypeinfo_IsCompatible_NUM, - BobIoTypeinfo_Str_NUM, - // Data reordering - BobIoReorder_RowToCol_NUM, - BobIoReorder_ColToRow_NUM, - BobIoReorder_RowToColComplex_NUM, - BobIoReorder_ColToRowComplex_NUM, // Bindings for bob.io.base.File PyBobIoFile_Type_NUM, PyBobIoFileIterator_Type_NUM, - // File loading and data type peeking - BobIoFile_Open_NUM, - BobIoFile_OpenWithExtension_NUM, - BobIoFile_Peek_NUM, - BobIoFile_PeekAll_NUM, // I/O generic bindings - PyBobIo_TypeinfoAsTuple_NUM, + PyBobIo_AsTypenum_NUM, + PyBobIo_TypeInfoAsTuple_NUM, PyBobIo_FilenameConverter_NUM, // HDF5 bindings PyBobIoHDF5File_Type_NUM, @@ -78,88 +55,11 @@ enum _PyBobIo_ENUM{ #define PyBobIo_APIVersion_TYPE int -/******************** - * Type Information * - ********************/ - -typedef struct { - - int dtype; ///< data type - size_t nd; ///< number of dimensions - size_t shape[BOB_BLITZ_MAXDIMS+1]; ///< length along each dimension - size_t stride[BOB_BLITZ_MAXDIMS+1]; ///< strides along each dimension - -} BobIoTypeinfo; - - -#define BobIoTypeinfo_Init_RET void -#define BobIoTypeinfo_Init_PROTO (BobIoTypeinfo*) - -#define BobIoTypeinfo_Copy_RET int -#define BobIoTypeinfo_Copy_PROTO (BobIoTypeinfo*, const BobIoTypeinfo*) - -#define BobIoTypeinfo_Set_RET int -#define BobIoTypeinfo_Set_PROTO (BobIoTypeinfo*, int, size_t, const size_t*) - -#define BobIoTypeinfo_SetWithStrides_RET int -#define BobIoTypeinfo_SetWithStrides_PROTO (BobIoTypeinfo*, int, size_t, const size_t*, const size_t*) - -#define BobIoTypeinfo_SignedSet_RET int -#define BobIoTypeinfo_SignedSet_PROTO (BobIoTypeinfo*, int, Py_ssize_t, const Py_ssize_t*) - -#define BobIoTypeinfo_SignedSetWithStrides_RET int -#define BobIoTypeinfo_SignedSetWithStrides_PROTO (BobIoTypeinfo*, int, Py_ssize_t, const Py_ssize_t*, const Py_ssize_t*) - -#define BobIoTypeinfo_Reset_RET void -#define BobIoTypeinfo_Reset_PROTO (BobIoTypeinfo*) - -#define BobIoTypeinfo_IsValid_RET bool -#define BobIoTypeinfo_IsValid_PROTO (const BobIoTypeinfo*) - -#define BobIoTypeinfo_HasValidShape_RET bool -#define BobIoTypeinfo_HasValidShape_PROTO (const BobIoTypeinfo*) - -#define BobIoTypeinfo_ResetShape_RET void -#define BobIoTypeinfo_ResetShape_PROTO (BobIoTypeinfo*) - -#define BobIoTypeinfo_UpdateStrides_RET int -#define BobIoTypeinfo_UpdateStrides_PROTO (BobIoTypeinfo*) - -#define BobIoTypeinfo_Size_RET size_t -#define BobIoTypeinfo_Size_PROTO (const BobIoTypeinfo*) - -#define BobIoTypeinfo_BufferSize_RET size_t -#define BobIoTypeinfo_BufferSize_PROTO (const BobIoTypeinfo*) - -#define BobIoTypeinfo_IsCompatible_RET bool -#define BobIoTypeinfo_IsCompatible_PROTO (const BobIoTypeinfo*, const BobIoTypeinfo*) - -#define BobIoTypeinfo_Str_RET std::string -#define BobIoTypeinfo_Str_PROTO (const BobIoTypeinfo*) - -/******************** - * Array reordering * - ********************/ - -#define BobIoReorder_RowToCol_RET int -#define BobIoReorder_RowToCol_PROTO (const void*, void*, const BobIoTypeinfo*) - -#define BobIoReorder_ColToRow_RET int -#define BobIoReorder_ColToRow_PROTO (const void*, void*, const BobIoTypeinfo*) - -#define BobIoReorder_RowToColComplex_RET int -#define BobIoReorder_RowToColComplex_PROTO (const void*, void*, void*, const BobIoTypeinfo*) - -#define BobIoReorder_ColToRowComplex_RET int -#define BobIoReorder_ColToRowComplex_PROTO (const void*, const void*, void*, const BobIoTypeinfo*) - /********************************** * Bindings for bob.io.base.File * **********************************/ /* Type definition for PyBobIoFileObject */ - -namespace bob { namespace io { namespace base { class File; }}} typedef struct { PyObject_HEAD @@ -181,28 +81,15 @@ typedef struct { #define PyBobIoFileIterator_Type_TYPE PyTypeObject -/************************************** - * File loading and data type peeking * - **************************************/ - -#define BobIoFile_Open_RET boost::shared_ptr<bob::io::base::File> -#define BobIoFile_Open_PROTO (const char*, char) - -#define BobIoFile_OpenWithExtension_RET boost::shared_ptr<bob::io::base::File> -#define BobIoFile_OpenWithExtension_PROTO (const char*, char, const char*) - -#define BobIoFile_Peek_RET void -#define BobIoFile_Peek_PROTO (const char*, BobIoTypeinfo*) - -#define BobIoFile_PeekAll_RET void -#define BobIoFile_PeekAll_PROTO (const char*, BobIoTypeinfo*) - /************************ * I/O generic bindings * ************************/ -#define PyBobIo_TypeinfoAsTuple_RET PyObject* -#define PyBobIo_TypeinfoAsTuple_PROTO (const BobIoTypeinfo& ti) +#define PyBobIo_AsTypenum_RET int +#define PyBobIo_AsTypenum_PROTO (bob::io::base::array::ElementType et) + +#define PyBobIo_TypeInfoAsTuple_RET PyObject* +#define PyBobIo_TypeInfoAsTuple_PROTO (const bob::io::base::array::typeinfo& ti) #define PyBobIo_FilenameConverter_RET int #define PyBobIo_FilenameConverter_PROTO (PyObject* o, PyObject** b) @@ -211,7 +98,6 @@ typedef struct { * HDF5 bindings * *****************/ -namespace bob { namespace io { namespace base { class HDF5File; }}} typedef struct { PyObject_HEAD @@ -232,30 +118,8 @@ typedef struct { * Code Registration and De-registration * *****************************************/ -/** - * @brief This defines the factory method F that can create codecs. Your - * task, as a codec developer is to create one of such methods for each of - * your codecs and statically register them to the codec registry. - * - * Here are the meanings of the mode flag that should be respected by your - * factory implementation: - * - * 'r': opens for reading only - no modifications can occur; it is an - * error to open a file that does not exist for read-only operations. - * 'w': opens for reading and writing, but truncates the file if it - * exists; it is not an error to open files that do not exist with - * this flag. - * 'a': opens for reading and writing - any type of modification can - * occur. If the file does not exist, this flag is effectively like - * 'w'. - * - * Returns a newly allocated File object that can read and write data to the - * file using a specific backend. - */ -typedef boost::shared_ptr<bob::io::base::File> (*BobIoFileFactory) (const char* filename, char mode); - #define PyBobIoCodec_Register_RET int -#define PyBobIoCodec_Register_PROTO (const char* extension, const char* description, BobIoFileFactory factory) +#define PyBobIoCodec_Register_PROTO (const char* extension, const char* description, bob::io::base::file_factory_t factory) #define PyBobIoCodec_Deregister_RET int #define PyBobIoCodec_Deregister_PROTO (const char* extension) @@ -276,52 +140,6 @@ typedef boost::shared_ptr<bob::io::base::File> (*BobIoFileFactory) (const char* extern int PyBobIo_APIVersion; - /******************** - * Type Information * - ********************/ - - BobIoTypeinfo_Init_RET BobIoTypeinfo_Init BobIoTypeinfo_Init_PROTO; - - BobIoTypeinfo_Copy_RET BobIoTypeinfo_Copy BobIoTypeinfo_Copy_PROTO; - - BobIoTypeinfo_Set_RET BobIoTypeinfo_Set BobIoTypeinfo_Set_PROTO; - - BobIoTypeinfo_SetWithStrides_RET BobIoTypeinfo_SetWithStrides BobIoTypeinfo_SetWithStrides_PROTO; - - BobIoTypeinfo_SignedSet_RET BobIoTypeinfo_SignedSet BobIoTypeinfo_SignedSet_PROTO; - - BobIoTypeinfo_SignedSetWithStrides_RET BobIoTypeinfo_SignedSetWithStrides BobIoTypeinfo_SignedSetWithStrides_PROTO; - - BobIoTypeinfo_Reset_RET BobIoTypeinfo_Reset BobIoTypeinfo_Reset_PROTO; - - BobIoTypeinfo_IsValid_RET BobIoTypeinfo_IsValid BobIoTypeinfo_IsValid_PROTO; - - BobIoTypeinfo_HasValidShape_RET BobIoTypeinfo_HasValidShape BobIoTypeinfo_HasValidShape_PROTO; - - BobIoTypeinfo_ResetShape_RET BobIoTypeinfo_ResetShape BobIoTypeinfo_ResetShape_PROTO; - - BobIoTypeinfo_UpdateStrides_RET BobIoTypeinfo_UpdateStrides BobIoTypeinfo_UpdateStrides_PROTO; - - BobIoTypeinfo_Size_RET BobIoTypeinfo_Size BobIoTypeinfo_Size_PROTO; - - BobIoTypeinfo_BufferSize_RET BobIoTypeinfo_BufferSize BobIoTypeinfo_BufferSize_PROTO; - - BobIoTypeinfo_IsCompatible_RET BobIoTypeinfo_IsCompatible BobIoTypeinfo_IsCompatible_PROTO; - - BobIoTypeinfo_Str_RET BobIoTypeinfo_Str BobIoTypeinfo_Str_PROTO; - - /******************** - * Array reordering * - ********************/ - - BobIoReorder_RowToCol_RET BobIoReorder_RowToCol BobIoReorder_RowToCol_PROTO; - - BobIoReorder_ColToRow_RET BobIoReorder_ColToRow BobIoReorder_ColToRow_PROTO; - - BobIoReorder_RowToColComplex_RET BobIoReorder_RowToColComplex BobIoReorder_RowToColComplex_PROTO; - - BobIoReorder_ColToRowComplex_RET BobIoReorder_ColToRowComplex BobIoReorder_ColToRowComplex_PROTO; - /********************************** * Bindings for bob.io.base.File * **********************************/ @@ -329,29 +147,19 @@ typedef boost::shared_ptr<bob::io::base::File> (*BobIoFileFactory) (const char* extern PyBobIoFile_Type_TYPE PyBobIoFile_Type; extern PyBobIoFileIterator_Type_TYPE PyBobIoFileIterator_Type; - /************************************** - * File loading and data type peeking * - **************************************/ - - BobIoFile_Open_RET BobIoFile_Open BobIoFile_Open_PROTO; - - BobIoFile_OpenWithExtension_RET BobIoFile_OpenWithExtension BobIoFile_OpenWithExtension_PROTO; - - BobIoFile_Peek_RET BobIoFile_Peek BobIoFile_Peek_PROTO; - - BobIoFile_PeekAll_RET BobIoFile_PeekAll BobIoFile_PeekAll_PROTO; - /************************ * I/O generic bindings * ************************/ - PyBobIo_TypeinfoAsTuple_RET PyBobIo_TypeinfoAsTuple PyBobIo_TypeinfoAsTuple_PROTO; + PyBobIo_AsTypenum_RET PyBobIo_AsTypenum PyBobIo_AsTypenum_PROTO; + + PyBobIo_TypeInfoAsTuple_RET PyBobIo_TypeInfoAsTuple PyBobIo_TypeInfoAsTuple_PROTO; PyBobIo_FilenameConverter_RET PyBobIo_FilenameConverter PyBobIo_FilenameConverter_PROTO; - /***************** - * HDF5 bindings * - *****************/ +/***************** + * HDF5 bindings * + *****************/ extern PyBobIoHDF5File_Type_TYPE PyBobIoHDF5File_Type; @@ -359,17 +167,17 @@ typedef boost::shared_ptr<bob::io::base::File> (*BobIoFileFactory) (const char* PyBobIoHDF5File_Converter_RET PyBobIoHDF5File_Converter PyBobIoHDF5File_Converter_PROTO; - /***************************************** - * Code Registration and De-registration * - *****************************************/ +/***************************************** + * Code Registration and De-registration * + *****************************************/ - PyBobIoCodec_Register_RET PyBobIoCodec_Register PyBobIoCodec_Register_PROTO; + PyBobIoCodec_Register_RET PyBobIoCodec_Register PyBobIoCodec_Register_PROTO; - PyBobIoCodec_Deregister_RET PyBobIoCodec_Deregister PyBobIoCodec_Deregister_PROTO; + PyBobIoCodec_Deregister_RET PyBobIoCodec_Deregister PyBobIoCodec_Deregister_PROTO; - PyBobIoCodec_IsRegistered_RET PyBobIoCodec_IsRegistered PyBobIoCodec_IsRegistered_PROTO; + PyBobIoCodec_IsRegistered_RET PyBobIoCodec_IsRegistered PyBobIoCodec_IsRegistered_PROTO; - PyBobIoCodec_GetDescription_RET PyBobIoCodec_GetDescription PyBobIoCodec_GetDescription_PROTO; + PyBobIoCodec_GetDescription_RET PyBobIoCodec_GetDescription PyBobIoCodec_GetDescription_PROTO; #else @@ -391,52 +199,6 @@ typedef boost::shared_ptr<bob::io::base::File> (*BobIoFileFactory) (const char* # define PyBobIo_APIVersion (*(PyBobIo_APIVersion_TYPE *)PyBobIo_API[PyBobIo_APIVersion_NUM]) - /******************** - * Type Information * - ********************/ - -# define BobIoTypeinfo_Init (*(BobIoTypeinfo_Init_RET (*)BobIoTypeinfo_Init_PROTO) PyBobIo_API[BobIoTypeinfo_Init_NUM]) - -# define BobIoTypeinfo_Copy (*(BobIoTypeinfo_Copy_RET (*)BobIoTypeinfo_Copy_PROTO) PyBobIo_API[BobIoTypeinfo_Copy_NUM]) - -# define BobIoTypeinfo_Set (*(BobIoTypeinfo_Set_RET (*)BobIoTypeinfo_Set_PROTO) PyBobIo_API[BobIoTypeinfo_Set_NUM]) - -# define BobIoTypeinfo_SetWithStrides (*(BobIoTypeinfo_SetWithStrides_RET (*)BobIoTypeinfo_SetWithStrides_PROTO) PyBobIo_API[BobIoTypeinfo_SetWithStrides_NUM]) - -# define BobIoTypeinfo_SignedSet (*(BobIoTypeinfo_SignedSet_RET (*)BobIoTypeinfo_SignedSet_PROTO) PyBobIo_API[BobIoTypeinfo_SignedSet_NUM]) - -# define BobIoTypeinfo_SignedSetWithStrides (*(BobIoTypeinfo_SignedSetWithStrides_RET (*)BobIoTypeinfo_SignedSetWithStrides_PROTO) PyBobIo_API[BobIoTypeinfo_SignedSetWithStrides_NUM]) - -# define BobIoTypeinfo_Reset (*(BobIoTypeinfo_Reset_RET (*)BobIoTypeinfo_Reset_PROTO) PyBobIo_API[BobIoTypeinfo_Reset_NUM]) - -# define BobIoTypeinfo_IsValid (*(BobIoTypeinfo_IsValid_RET (*)BobIoTypeinfo_IsValid_PROTO) PyBobIo_API[BobIoTypeinfo_IsValid_NUM]) - -# define BobIoTypeinfo_HasValidShape (*(BobIoTypeinfo_HasValidShape_RET (*)BobIoTypeinfo_HasValidShape_PROTO) PyBobIo_API[BobIoTypeinfo_HasValidShape_NUM]) - -# define BobIoTypeinfo_ResetShape (*(BobIoTypeinfo_ResetShape_RET (*)BobIoTypeinfo_ResetShape_PROTO) PyBobIo_API[BobIoTypeinfo_ResetShape_NUM]) - -# define BobIoTypeinfo_UpdateStrides (*(BobIoTypeinfo_UpdateStrides_RET (*)BobIoTypeinfo_UpdateStrides_PROTO) PyBobIo_API[BobIoTypeinfo_UpdateStrides_NUM]) - -# define BobIoTypeinfo_Size (*(BobIoTypeinfo_Size_RET (*)BobIoTypeinfo_Size_PROTO) PyBobIo_API[BobIoTypeinfo_Size_NUM]) - -# define BobIoTypeinfo_BufferSize (*(BobIoTypeinfo_BufferSize_RET (*)BobIoTypeinfo_BufferSize_PROTO) PyBobIo_API[BobIoTypeinfo_BufferSize_NUM]) - -# define BobIoTypeinfo_IsCompatible (*(BobIoTypeinfo_IsCompatible_RET (*)BobIoTypeinfo_IsCompatible_PROTO) PyBobIo_API[BobIoTypeinfo_IsCompatible_NUM]) - -# define BobIoTypeinfo_Str (*(BobIoTypeinfo_Str_RET (*)BobIoTypeinfo_Str_PROTO) PyBobIo_API[BobIoTypeinfo_Str_NUM]) - - /******************** - * Array reordering * - ********************/ - -# define BobIoReorder_RowToCol (*(BobIoReorder_RowToCol_RET (*)BobIoReorder_RowToCol_PROTO) PyBobIo_API[BobIoReorder_RowToCol_NUM]) - -# define BobIoReorder_ColToRow (*(BobIoReorder_ColToRow_RET (*)BobIoReorder_ColToRow_PROTO) PyBobIo_API[BobIoReorder_ColToRow_NUM]) - -# define BobIoReorder_RowToColComplex (*(BobIoReorder_RowToColComplex_RET (*)BobIoReorder_RowToColComplex_PROTO) PyBobIo_API[BobIoReorder_RowToColComplex_NUM]) - -# define BobIoReorder_ColToRowComplex (*(BobIoReorder_ColToRowComplex_RET (*)BobIoReorder_ColToRowComplex_PROTO) PyBobIo_API[BobIoReorder_ColToRowComplex_NUM]) - /***************************** * Bindings for bob.io.File * *****************************/ @@ -444,23 +206,13 @@ typedef boost::shared_ptr<bob::io::base::File> (*BobIoFileFactory) (const char* # define PyBobIoFile_Type (*(PyBobIoFile_Type_TYPE *)PyBobIo_API[PyBobIoFile_Type_NUM]) # define PyBobIoFileIterator_Type (*(PyBobIoFileIterator_Type_TYPE *)PyBobIo_API[PyBobIoFileIterator_Type_NUM]) - /************************************** - * File loading and data type peeking * - **************************************/ - -# define BobIoFile_Open (*(BobIoFile_Open_RET (*)BobIoFile_Open_PROTO) PyBobIo_API[BobIoFile_Open_NUM]) - -# define BobIoFile_OpenWithExtension (*(BobIoFile_OpenWithExtension_RET (*)BobIoFile_OpenWithExtension_PROTO) PyBobIo_API[BobIoFile_OpenWithExtension_NUM]) - -# define BobIoFile_Peek (*(BobIoFile_Peek_RET (*)BobIoFile_Peek_PROTO) PyBobIo_API[BobIoFile_Peek_NUM]) - -# define BobIoFile_PeekAll (*(BobIoFile_PeekAll_RET (*)BobIoFile_PeekAll_PROTO) PyBobIo_API[BobIoFile_PeekAll_NUM]) - /************************ * I/O generic bindings * ************************/ -# define PyBobIo_TypeinfoAsTuple (*(PyBobIo_TypeinfoAsTuple_RET (*)PyBobIo_TypeinfoAsTuple_PROTO) PyBobIo_API[PyBobIo_TypeinfoAsTuple_NUM]) +# define PyBobIo_AsTypenum (*(PyBobIo_AsTypenum_RET (*)PyBobIo_AsTypenum_PROTO) PyBobIo_API[PyBobIo_AsTypenum_NUM]) + +# define PyBobIo_TypeInfoAsTuple (*(PyBobIo_TypeInfoAsTuple_RET (*)PyBobIo_TypeInfoAsTuple_PROTO) PyBobIo_API[PyBobIo_TypeInfoAsTuple_NUM]) # define PyBobIo_FilenameConverter (*(PyBobIo_FilenameConverter_RET (*)PyBobIo_FilenameConverter_PROTO) PyBobIo_API[PyBobIo_FilenameConverter_NUM]) diff --git a/bob/io/base/include/bob.io.base/array.h b/bob/io/base/include/bob.io.base/array.h index 5bbe268..570c09f 100644 --- a/bob/io/base/include/bob.io.base/array.h +++ b/bob/io/base/include/bob.io.base/array.h @@ -11,15 +11,14 @@ #ifndef BOB_IO_BASE_ARRAY_INTERFACE_H #define BOB_IO_BASE_ARRAY_INTERFACE_H -#include <bob.blitz/cppapi.h> -#include <bob.io.base/api.h> - #include <stdexcept> #include <string> #include <boost/shared_ptr.hpp> #include <blitz/array.h> +#include <bob.io.base/array_type.h> + /* MinGW flags */ #ifdef _WIN32 #undef interface @@ -30,6 +29,170 @@ */ namespace bob { namespace io { namespace base { namespace array { + /** + * @brief Encapsulation of special type information of interfaces. + */ + struct typeinfo { + + ElementType dtype; ///< data type + size_t nd; ///< number of dimensions + size_t shape[BOB_MAX_DIM+1]; ///< length along each dimension + size_t stride[BOB_MAX_DIM+1]; ///< strides along each dimension + + /** + * @brief Default constructor + */ + typeinfo(); + + /** + * @brief Simplification to build a typeinfo from a size + */ + template <typename T> typeinfo(ElementType dtype_, T nd_) { + set(dtype_, nd_); + } + + /** + * @brief Simplification to build a typeinfo from a shape pointer. + */ + template <typename T> typeinfo(ElementType dtype_, T nd_, const T* shape_) { + set(dtype_, nd_, shape_); + } + + /** + * @brief Copies information from another typeinfo + */ + typeinfo(const typeinfo& other); + + /** + * @brief Assignment + */ + typeinfo& operator= (const typeinfo& other); + + /** + * @brief Builds with type and number of dimensions, but set the shape and + * strides to all zeros. + */ + template <typename T> + void set(ElementType dtype_, T nd_) { + dtype = dtype_; + nd = nd_; + reset_shape(); + } + + /** + * @brief Set to specific values + */ + template <typename T> + void set(ElementType dtype_, T nd_, const T* shape_) { + dtype = dtype_; + set_shape(nd_, shape_); + } + + /** + * @brief Set to specific values, including strides + */ + template <typename T> + void set(ElementType dtype_, T nd_, const T* shape_, + const T* stride_) { + dtype = dtype_; + nd = nd_; + for (size_t k=0; k<nd; ++k) { + shape[k] = shape_[k]; + stride[k] = stride_[k]; + } + } + + /** + * @brief Reset to defaults -- as if uninitialized. + */ + void reset(); + + /** + * @brief Is this a valid type information? + */ + bool is_valid() const; + + /** + * @brief Does this has a valid shape information? + */ + bool has_valid_shape() const; + + /** + * @brief sets the shape + */ + template <typename T> void set_shape(T nd_, const T* shape_) { + if (nd_ > (BOB_MAX_DIM+1)) + throw std::runtime_error("unsupported number of dimensions"); + nd = nd_; + for (size_t k=0; k<nd; ++k) shape[k] = shape_[k]; + update_strides(); + } + + /** + * @brief resets the shape to all zeros + */ + void reset_shape(); + + /** + * @brief Update my own stride vector. Called automatically after any use + * of set_shape(). + */ + void update_strides(); + + /** + * @brief Returns the total number of elements available + */ + size_t size() const; + + /** + * @brief Returns the size of each element + */ + inline size_t item_size() const { return getElementSize(dtype); } + + /** + * @brief Returns the total size (in bytes) of the buffer that I'm + * associated with. + */ + size_t buffer_size() const; + + /** + * @brief Returns the item type description + */ + const char* item_str() const { return stringize(dtype); } + + /** + * @brief Checks compatibility with other typeinfo + */ + bool is_compatible(const typeinfo& other) const; + + /** + * @brief Formats and returns a string containing the full typeinfo + * description. + */ + std::string str() const; + + /** + * @brief Make it easy to set for blitz::Array<T,N> + */ + template <typename T, int N> void set(const blitz::Array<T,N>& array) { + dtype = getElementType<T>(); + set_shape(array.shape()); + } + + template <typename T, int N> + void set(boost::shared_ptr<blitz::Array<T,N> >& array) { + dtype = getElementType<T>(); + set_shape(array->shape()); + } + + template <int N> void set_shape(const blitz::TinyVector<int,N>& tv_shape) { + nd = N; + for (size_t k=0; k<nd; ++k) shape[k] = tv_shape(k); + update_strides(); + } + + }; + /** * @brief The interface manager introduces a concept for managing the * interfaces that can be handled as C-style arrays. It encapsulates methods @@ -62,12 +225,12 @@ namespace bob { namespace io { namespace base { namespace array { * @brief Re-allocates this interface taking into consideration new * requirements. The internal memory should be considered uninitialized. */ - virtual void set (const BobIoTypeinfo& req) =0; + virtual void set (const typeinfo& req) =0; /** * @brief Type information for this interface. */ - virtual const BobIoTypeinfo& type() const =0; + virtual const typeinfo& type() const =0; /** * @brief Borrows a reference from the underlying memory. This means diff --git a/bob/io/base/include/bob.io.base/array_type.h b/bob/io/base/include/bob.io.base/array_type.h new file mode 100644 index 0000000..89eb1e2 --- /dev/null +++ b/bob/io/base/include/bob.io.base/array_type.h @@ -0,0 +1,162 @@ +/** + * @date Sat Apr 9 18:10:10 2011 +0200 + * @author Laurent El Shafey <Laurent.El-Shafey@idiap.ch> + * + * @brief This file contains information about the supported arrays + * + * Copyright (C) Idiap Research Institute, Martigny, Switzerland + */ + +#ifndef BOB_IO_BASE_ARRAY_TYPE_H +#define BOB_IO_BASE_ARRAY_TYPE_H + +#include <stdint.h> +#include <cstdlib> +#include <complex> + +/** + * @ingroup IO_ARRAY + * @brief This macro defines the maximum number of dimensions supported by bob. + * A variable in the bob.io.array namespace is created from this macro + * receiving the same value. Use that variable on your programs, or this macro + * on your preprocessor code. + */ +#define BOB_MAX_DIM 4 + +namespace bob { namespace io { namespace base { namespace array { + + /** + * @brief Enumeration of the supported type for multidimensional arrays + * @warning float128 and complex256 are defined but currently not + * supported + */ + typedef enum ElementType { + t_unknown=0, + t_bool=1, + t_int8=2, + t_int16=3, + t_int32=4, + t_int64=5, + t_uint8=6, + t_uint16=7, + t_uint32=8, + t_uint64=9, + t_float32=10, + t_float64=11, + t_float128=12, + t_complex64=13, + t_complex128=14, + t_complex256=15 + } ElementType; + + /** + * @brief Maximum number of supported dimensions for multidimensional + * arrays. + */ + const size_t N_MAX_DIMENSIONS_ARRAY = BOB_MAX_DIM; + + /** + * @brief These are some type to element type conversions + */ + template<typename T> ElementType getElementType() { + return t_unknown; + } + + /** + * @brief Some specializations that convert type to element type. + */ + template<> inline ElementType getElementType<bool>() { return t_bool; } + template<> inline ElementType getElementType<int8_t>() { return t_int8; } + template<> inline ElementType getElementType<int16_t>() + { return t_int16; } + template<> inline ElementType getElementType<int32_t>() + { return t_int32; } + template<> inline ElementType getElementType<int64_t>() + { return t_int64; } + template<> inline ElementType getElementType<uint8_t>() + { return t_uint8; } + template<> inline ElementType getElementType<uint16_t>() + { return t_uint16; } + template<> inline ElementType getElementType<uint32_t>() + { return t_uint32; } + template<> inline ElementType getElementType<uint64_t>() + { return t_uint64; } + template<> inline ElementType getElementType<float>() + { return t_float32; } + template<> inline ElementType getElementType<double>() + { return t_float64; } + template<> inline ElementType getElementType<long double>() + { return t_float128; } + template<> inline ElementType getElementType<std::complex<float> >() + { return t_complex64; } + template<> inline ElementType getElementType<std::complex<double> >() + { return t_complex128; } + template<> inline ElementType getElementType<std::complex<long double> >() + { return t_complex256; } + + /** + * @brief These are some type to element size conversions + */ + template<typename T> size_t getElementSize() { + return 0; + } + + /** + * @brief Some specializations that convert the types we handle properly + */ + template<> inline size_t getElementSize<bool>() { return sizeof(bool); } + template<> inline size_t getElementSize<int8_t>() + { return sizeof(int8_t); } + template<> inline size_t getElementSize<int16_t>() + { return sizeof(int16_t); } + template<> inline size_t getElementSize<int32_t>() + { return sizeof(int32_t); } + template<> inline size_t getElementSize<int64_t>() + { return sizeof(int64_t); } + template<> inline size_t getElementSize<uint8_t>() + { return sizeof(uint8_t); } + template<> inline size_t getElementSize<uint16_t>() + { return sizeof(uint16_t); } + template<> inline size_t getElementSize<uint32_t>() + { return sizeof(uint32_t); } + template<> inline size_t getElementSize<uint64_t>() + { return sizeof(uint64_t); } + template<> inline size_t getElementSize<float>() + { return sizeof(float); } + template<> inline size_t getElementSize<double>() + { return sizeof(double); } + template<> inline size_t getElementSize<long double>() + { return sizeof(long double); } + template<> inline size_t getElementSize<std::complex<float> >() + { return sizeof(std::complex<float>); } + template<> inline size_t getElementSize<std::complex<double> >() + { return sizeof(std::complex<double>); } + template<> inline size_t getElementSize<std::complex<long double> >() + { return sizeof(std::complex<long double>); } + + /** + * @brief Returns the type size given the enumeration + */ + size_t getElementSize(ElementType t); + + /** + * @brief Gets a string representation of an element type value + */ + const char* stringize(ElementType t); + + /** + * @brief Equivalent to call stringize() on the result of + * getElementType<T>(). + */ + template<typename T> const char* stringize() { + return stringize(getElementType<T>()); + } + + /** + * @brief Returns the ElementType given the string representation + */ + ElementType unstringize(const char* name); + +}}}} + +#endif /* BOB_IO_BASE_ARRAY_TYPE_H */ diff --git a/bob/io/base/include/bob.io.base/array_utils.h b/bob/io/base/include/bob.io.base/array_utils.h index 2ccf320..8fdfa77 100644 --- a/bob/io/base/include/bob.io.base/array_utils.h +++ b/bob/io/base/include/bob.io.base/array_utils.h @@ -22,9 +22,9 @@ namespace bob { namespace io { namespace base { namespace array { /** - * @brief Fills in shape and stride starting from a type information object + * @brief Fills in shape and stride starting from a typeinfo object */ - template <int N> void set_shape_and_stride(const BobIoTypeinfo& info, + template <int N> void set_shape_and_stride(const typeinfo& info, blitz::TinyVector<int,N>& shape, blitz::TinyVector<int,N>& stride) { for (int k=0; k<N; ++k) { shape[k] = info.shape[k]; @@ -43,19 +43,19 @@ namespace bob { namespace io { namespace base { namespace array { template <typename T, int N> blitz::Array<T,N> wrap(const interface& buf) { - const BobIoTypeinfo& type = buf.type(); + const typeinfo& type = buf.type(); if (!buf.ptr()) throw std::runtime_error("empty buffer"); - if (type.dtype != PyBlitzArrayCxx_CToTypenum<T>()) { + if (type.dtype != bob::io::base::array::getElementType<T>()) { boost::format m("cannot efficiently retrieve blitz::Array<%s,%d> from buffer of type '%s'"); - m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&type); + m % stringize<T>() % N % type.str(); throw std::runtime_error(m.str()); } if (type.nd != N) { boost::format m("cannot retrieve blitz::Array<%s,%d> from buffer of type '%s'"); - m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&type); + m % stringize<T>() % N % type.str(); throw std::runtime_error(m.str()); } @@ -80,49 +80,45 @@ namespace bob { namespace io { namespace base { namespace array { template <typename T, int N> blitz::Array<T,N> cast(const interface& buf) { - const BobIoTypeinfo& type = buf.type(); + const typeinfo& type = buf.type(); if (type.nd != N) { boost::format m("cannot cast blitz::Array<%s,%d> from buffer of type '%s'"); - m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&type); + m % stringize<T>() % N % type.str(); throw std::runtime_error(m.str()); } switch (type.dtype) { - case NPY_BOOL: + case bob::io::base::array::t_bool: return bob::core::array::cast<T>(wrap<bool,N>(buf)); - case NPY_INT8: + case bob::io::base::array::t_int8: return bob::core::array::cast<T>(wrap<int8_t,N>(buf)); - case NPY_INT16: + case bob::io::base::array::t_int16: return bob::core::array::cast<T>(wrap<int16_t,N>(buf)); - case NPY_INT32: + case bob::io::base::array::t_int32: return bob::core::array::cast<T>(wrap<int32_t,N>(buf)); - case NPY_INT64: + case bob::io::base::array::t_int64: return bob::core::array::cast<T>(wrap<int64_t,N>(buf)); - case NPY_UINT8: + case bob::io::base::array::t_uint8: return bob::core::array::cast<T>(wrap<uint8_t,N>(buf)); - case NPY_UINT16: + case bob::io::base::array::t_uint16: return bob::core::array::cast<T>(wrap<uint16_t,N>(buf)); - case NPY_UINT32: + case bob::io::base::array::t_uint32: return bob::core::array::cast<T>(wrap<uint32_t,N>(buf)); - case NPY_UINT64: + case bob::io::base::array::t_uint64: return bob::core::array::cast<T>(wrap<uint64_t,N>(buf)); - case NPY_FLOAT32: + case bob::io::base::array::t_float32: return bob::core::array::cast<T>(wrap<float,N>(buf)); - case NPY_FLOAT64: + case bob::io::base::array::t_float64: return bob::core::array::cast<T>(wrap<double,N>(buf)); -# ifdef NPY_FLOAT128 - case NPY_FLOAT128: + case bob::io::base::array::t_float128: return bob::core::array::cast<T>(wrap<long double,N>(buf)); -# endif - case NPY_COMPLEX64: + case bob::io::base::array::t_complex64: return bob::core::array::cast<T>(wrap<std::complex<float>,N>(buf)); - case NPY_COMPLEX128: + case bob::io::base::array::t_complex128: return bob::core::array::cast<T>(wrap<std::complex<double>,N>(buf)); -# ifdef NPY_COMPLEX256 - case NPY_COMPLEX256: + case bob::io::base::array::t_complex256: return bob::core::array::cast<T>(wrap<std::complex<long double>,N>(buf)); -# endif default: break; } diff --git a/bob/io/base/include/bob.io.base/blitz_array.h b/bob/io/base/include/bob.io.base/blitz_array.h index f784156..9927e00 100644 --- a/bob/io/base/include/bob.io.base/blitz_array.h +++ b/bob/io/base/include/bob.io.base/blitz_array.h @@ -11,17 +11,18 @@ #ifndef BOB_IO_BASE_BLITZ_ARRAY_H #define BOB_IO_BASE_BLITZ_ARRAY_H -#include <bob.io.base/array.h> -#include <bob.io.base/array_utils.h> +#include <stdexcept> +#include <boost/make_shared.hpp> +#include <boost/format.hpp> +#include <blitz/array.h> #include <bob.core/check.h> #include <bob.core/cast.h> #include <bob.core/array_copy.h> -#include <stdexcept> -#include <boost/make_shared.hpp> -#include <boost/format.hpp> -#include <blitz/array.h> +#include <bob.io.base/array.h> +#include <bob.io.base/array_utils.h> +#include <bob.io.base/array_type.h> namespace bob { namespace io { namespace base { namespace array { @@ -55,13 +56,13 @@ namespace bob { namespace io { namespace base { namespace array { /** * @brief Starts with an uninitialized, pre-allocated array. */ - blitz_array(const BobIoTypeinfo& info); + blitz_array(const typeinfo& info); /** * @brief Borrows the given pointer - if you use this constructor, you * must make sure the pointed data outlives this object. */ - blitz_array(void* data, const BobIoTypeinfo& info); + blitz_array(void* data, const typeinfo& info); /** * @brief Destroyes me @@ -82,7 +83,7 @@ namespace bob { namespace io { namespace base { namespace array { * @brief Re-allocates this buffer taking into consideration new * requirements. The internal memory should be considered uninitialized. */ - virtual void set (const BobIoTypeinfo& req); + virtual void set (const typeinfo& req); /** * @brief Refers to the data of another blitz array. @@ -90,9 +91,9 @@ namespace bob { namespace io { namespace base { namespace array { void set(boost::shared_ptr<blitz_array> other); /** - * @brief type information + * @brief Element type */ - virtual const BobIoTypeinfo& type() const { return m_type; } + virtual const typeinfo& type() const { return m_type; } /** * @brief Borrows a reference from the underlying memory. This means @@ -151,20 +152,16 @@ namespace bob { namespace io { namespace base { namespace array { template <typename T, int N> void set(boost::shared_ptr<blitz::Array<T,N> > data) { - if (PyBlitzArrayCxx_CToTypenum<T>() == NPY_NOTYPE) + if (getElementType<T>() == t_unknown) throw std::runtime_error("unsupported element type on blitz::Array<>"); - if (N > BOB_BLITZ_MAXDIMS) + if (N > BOB_MAX_DIM) throw std::runtime_error("unsupported number of dimensions on blitz::Array<>"); if (!isCContiguous(*data.get())) throw std::runtime_error("cannot buffer'ize non-c contiguous array"); - m_type.dtype = PyBlitzArrayCxx_CToTypenum<T>(); - m_type.nd = data->ndim(); - for (size_t k=0; k<m_type.nd; ++k) { - m_type.shape[k] = data->shape(k); - m_type.stride[k] = data->stride(k); - } + m_type.set(data); + m_data = data; m_ptr = reinterpret_cast<void*>(data->data()); m_is_blitz = true; @@ -212,15 +209,15 @@ namespace bob { namespace io { namespace base { namespace array { if (!m_data) throw std::runtime_error("empty blitz array"); - if (m_type.dtype != PyBlitzArrayCxx_CToTypenum<T>()) { + if (m_type.dtype != getElementType<T>()) { boost::format m("cannot efficiently retrieve blitz::Array<%s,%d> from buffer of type '%s'"); - m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&m_type); + m % stringize<T>() % N % m_type.str(); throw std::runtime_error(m.str()); } if (m_type.nd != N) { boost::format m("cannot retrieve blitz::Array<%s,%d> from buffer of type '%s'"); - m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&m_type); + m % stringize<T>() % N % m_type.str(); throw std::runtime_error(m.str()); } @@ -252,7 +249,7 @@ namespace bob { namespace io { namespace base { namespace array { private: //representation - BobIoTypeinfo m_type; ///< type information + typeinfo m_type; ///< type information void* m_ptr; ///< pointer to the data bool m_is_blitz; ///< true if initiated with a blitz::Array<> boost::shared_ptr<void> m_data; ///< Pointer to the data owner diff --git a/bob/io/base/include/bob.io.base/reorder.h b/bob/io/base/include/bob.io.base/reorder.h new file mode 100644 index 0000000..09ebf50 --- /dev/null +++ b/bob/io/base/include/bob.io.base/reorder.h @@ -0,0 +1,94 @@ +/** + * @date Tue Nov 22 11:24:44 2011 +0100 + * @author Andre Anjos <andre.anjos@idiap.ch> + * + * @brief Row-major to column-major reordering and vice-versa + * + * Copyright (C) Idiap Research Institute, Martigny, Switzerland + */ + +#ifndef BOB_IO_BASE_REORDER_H +#define BOB_IO_BASE_REORDER_H + +#include <stdint.h> + +#include <bob.io.base/array.h> + +namespace bob { namespace io { namespace base { + + /** + * Returns, on the first argument, the linear indexes by calculating the + * linear positions relative to both row-major and column-major order + * matrixes given a certain index accessing a position in the matrix and the + * matrix shape + * + * @param row The resulting row-major linear index. + * (row,col) is a 2-tuple with the results: row-major and + * column-major linear indexes + * @param col The resulting column-major linear index. (see above) + * @param i Index of the column. + * (i,j) a 2-tuple with the indexes as would be accessed + * [col][row]; this is the same as accessing the matrix like + * on directions [y][x] + * @param j Index of the row. (see above) + * @param shape a 2-tuple with the matrix shape like [col][row]; this is the + * same as thinking about the extends of the matrix like on directions + * [y][x] + * + * Detailed arithmetics with graphics and explanations can be found here: + * http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html + */ + void rc2d(size_t& row, size_t& col, const size_t i, const size_t j, + const size_t* shape); + + /** + * Same as above, but for a 3D array organized as [depth][column][row] + */ + void rc3d(size_t& row, size_t& col, const size_t i, const size_t j, + const size_t k, const size_t* shape); + + /** + * Same as above, but for a 4D array organized as [time][depth][column][row] + */ + void rc4d(size_t& row, size_t& col, const size_t i, const size_t j, + const size_t k, const size_t l, const size_t* shape); + + /** + * Converts the data from row-major order (C-Style) to column major order + * (Fortran style). Input parameters are the src data in row-major order, the + * destination (pre-allocated) array of the same size and the type + * information. + */ + void row_to_col_order(const void* src_, void* dst_, const + bob::io::base::array::typeinfo& info); + + /** + * Converts the data from column-major order (Fortran-Style) to row major + * order (C style), which is required by bob. Input parameters are the src + * data in column-major order, the destination (pre-allocated) array of the + * same size and the type information. + */ + void col_to_row_order(const void* src_, void* dst_, + const bob::io::base::array::typeinfo& info); + + /** + * Converts the data from row-major order (C-Style) to column major order + * (Fortran style). Input parameters are the src data in row-major order, the + * destination (pre-allocated) array of the same size and the type + * information. + */ + void row_to_col_order_complex(const void* src_, void* dst_re_, + void* dst_im_, const bob::io::base::array::typeinfo& info); + + /** + * Converts the data from column-major order (Fortran-Style) to row major + * order (C style), which is required by bob. Input parameters are the src + * data in column-major order, the destination (pre-allocated) array of the + * same size and the type information. + */ + void col_to_row_order_complex(const void* src_re_, const void* src_im_, + void* dst_, const bob::io::base::array::typeinfo& info); + +}}} + +#endif /* BOB_IO_BASE_REORDER_H */ diff --git a/bob/io/base/include/bob.io.base/utils.h b/bob/io/base/include/bob.io.base/utils.h new file mode 100644 index 0000000..c42b1fa --- /dev/null +++ b/bob/io/base/include/bob.io.base/utils.h @@ -0,0 +1,105 @@ +/** + * @author Andre Anjos <andre.anjos@idiap.ch> + * @date Wed 3 Oct 07:46:49 2012 + * + * @brief Utilities for easy manipulation of filed data. + */ + +#ifndef BOB_IO_BASE_BASE_UTILS_H +#define BOB_IO_BASE_BASE_UTILS_H + +#include <boost/shared_ptr.hpp> + +#include <bob.io.base/File.h> + +namespace bob { namespace io { namespace base { + + /** + * Creates a new array codec using the filename extension to determine which + * codec to use. The opening mode is passed to the underlying registered File + * implementation. + * + * Here are the meanings of the mode flag: + * + * 'r': opens for reading only - no modifications can occur; it is an + * error to open a file that does not exist for read-only operations. + * 'w': opens for reading and writing, but truncates the file if it + * exists; it is not an error to open files that do not exist with + * this flag. + * 'a': opens for reading and writing - any type of modification can + * occur. If the file does not exist, this flag is effectively like + * 'w'. + */ + boost::shared_ptr<File> open (const char* filename, char mode); + + /** + * Opens the file pretending it has a different extension (that is, using a + * different codec) then the one expected (if any). This allows you to write + * a file with the extension you want, but still using one of the available + * codecs. + */ + boost::shared_ptr<File> open (const char* filename, char mode, + const char* pretend_extension); + + /** + * Peeks the file and returns the typeinfo for reading individual frames (or + * samples) from the file. + * + * This method is equivalent to calling open() with 'r' as mode flag and then + * calling type() on the returned bob::io::base::File object. + */ + bob::io::base::array::typeinfo peek (const char* filename); + + /** + * Peeks the file and returns the typeinfo for reading the whole contents in + * a single shot. + * + * This method is equivalent to calling open() with 'r' as mode flag and then + * calling type_all() on the returned bob::io::base::File object. + */ + bob::io::base::array::typeinfo peek_all (const char* filename); + + /** + * Opens for reading and load all contents + * + * This method is equivalent to calling open() with 'r' as mode flag and then + * calling read_all() on the returned bob::io::base::File object. + */ + template <typename T, int N> blitz::Array<T,N> load (const char* filename) { + return open(filename, 'r')->read_all<T,N>(); + } + + /** + * Opens for reading and load a particular frame (or sample) + * + * This method is equivalent to calling open() with 'r' as mode flag and then + * calling read(index) on the returned bob::io::base::File object. + */ + template <typename T, int N> blitz::Array<T,N> load (const char* filename, size_t index) { + return open(filename, 'r')->read<T,N>(index); + } + + /** + * Opens for appending and add an array to it + * + * This method is equivalent to calling open() with 'a' as mode flag and then + * calling append(data) on the returned bob::io::base::File object. + */ + template <typename T, int N> void append (const char* filename, const blitz::Array<T,N>& data) { + open(filename, 'a')->append(data); + } + + /** + * Opens for writing and write an array to it. If the file exists before the + * call to this method, it is truncated. + * + * This method is equivalent to calling open() with 'w' as mode flag and then + * calling write(data) on the returned bob::io::base::File object. + */ + template <typename T, int N> void save (const char* filename, const blitz::Array<T,N>& data) { + open(filename, 'w')->write(data); + } + +}}} + +#endif /* BOB_IO_BASE_BASE_UTILS_H */ diff --git a/bob/io/base/main.cpp b/bob/io/base/main.cpp index 50eaabd..f7dfb87 100644 --- a/bob/io/base/main.cpp +++ b/bob/io/base/main.cpp @@ -13,10 +13,6 @@ #endif #include <bob.blitz/capi.h> #include <bob.blitz/cleanup.h> -#include <bob.core/logging.h> - -#include "cpp/CodecRegistry.h" -#include "plugin.h" /** * Creates an str object, from a C or C++ string. Returns a **new @@ -124,52 +120,6 @@ static PyObject* create_module (void) { PyBobIo_API[PyBobIo_APIVersion_NUM] = (void *)&PyBobIo_APIVersion; - /******************** - * Type Information * - ********************/ - - PyBobIo_API[BobIoTypeinfo_Init_NUM] = (void *)&BobIoTypeinfo_Init; - - PyBobIo_API[BobIoTypeinfo_Copy_NUM] = (void *)&BobIoTypeinfo_Copy; - - PyBobIo_API[BobIoTypeinfo_Set_NUM] = (void *)&BobIoTypeinfo_Set; - - PyBobIo_API[BobIoTypeinfo_SetWithStrides_NUM] = (void *)&BobIoTypeinfo_SetWithStrides; - - PyBobIo_API[BobIoTypeinfo_SignedSet_NUM] = (void *)&BobIoTypeinfo_SignedSet; - - PyBobIo_API[BobIoTypeinfo_SignedSetWithStrides_NUM] = (void *)&BobIoTypeinfo_SignedSetWithStrides; - - PyBobIo_API[BobIoTypeinfo_Reset_NUM] = (void *)&BobIoTypeinfo_Reset; - - PyBobIo_API[BobIoTypeinfo_IsValid_NUM] = (void *)&BobIoTypeinfo_IsValid; - - PyBobIo_API[BobIoTypeinfo_HasValidShape_NUM] = (void *)&BobIoTypeinfo_HasValidShape; - - PyBobIo_API[BobIoTypeinfo_ResetShape_NUM] = (void *)&BobIoTypeinfo_ResetShape; - - PyBobIo_API[BobIoTypeinfo_UpdateStrides_NUM] = (void *)&BobIoTypeinfo_UpdateStrides; - - PyBobIo_API[BobIoTypeinfo_Size_NUM] = (void *)&BobIoTypeinfo_Size; - - PyBobIo_API[BobIoTypeinfo_BufferSize_NUM] = (void *)&BobIoTypeinfo_BufferSize; - - PyBobIo_API[BobIoTypeinfo_IsCompatible_NUM] = (void *)&BobIoTypeinfo_IsCompatible; - - PyBobIo_API[BobIoTypeinfo_Str_NUM] = (void *)&BobIoTypeinfo_Str; - - /******************** - * Array reordering * - ********************/ - - PyBobIo_API[BobIoReorder_RowToCol_NUM] = (void *)&BobIoReorder_RowToCol; - - PyBobIo_API[BobIoReorder_ColToRow_NUM] = (void *)&BobIoReorder_ColToRow; - - PyBobIo_API[BobIoReorder_RowToColComplex_NUM] = (void *)&BobIoReorder_RowToColComplex; - - PyBobIo_API[BobIoReorder_ColToRowComplex_NUM] = (void *)&BobIoReorder_ColToRowComplex; - /********************************** * Bindings for bob.io.base.File * **********************************/ @@ -178,23 +128,13 @@ static PyObject* create_module (void) { PyBobIo_API[PyBobIoFileIterator_Type_NUM] = (void *)&PyBobIoFileIterator_Type; - /************************************** - * File loading and data type peeking * - **************************************/ - - PyBobIo_API[BobIoFile_Open_NUM] = (void *)&BobIoFile_Open; - - PyBobIo_API[BobIoFile_OpenWithExtension_NUM] = (void *)&BobIoFile_OpenWithExtension; - - PyBobIo_API[BobIoFile_Peek_NUM] = (void *)&BobIoFile_Peek; - - PyBobIo_API[BobIoFile_PeekAll_NUM] = (void *)&BobIoFile_PeekAll; - /************************ * I/O generic bindings * ************************/ - PyBobIo_API[PyBobIo_TypeinfoAsTuple_NUM] = (void *)PyBobIo_TypeinfoAsTuple; + PyBobIo_API[PyBobIo_AsTypenum_NUM] = (void *)PyBobIo_AsTypenum; + + PyBobIo_API[PyBobIo_TypeInfoAsTuple_NUM] = (void *)PyBobIo_TypeInfoAsTuple; PyBobIo_API[PyBobIo_FilenameConverter_NUM] = (void *)PyBobIo_FilenameConverter; @@ -208,9 +148,9 @@ static PyObject* create_module (void) { PyBobIo_API[PyBobIoHDF5File_Converter_NUM] = (void *)&PyBobIoHDF5File_Converter; - /***************************************** - * Code Registration and De-registration * - *****************************************/ +/***************************************** + * Code Registration and De-registration * + *****************************************/ PyBobIo_API[PyBobIoCodec_Register_NUM] = (void *)&PyBobIoCodec_Register; @@ -237,13 +177,6 @@ static PyObject* create_module (void) { if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) return 0; - /* imports dependencies */ - if (import_bob_core_logging() < 0) { - PyErr_Print(); - PyErr_Format(PyExc_ImportError, "cannot import `%s'", BOB_EXT_MODULE_NAME); - return 0; - } - /* imports dependencies */ if (import_bob_blitz() < 0) { PyErr_Print(); @@ -251,41 +184,6 @@ static PyObject* create_module (void) { return 0; } - /* activates built-in plugins */ - if (!PyBobIoCodec_Register(".csv", "Comma-Separated Values (built-in)", - &make_csv_file)) { - PyErr_Print(); - } - - if (!PyBobIoCodec_Register(".txt", "Comma-Separated Values (built-in)", - &make_csv_file)) { - PyErr_Print(); - } - - if (!PyBobIoCodec_Register(".h5", "Hierarchical Data Format v5 (libhdf5)", - &make_hdf5_file)) { - PyErr_Print(); - } - - if (!PyBobIoCodec_Register(".hdf5", "Hierarchical Data Format v5 (libhdf5)", - &make_hdf5_file)) { - PyErr_Print(); - } - - if (!PyBobIoCodec_Register(".hdf", "Hierarchical Data Format v5 (libhdf5)", - &make_hdf5_file)) { - PyErr_Print(); - } - - if (!PyBobIoCodec_Register(".bindata", "Torch3 binary data format (built-in)", - &make_torch3_file)) { - PyErr_Print(); - } - - if (!PyBobIoCodec_Register(".tensor", "Torch3vision v2.1 tensor format (built-in)", &make_tensor_file)) { - PyErr_Print(); - } - Py_INCREF(m); return m; diff --git a/bob/io/base/plugin.h b/bob/io/base/plugin.h deleted file mode 100644 index 735ff37..0000000 --- a/bob/io/base/plugin.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @author Andre Anjos <andre.anjos@idiap.ch> - * @date Wed 14 May 14:42:34 2014 CEST - * - * @brief Implements the matlab (.mat) array codec using matio - * - * Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland - */ - -#ifndef BOB_IO_BASE_PLUGIN_H -#define BOB_IO_BASE_PLUGIN_H - -#include <boost/shared_ptr.hpp> -#include <bob.io.base/File.h> - -/** - * This defines the factory method F that can create codecs of this type. - * - * Here are the meanings of the mode flag that should be respected by your - * factory implementation: - * - * 'r': opens for reading only - no modifications can occur; it is an - * error to open a file that does not exist for read-only operations. - * 'w': opens for reading and writing, but truncates the file if it - * exists; it is not an error to open files that do not exist with - * this flag. - * 'a': opens for reading and writing - any type of modification can - * occur. If the file does not exist, this flag is effectively like - * 'w'. - * - * Returns a newly allocated File object that can read and write data to the - * file using a specific backend. - */ -boost::shared_ptr<bob::io::base::File> make_csv_file (const char* path, char mode); -boost::shared_ptr<bob::io::base::File> make_hdf5_file (const char* path, char mode); -boost::shared_ptr<bob::io::base::File> make_torch3_file (const char* path, char mode); -boost::shared_ptr<bob::io::base::File> make_tensor_file (const char* path, char mode); - -#endif /* BOB_IO_BASE_PLUGIN_H */ diff --git a/bob/io/base/reorder.cpp b/bob/io/base/reorder.cpp deleted file mode 100644 index b07ac50..0000000 --- a/bob/io/base/reorder.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/** - * @date Tue Nov 22 11:24:44 2011 +0100 - * @author Andre Anjos <andre.anjos@idiap.ch> - * - * @brief Implementation of row-major/column-major reordering - * - * Copyright (C) Idiap Research Institute, Martigny, Switzerland - */ - -#define BOB_IO_BASE_MODULE -#include <bob.io.base/api.h> -#include <bob.blitz/capi.h> -#include <cstring> //for memcpy - -/** - * Returns, on the first argument, the linear indexes by calculating the - * linear positions relative to both row-major and column-major order - * matrixes given a certain index accessing a position in the matrix and the - * matrix shape - * - * @param row The resulting row-major linear index. - * (row,col) is a 2-tuple with the results: row-major and - * column-major linear indexes - * @param col The resulting column-major linear index. (see above) - * @param i Index of the column. - * (i,j) a 2-tuple with the indexes as would be accessed - * [col][row]; this is the same as accessing the matrix like - * on directions [y][x] - * @param j Index of the row. (see above) - * @param shape a 2-tuple with the matrix shape like [col][row]; this is the - * same as thinking about the extends of the matrix like on directions - * [y][x] - * - * Detailed arithmetics with graphics and explanations can be found here: - * http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html - */ -static void rc2d(size_t& row, size_t& col, const size_t i, const size_t j, - const size_t* shape) { - - row = (i * shape[1]) + j; - col = (j * shape[0]) + i; - -} - -/** - * Same as above, but for a 3D array organized as [depth][column][row] - */ -static void rc3d(size_t& row, size_t& col, const size_t i, const size_t j, - const size_t k, const size_t* shape) { - - row = ( (i * shape[1]) + j ) * shape[2] + k; - col = ( (k * shape[1]) + j ) * shape[0] + i; - -} - -/** - * Same as above, but for a 4D array organized as [time][depth][column][row] - */ -static void rc4d(size_t& row, size_t& col, const size_t i, const size_t j, - const size_t k, const size_t l, const size_t* shape) { - - row = ( ( i * shape[1] + j ) * shape[2] + k ) * shape[3] + l; - col = ( ( l * shape[2] + k ) * shape[1] + j ) * shape[0] + i; - -} - -int BobIoReorder_RowToCol(const void* src_, void* dst_, - const BobIoTypeinfo* info) { - - size_t dsize = PyBlitzArray_TypenumSize(info->dtype); - - //cast to byte type so we can manipulate the pointers... - const uint8_t* src = static_cast<const uint8_t*>(src_); - uint8_t* dst = static_cast<uint8_t*>(dst_); - - switch(info->nd) { - - case 1: - std::memcpy(dst, src, BobIoTypeinfo_BufferSize(info)); - break; - - case 2: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) { - size_t row_major, col_major; - rc2d(row_major, col_major, i, j, info->shape); - row_major *= dsize; - col_major *= dsize; - std::memcpy(&dst[col_major], &src[row_major], dsize); - } - break; - - case 3: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) { - size_t row_major, col_major; - rc3d(row_major, col_major, i, j, k, info->shape); - row_major *= dsize; - col_major *= dsize; - std::memcpy(&dst[col_major], &src[row_major], dsize); - } - break; - - case 4: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) - for (size_t l=0; l<info->shape[3]; ++l) { - size_t row_major, col_major; - rc4d(row_major, col_major, i, j, k, l, info->shape); - row_major *= dsize; - col_major *= dsize; - std::memcpy(&dst[col_major], &src[row_major], dsize); - } - break; - - default: - PyErr_Format(PyExc_RuntimeError, "can only flip arrays with up to %u dimensions - you passed one with %zu dimensions", BOB_BLITZ_MAXDIMS, info->nd); - return 0; - } - - return 1; -} - -int BobIoReorder_ColToRow(const void* src_, void* dst_, - const BobIoTypeinfo* info) { - - size_t dsize = PyBlitzArray_TypenumSize(info->dtype); - - //cast to byte type so we can manipulate the pointers... - const uint8_t* src = static_cast<const uint8_t*>(src_); - uint8_t* dst = static_cast<uint8_t*>(dst_); - - switch(info->nd) { - - case 1: - std::memcpy(dst, src, BobIoTypeinfo_BufferSize(info)); - break; - - case 2: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) { - size_t row_major, col_major; - rc2d(row_major, col_major, i, j, info->shape); - row_major *= dsize; - col_major *= dsize; - std::memcpy(&dst[row_major], &src[col_major], dsize); - } - break; - - case 3: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) { - size_t row_major, col_major; - rc3d(row_major, col_major, i, j, k, info->shape); - row_major *= dsize; - col_major *= dsize; - std::memcpy(&dst[row_major], &src[col_major], dsize); - } - break; - - case 4: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) - for (size_t l=0; l<info->shape[3]; ++l) { - size_t row_major, col_major; - rc4d(row_major, col_major, i, j, k, l, info->shape); - row_major *= dsize; - col_major *= dsize; - std::memcpy(&dst[row_major], &src[col_major], dsize); - } - break; - - default: - PyErr_Format(PyExc_RuntimeError, "can only flip arrays with up to %u dimensions - you passed one with %zu dimensions", BOB_BLITZ_MAXDIMS, info->nd); - return 0; - } - - return 1; -} - -int BobIoReorder_RowToColComplex(const void* src_, void* dst_re_, - void* dst_im_, const BobIoTypeinfo* info) { - - size_t dsize = PyBlitzArray_TypenumSize(info->dtype); - size_t dsize2 = dsize/2; ///< size of each complex component (real, imaginary) - - //cast to byte type so we can manipulate the pointers... - const uint8_t* src = static_cast<const uint8_t*>(src_); - uint8_t* dst_re = static_cast<uint8_t*>(dst_re_); - uint8_t* dst_im = static_cast<uint8_t*>(dst_im_); - - switch(info->nd) { - - case 1: - for (size_t i=0; i<info->shape[0]; ++i) { - std::memcpy(&dst_re[dsize2*i], &src[dsize*i] , dsize2); - std::memcpy(&dst_im[dsize2*i], &src[dsize*i]+dsize2, dsize2); - } - break; - - case 2: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) { - size_t row_major, col_major; - rc2d(row_major, col_major, i, j, info->shape); - row_major *= dsize; - col_major *= dsize2; - std::memcpy(&dst_re[col_major], &src[row_major] , dsize2); - std::memcpy(&dst_im[col_major], &src[row_major]+dsize2, dsize2); - } - break; - - case 3: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) { - size_t row_major, col_major; - rc3d(row_major, col_major, i, j, k, info->shape); - row_major *= dsize; - col_major *= dsize2; - std::memcpy(&dst_re[col_major], &src[row_major] , dsize2); - std::memcpy(&dst_im[col_major], &src[row_major]+dsize2, dsize2); - } - break; - - case 4: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) - for (size_t l=0; l<info->shape[3]; ++l) { - size_t row_major, col_major; - rc4d(row_major, col_major, i, j, k, l, info->shape); - row_major *= dsize; - col_major *= dsize2; - std::memcpy(&dst_re[col_major], &src[row_major] , dsize2); - std::memcpy(&dst_im[col_major], &src[row_major]+dsize2, dsize2); - } - break; - - default: - PyErr_Format(PyExc_RuntimeError, "can only flip arrays with up to %u dimensions - you passed one with %zu dimensions", BOB_BLITZ_MAXDIMS, info->nd); - return 0; - } - - return 1; -} - -int BobIoReorder_ColToRowComplex(const void* src_re_, - const void* src_im_, void* dst_, const BobIoTypeinfo* info) { - - size_t dsize = PyBlitzArray_TypenumSize(info->dtype); - size_t dsize2 = dsize/2; ///< size of each complex component (real, imaginary) - - //cast to byte type so we can manipulate the pointers... - const uint8_t* src_re = static_cast<const uint8_t*>(src_re_); - const uint8_t* src_im = static_cast<const uint8_t*>(src_im_); - uint8_t* dst = static_cast<uint8_t*>(dst_); - - switch(info->nd) { - - case 1: - for (size_t i=0; i<info->shape[0]; ++i) { - std::memcpy(&dst[dsize*i] , &src_re[dsize2*i], dsize2); - std::memcpy(&dst[dsize*i]+dsize2, &src_im[dsize2*i], dsize2); - } - break; - - case 2: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) { - size_t row_major, col_major; - rc2d(row_major, col_major, i, j, info->shape); - row_major *= dsize; - col_major *= dsize2; - std::memcpy(&dst[row_major], &src_re[col_major], dsize2); - std::memcpy(&dst[row_major]+dsize2, &src_im[col_major], dsize2); - } - break; - - case 3: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) { - size_t row_major, col_major; - rc3d(row_major, col_major, i, j, k, info->shape); - row_major *= dsize; - col_major *= dsize2; - std::memcpy(&dst[row_major] , &src_re[col_major], dsize2); - std::memcpy(&dst[row_major]+dsize2, &src_im[col_major], dsize2); - } - break; - - case 4: - for (size_t i=0; i<info->shape[0]; ++i) - for (size_t j=0; j<info->shape[1]; ++j) - for (size_t k=0; k<info->shape[2]; ++k) - for (size_t l=0; l<info->shape[3]; ++l) { - size_t row_major, col_major; - rc4d(row_major, col_major, i, j, k, l, info->shape); - row_major *= dsize; - col_major *= dsize2; - std::memcpy(&dst[row_major] , &src_re[col_major], dsize2); - std::memcpy(&dst[row_major]+dsize2, &src_im[col_major], dsize2); - } - break; - - default: - PyErr_Format(PyExc_RuntimeError, "can only flip arrays with up to %u dimensions - you passed one with %zu dimensions", BOB_BLITZ_MAXDIMS, info->nd); - return 0; - } - - return 1; -} diff --git a/bob/io/base/typeinfo.cpp b/bob/io/base/typeinfo.cpp deleted file mode 100644 index 386843f..0000000 --- a/bob/io/base/typeinfo.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/** - * @date Tue Nov 8 15:34:31 2011 +0100 - * @author Andre Anjos <andre.anjos@idiap.ch> - * - * @brief Some buffer stuff - * - * Copyright (C) Idiap Research Institute, Martigny, Switzerland - */ - -#define BOB_IO_BASE_MODULE -#include <bob.blitz/capi.h> -#include <bob.io.base/api.h> -#include <boost/format.hpp> - -void BobIoTypeinfo_Init(BobIoTypeinfo* self) { - BobIoTypeinfo_Reset(self); -} - -int BobIoTypeinfo_Copy (BobIoTypeinfo* self, const BobIoTypeinfo* other) { - - self->dtype = other->dtype; - - if (other->nd > (BOB_BLITZ_MAXDIMS+1)) { - PyErr_Format(PyExc_RuntimeError, "unsupported number of dimensions (%" PY_FORMAT_SIZE_T "d) while the maximum is %d", other->nd, BOB_BLITZ_MAXDIMS); - return 0; - } - - self->nd = other->nd; - for (size_t k=0; k<self->nd; ++k) self->shape[k] = other->shape[k]; - - return BobIoTypeinfo_UpdateStrides(self); - -} - -int BobIoTypeinfo_Set (BobIoTypeinfo* self, int dtype, size_t nd, - const size_t* shape) { - - self->dtype = dtype; - - if (nd > (BOB_BLITZ_MAXDIMS+1)) { - PyErr_Format(PyExc_RuntimeError, "unsupported number of dimensions (%" PY_FORMAT_SIZE_T "d) while the maximum is %d", nd, BOB_BLITZ_MAXDIMS); - return 0; - } - - self->nd = nd; - for (size_t k=0; k<nd; ++k) self->shape[k] = shape[k]; - - return BobIoTypeinfo_UpdateStrides(self); - -} - -int BobIoTypeinfo_SignedSet (BobIoTypeinfo* self, int dtype, Py_ssize_t nd, - const Py_ssize_t* shape) { - - self->dtype = dtype; - - if (nd > (BOB_BLITZ_MAXDIMS+1)) { - PyErr_Format(PyExc_RuntimeError, "unsupported number of dimensions (%" PY_FORMAT_SIZE_T "d) while the maximum is %d", nd, BOB_BLITZ_MAXDIMS); - return 0; - } - - self->nd = nd; - for (Py_ssize_t k=0; k<nd; ++k) self->shape[k] = shape[k]; - - return BobIoTypeinfo_UpdateStrides(self); - -} - -int BobIoTypeinfo_SetWithStrides (BobIoTypeinfo* self, int dtype, - size_t nd, const size_t* shape, const size_t* stride) { - self->dtype = dtype; - - if (nd > (BOB_BLITZ_MAXDIMS+1)) { - PyErr_Format(PyExc_RuntimeError, "unsupported number of dimensions (%" PY_FORMAT_SIZE_T "d) while the maximum is %d", nd, BOB_BLITZ_MAXDIMS); - return 0; - } - - self->nd = nd; - for (Py_ssize_t k=0; k<nd; ++k) { - self->shape[k] = shape[k]; - self->stride[k] = stride[k]; - } - - return 1; - -} - -int BobIoTypeinfo_SignedSetWithStrides (BobIoTypeinfo* self, int dtype, - Py_ssize_t nd, const Py_ssize_t* shape, const Py_ssize_t* stride) { - self->dtype = dtype; - - if (nd > (BOB_BLITZ_MAXDIMS+1)) { - PyErr_Format(PyExc_RuntimeError, "unsupported number of dimensions (%" PY_FORMAT_SIZE_T "d) while the maximum is %d", nd, BOB_BLITZ_MAXDIMS); - return 0; - } - - self->nd = nd; - for (Py_ssize_t k=0; k<nd; ++k) { - self->shape[k] = shape[k]; - self->stride[k] = stride[k]; - } - - return 1; - -} - -void BobIoTypeinfo_Reset(BobIoTypeinfo* self) { - - self->dtype = NPY_NOTYPE; - self->nd = 0; - -} - -bool BobIoTypeinfo_IsValid(const BobIoTypeinfo* self) { - - return (self->dtype != NPY_NOTYPE) && (self->nd > 0) && (self->nd <= (BOB_BLITZ_MAXDIMS+1)) && BobIoTypeinfo_HasValidShape(self); - -} - -int BobIoTypeinfo_UpdateStrides(BobIoTypeinfo* self) { - - auto* stride = self->stride; - auto* shape = self->shape; - - switch (self->nd) { - - case 0: - return 1; - - case 1: - stride[0] = 1; - return 1; - - case 2: - stride[1] = 1; - stride[0] = shape[1]; - return 1; - - case 3: - stride[2] = 1; - stride[1] = shape[2]; - stride[0] = shape[1]*shape[2]; - return 1; - - case 4: - stride[3] = 1; - stride[2] = shape[3]; - stride[1] = shape[2]*shape[3]; - stride[0] = shape[1]*shape[2]*shape[3]; - return 1; - - case 5: - stride[4] = 1; - stride[3] = shape[4]; - stride[2] = shape[3]*shape[4]; - stride[1] = shape[2]*shape[3]*shape[4]; - stride[0] = shape[1]*shape[2]*shape[3]*shape[4]; - return 1; - - default: - break; - - } - - PyErr_Format(PyExc_RuntimeError, "unsupported number of dimensions (%" PY_FORMAT_SIZE_T "d) while the maximum is %d", self->nd, BOB_BLITZ_MAXDIMS); - return 0; - -} - -size_t BobIoTypeinfo_Size(const BobIoTypeinfo* self) { - - size_t retval = 1; - for (size_t k=0; k<self->nd; ++k) retval *= self->shape[k]; - return retval; - -} - -size_t BobIoTypeinfo_BufferSize(const BobIoTypeinfo* self) { - - return BobIoTypeinfo_Size(self) * PyBlitzArray_TypenumSize(self->dtype); - -} - -static bool same_shape(size_t nd, const size_t* s1, const size_t* s2) { - - for (size_t k=0; k<nd; ++k) if (s1[k] != s2[k]) return false; - return true; - -} - -bool BobIoTypeinfo_IsCompatible(const BobIoTypeinfo* self, - const BobIoTypeinfo* other) { - - return (self->dtype == other->dtype) && (self->nd == other->nd) && same_shape(self->nd, self->shape, other->shape); - -} - -std::string BobIoTypeinfo_Str(const BobIoTypeinfo* self) { - - boost::format s("dtype: %s (%d); shape: [%s]; size: %d bytes"); - size_t sz = 0; - size_t buf_sz = 0; - if (self->dtype != NPY_NOTYPE) { - //otherwise it throws - sz = PyBlitzArray_TypenumSize(self->dtype); - buf_sz = BobIoTypeinfo_BufferSize(self); - } - s % PyBlitzArray_TypenumAsString(self->dtype) % sz; - - auto* shape = self->shape; - - switch (self->nd) { - - case 0: - s % ""; - break; - - case 1: - s % (boost::format("%d") % shape[0]).str(); - break; - - case 2: - s % (boost::format("%d,%d") % shape[0] % shape[1]).str(); - break; - - case 3: - s % (boost::format("%d,%d,%d") % shape[0] % shape[1] % shape[2]).str(); - break; - - case 4: - s % (boost::format("%d,%d,%d,%d") % shape[0] % shape[1] % shape[2] % shape[3]).str(); - break; - - default: - s % ">4 dimensions?"; - break; - - } - - s % buf_sz; - return s.str(); - -} - -void BobIoTypeinfo_ResetShape (BobIoTypeinfo* self) { - self->shape[0] = 0; -} - -bool BobIoTypeinfo_HasValidShape(const BobIoTypeinfo* self) { - return self->shape[0] != 0; -} diff --git a/setup.py b/setup.py index 967e9b5..d3eac6e 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ package_dir = os.path.dirname(os.path.realpath(__file__)) package_dir = os.path.join(package_dir, 'bob', 'io', 'base', 'include') include_dirs = [package_dir, bob.core.get_include()] +packages = ['bob-core >= 1.2.2'] version = '2.0.0a0' def libhdf5_version(header): @@ -147,7 +148,6 @@ setup( install_requires=[ 'setuptools', 'bob.blitz', - 'bob.core', ], namespace_packages=[ @@ -160,46 +160,47 @@ setup( [ "bob/io/base/version.cpp", ], + packages = packages, include_dirs = include_dirs, define_macros = define_macros, extra_compile_args = extra_compile_args, version = version, - packages = ['boost'], ), Extension("bob.io.base._library", [ - "bob/io/base/cpp/blitz_array.cpp", - "bob/io/base/cpp/TensorFileHeader.cpp", - "bob/io/base/cpp/TensorFile.cpp", "bob/io/base/cpp/CodecRegistry.cpp", + "bob/io/base/cpp/CSVFile.cpp", + "bob/io/base/cpp/File.cpp", + "bob/io/base/cpp/HDF5ArrayFile.cpp", "bob/io/base/cpp/HDF5Attribute.cpp", "bob/io/base/cpp/HDF5Dataset.cpp", "bob/io/base/cpp/HDF5File.cpp", "bob/io/base/cpp/HDF5Group.cpp", "bob/io/base/cpp/HDF5Types.cpp", "bob/io/base/cpp/HDF5Utils.cpp", + "bob/io/base/cpp/reorder.cpp", + "bob/io/base/cpp/T3File.cpp", + "bob/io/base/cpp/TensorArrayFile.cpp", + "bob/io/base/cpp/TensorFileHeader.cpp", + "bob/io/base/cpp/utils.cpp", + "bob/io/base/cpp/TensorFile.cpp", + "bob/io/base/cpp/array.cpp", + "bob/io/base/cpp/array_type.cpp", + "bob/io/base/cpp/blitz_array.cpp", - "bob/io/base/file.cpp", - "bob/io/base/utils.cpp", - "bob/io/base/csv.cpp", - "bob/io/base/hdf5plugin.cpp", - "bob/io/base/torch3.cpp", - "bob/io/base/tensor.cpp", - "bob/io/base/reorder.cpp", - "bob/io/base/typeinfo.cpp", "bob/io/base/bobskin.cpp", "bob/io/base/codec.cpp", + "bob/io/base/file.cpp", "bob/io/base/hdf5.cpp", "bob/io/base/main.cpp", ], + packages = packages, include_dirs = include_dirs, library_dirs = library_dirs, libraries = libraries, define_macros = define_macros, extra_compile_args = extra_compile_args, version = version, - packages = ['boost'], - boost_modules = ['iostreams', 'filesystem'], ), ], -- GitLab