From c61e788abb495f502d3ed586283ff75cb13961a9 Mon Sep 17 00:00:00 2001 From: Andre Anjos <andre.anjos@idiap.ch> Date: Sat, 9 Aug 2014 19:10:18 +0200 Subject: [PATCH] Tries, very hard, to make it a Python-only package --- bob/io/base/bobskin.cpp | 120 +------ bob/io/base/bobskin.h | 17 +- bob/io/base/codec.cpp | 3 +- bob/io/base/cpp/CodecRegistry.cpp | 12 +- .../bob.io.base => cpp}/CodecRegistry.h | 12 +- bob/io/base/cpp/HDF5File.cpp | 3 +- bob/io/base/cpp/HDF5Types.cpp | 102 +++--- 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 | 65 ++-- bob/io/base/cpp/reorder.cpp | 288 ---------------- bob/io/base/{cpp/CSVFile.cpp => csv.cpp} | 90 ++--- bob/io/base/file.cpp | 84 +---- bob/io/base/hdf5.cpp | 1 + .../{cpp/HDF5ArrayFile.cpp => hdf5plugin.cpp} | 68 +--- bob/io/base/include/bob.io.base/File.h | 37 +- 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 | 14 +- 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 | 31 +- bob/io/base/include/bob.io.base/reorder.h | 94 ------ bob/io/base/include/bob.io.base/utils.h | 15 +- bob/io/base/main.cpp | 106 +++++- bob/io/base/plugin.h | 39 +++ bob/io/base/reorder.cpp | 317 ++++++++++++++++++ .../{cpp/TensorArrayFile.cpp => tensor.cpp} | 58 +--- bob/io/base/{cpp/T3File.cpp => torch3.cpp} | 113 +++---- bob/io/base/typeinfo.cpp | 251 ++++++++++++++ bob/io/base/{cpp => }/utils.cpp | 22 +- setup.py | 22 +- 39 files changed, 1394 insertions(+), 1684 deletions(-) rename bob/io/base/{include/bob.io.base => cpp}/CodecRegistry.h (86%) delete mode 100644 bob/io/base/cpp/array.cpp delete mode 100644 bob/io/base/cpp/array_type.cpp delete mode 100644 bob/io/base/cpp/reorder.cpp rename bob/io/base/{cpp/CSVFile.cpp => csv.cpp} (73%) rename bob/io/base/{cpp/HDF5ArrayFile.cpp => hdf5plugin.cpp} (70%) delete mode 100644 bob/io/base/include/bob.io.base/array_type.h delete mode 100644 bob/io/base/include/bob.io.base/reorder.h create mode 100644 bob/io/base/plugin.h create mode 100644 bob/io/base/reorder.cpp rename bob/io/base/{cpp/TensorArrayFile.cpp => tensor.cpp} (56%) rename bob/io/base/{cpp/T3File.cpp => torch3.cpp} (68%) create mode 100644 bob/io/base/typeinfo.cpp rename bob/io/base/{cpp => }/utils.cpp (53%) diff --git a/bob/io/base/bobskin.cpp b/bob/io/base/bobskin.cpp index 494bdaf..12117c1 100644 --- a/bob/io/base/bobskin.cpp +++ b/bob/io/base/bobskin.cpp @@ -8,126 +8,42 @@ #include "bobskin.h" #include <stdexcept> -bobskin::bobskin(PyObject* array, bob::io::base::array::ElementType eltype) { +bobskin::bobskin(PyObject* array, int dtype) { 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"); } - 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, bob::io::base::array::ElementType eltype) { - - m_type.set<npy_intp>(eltype, PyArray_NDIM((PyArrayObject*)array), - PyArray_DIMS((PyArrayObject*)array), - PyArray_STRIDES((PyArrayObject*)array)); + 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_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; -} +bobskin::bobskin(PyArrayObject* array, int dtype) { -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); + 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"); } - 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); - } + m_ptr = PyArray_DATA((PyArrayObject*)array); - return bob::io::base::array::t_unknown; } bobskin::bobskin(PyBlitzArrayObject* array) { - bob::io::base::array::ElementType eltype = num_to_type(array->type_num); - if (eltype == bob::io::base::array::t_unknown) { + if (!BobIoTypeinfo_SignedSetWithStrides(&m_type, array->type_num, + array->ndim, array->shape, array->stride)) { 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; } @@ -143,8 +59,8 @@ void bobskin::set(boost::shared_ptr<interface>) { throw std::runtime_error("error is already set"); } -void bobskin::set (const bob::io::base::array::typeinfo&) { - PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (const typeinfo&) implemented - DEBUG ME!"); +void bobskin::set (const BobIoTypeinfo&) { + PyErr_SetString(PyExc_NotImplementedError, "setting C++ bobskin with (const type-information&) 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 7e69132..a503562 100644 --- a/bob/io/base/bobskin.h +++ b/bob/io/base/bobskin.h @@ -10,13 +10,8 @@ #define PYTHON_BOB_IO_BOBSKIN_H #include <Python.h> - #include <bob.io.base/array.h> - -extern "C" { -#include <bob.blitz/capi.h> -} - +#include <bob.blitz/cppapi.h> /** * Wraps a PyArrayObject such that we can access it from bob::io @@ -28,12 +23,12 @@ class bobskin: public bob::io::base::array::interface { /** * @brief Builds a new skin from an array like object */ - bobskin(PyObject* array, bob::io::base::array::ElementType eltype); + bobskin(PyObject* array, int dtype); /** * @brief Builds a new skin from a numpy array object */ - bobskin(PyArrayObject* array, bob::io::base::array::ElementType eltype); + bobskin(PyArrayObject* array, int dtype); /** * @brief Builds a new skin around a blitz array object @@ -60,12 +55,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 bob::io::base::array::typeinfo& req); + virtual void set (const BobIoTypeinfo& req); /** * @brief Type information for this interface. */ - virtual const bob::io::base::array::typeinfo& type() const { return m_type; } + virtual const BobIoTypeinfo& type() const { return m_type; } /** * @brief Borrows a reference from the underlying memory. This means @@ -85,7 +80,7 @@ class bobskin: public bob::io::base::array::interface { private: //representation - bob::io::base::array::typeinfo m_type; ///< type information + BobIoTypeinfo 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 bfc3eb9..767fd20 100644 --- a/bob/io/base/codec.cpp +++ b/bob/io/base/codec.cpp @@ -7,8 +7,9 @@ #define BOB_IO_BASE_MODULE #include <bob.io.base/api.h> +#include "cpp/CodecRegistry.h" -int PyBobIoCodec_Register (const char* extension, const char* description, bob::io::base::file_factory_t factory) { +int PyBobIoCodec_Register (const char* extension, const char* description, BobIoFileFactory factory) { boost::shared_ptr<bob::io::base::CodecRegistry> instance = bob::io::base::CodecRegistry::instance(); diff --git a/bob/io/base/cpp/CodecRegistry.cpp b/bob/io/base/cpp/CodecRegistry.cpp index 821ecce..e3ce5fd 100644 --- a/bob/io/base/cpp/CodecRegistry.cpp +++ b/bob/io/base/cpp/CodecRegistry.cpp @@ -9,7 +9,7 @@ #include <bob.core/logging.h> -#include <bob.io.base/CodecRegistry.h> +#include "CodecRegistry.h" #include <vector> @@ -32,7 +32,7 @@ const char* bob::io::base::CodecRegistry::getDescription(const char* ext) { return it->second.c_str(); } -void bob::io::base::CodecRegistry::deregisterFactory(bob::io::base::file_factory_t factory) { +void bob::io::base::CodecRegistry::deregisterFactory(BobIoFileFactory factory) { std::vector<std::string> to_remove; for (auto it = s_extension2codec.begin(); it != s_extension2codec.end(); ++it) { @@ -47,7 +47,7 @@ void bob::io::base::CodecRegistry::deregisterFactory(bob::io::base::file_factory } void bob::io::base::CodecRegistry::registerExtension(const char* extension, - const char* description, bob::io::base::file_factory_t codec) { + const char* description, BobIoFileFactory codec) { auto it = s_extension2codec.find(extension); @@ -72,13 +72,13 @@ bool bob::io::base::CodecRegistry::isRegistered(const char* ext) { return (s_extension2codec.find(lower_extension) != s_extension2codec.end()); } -bob::io::base::file_factory_t bob::io::base::CodecRegistry::findByExtension (const char* ext) { +BobIoFileFactory 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, bob::io::base::file_factory_t >::iterator it = + std::map<std::string, BobIoFileFactory>::iterator it = s_extension2codec.find(lower_extension); if (it == s_extension2codec.end()) { @@ -91,7 +91,7 @@ bob::io::base::file_factory_t bob::io::base::CodecRegistry::findByExtension (con } -bob::io::base::file_factory_t bob::io::base::CodecRegistry::findByFilenameExtension +BobIoFileFactory bob::io::base::CodecRegistry::findByFilenameExtension (const char* filename) { return findByExtension(boost::filesystem::path(filename).extension().c_str()); diff --git a/bob/io/base/include/bob.io.base/CodecRegistry.h b/bob/io/base/cpp/CodecRegistry.h similarity index 86% rename from bob/io/base/include/bob.io.base/CodecRegistry.h rename to bob/io/base/cpp/CodecRegistry.h index 019bb57..aa9501e 100644 --- a/bob/io/base/include/bob.io.base/CodecRegistry.h +++ b/bob/io/base/cpp/CodecRegistry.h @@ -14,7 +14,7 @@ #include <string> #include <boost/shared_ptr.hpp> -#include <bob.io.base/File.h> +#include <bob.io.base/api.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, - file_factory_t factory); + BobIoFileFactory factory); - void deregisterFactory(file_factory_t factory); + void deregisterFactory(BobIoFileFactory factory); void deregisterExtension(const char* ext); /** @@ -58,8 +58,8 @@ namespace bob { namespace io { namespace base { */ const char* getDescription(const char* ext); - file_factory_t findByExtension(const char* ext); - file_factory_t findByFilenameExtension(const char* fn); + BobIoFileFactory findByExtension(const char* ext); + BobIoFileFactory 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, file_factory_t> s_extension2codec; + std::map<std::string, BobIoFileFactory> s_extension2codec; std::map<std::string, std::string> s_extension2description; bool s_ignore; ///< shall I ignore double-registrations? diff --git a/bob/io/base/cpp/HDF5File.cpp b/bob/io/base/cpp/HDF5File.cpp index 549069f..796e31f 100644 --- a/bob/io/base/cpp/HDF5File.cpp +++ b/bob/io/base/cpp/HDF5File.cpp @@ -7,9 +7,8 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#include <boost/format.hpp> - #include <bob.io.base/HDF5File.h> +#include <boost/format.hpp> static unsigned int getH5Access (bob::io::base::HDF5File::mode_t v) { switch(v) { diff --git a/bob/io/base/cpp/HDF5Types.cpp b/bob/io/base/cpp/HDF5Types.cpp index 6e79ae1..3f1f07d 100644 --- a/bob/io/base/cpp/HDF5Types.cpp +++ b/bob/io/base/cpp/HDF5Types.cpp @@ -415,7 +415,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 bob::io::base::array::typeinfo& value) const +bool bob::io::base::HDF5Type::compatible (const BobIoTypeinfo& value) const { return *this == HDF5Type(value); } @@ -619,9 +619,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::io::base::array::N_MAX_DIMENSIONS_ARRAY) {\ + if (N > BOB_BLITZ_MAXDIMS) {\ 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::io::base::array::N_MAX_DIMENSIONS_ARRAY; \ + m % N % BOB_BLITZ_MAXDIMS; \ throw std::runtime_error(m.str()); \ } \ } @@ -669,53 +669,56 @@ bob::io::base::HDF5Type::HDF5Type(bob::io::base::hdf5type type, const bob::io::b { } -static bob::io::base::hdf5type array_to_hdf5 (bob::io::base::array::ElementType eltype) { - switch(eltype) { - case bob::io::base::array::t_unknown: +static bob::io::base::hdf5type array_to_hdf5 (int dtype) { + switch(dtype) { + case NPY_NOTYPE: return bob::io::base::unsupported; - case bob::io::base::array::t_bool: + case NPY_BOOL: return bob::io::base::b; - case bob::io::base::array::t_int8: + case NPY_INT8: return bob::io::base::i8; - case bob::io::base::array::t_int16: + case NPY_INT16: return bob::io::base::i16; - case bob::io::base::array::t_int32: + case NPY_INT32: return bob::io::base::i32; - case bob::io::base::array::t_int64: + case NPY_INT64: return bob::io::base::i64; - case bob::io::base::array::t_uint8: + case NPY_UINT8: return bob::io::base::u8; - case bob::io::base::array::t_uint16: + case NPY_UINT16: return bob::io::base::u16; - case bob::io::base::array::t_uint32: + case NPY_UINT32: return bob::io::base::u32; - case bob::io::base::array::t_uint64: + case NPY_UINT64: return bob::io::base::u64; - case bob::io::base::array::t_float32: + case NPY_FLOAT32: return bob::io::base::f32; - case bob::io::base::array::t_float64: + case NPY_FLOAT64: return bob::io::base::f64; - case bob::io::base::array::t_float128: +# ifdef NPY_FLOAT128 + case NPY_FLOAT128: return bob::io::base::f128; - case bob::io::base::array::t_complex64: +# endif + case NPY_COMPLEX64: return bob::io::base::c64; - case bob::io::base::array::t_complex128: + case NPY_COMPLEX128: return bob::io::base::c128; - case bob::io::base::array::t_complex256: +# ifdef NPY_COMPLEX256 + case NPY_COMPLEX256: return bob::io::base::c256; +# endif } throw std::runtime_error("unsupported dtype <=> hdf5 type conversion -- FIXME"); } -bob::io::base::HDF5Type::HDF5Type(const bob::io::base::array::typeinfo& ti): +bob::io::base::HDF5Type::HDF5Type(const BobIoTypeinfo& ti): m_type(array_to_hdf5(ti.dtype)), m_shape(ti.nd, ti.shape) { } -bob::io::base::HDF5Type::HDF5Type(bob::io::base::array::ElementType eltype, - const HDF5Shape& extents): - m_type(array_to_hdf5(eltype)), +bob::io::base::HDF5Type::HDF5Type(int dtype, const HDF5Shape& extents): + m_type(array_to_hdf5(dtype)), m_shape(extents) { } @@ -765,56 +768,63 @@ std::string bob::io::base::HDF5Type::str() const { return retval.str(); } -bob::io::base::array::ElementType bob::io::base::HDF5Type::element_type() const { +int bob::io::base::HDF5Type::element_type() const { + switch (m_type) { case b: - return bob::io::base::array::t_bool; + return NPY_BOOL; case i8: - return bob::io::base::array::t_int8; + return NPY_INT8; case i16: - return bob::io::base::array::t_int16; + return NPY_INT16; case i32: - return bob::io::base::array::t_int32; + return NPY_INT32; case i64: - return bob::io::base::array::t_int64; + return NPY_INT64; case u8: - return bob::io::base::array::t_uint8; + return NPY_UINT8; case u16: - return bob::io::base::array::t_uint16; + return NPY_UINT16; case u32: - return bob::io::base::array::t_uint32; + return NPY_UINT32; case u64: - return bob::io::base::array::t_uint64; + return NPY_UINT64; case f32: - return bob::io::base::array::t_float32; + return NPY_FLOAT32; case f64: - return bob::io::base::array::t_float64; + return NPY_FLOAT64; +# ifdef NPY_FLOAT128 case f128: - return bob::io::base::array::t_float128; + return NPY_FLOAT128; +# endif case c64: - return bob::io::base::array::t_complex64; + return NPY_COMPLEX64; case c128: - return bob::io::base::array::t_complex128; + return NPY_COMPLEX128; +# ifdef NPY_COMPLEX256 case c256: - return bob::io::base::array::t_complex256; + return NPY_COMPLEX256; +# endif 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 bob::io::base::array::t_unknown; + + return NPY_NOTYPE; + } -void bob::io::base::HDF5Type::copy_to (bob::io::base::array::typeinfo& ti) const { +void bob::io::base::HDF5Type::copy_to (BobIoTypeinfo& ti) const { ti.dtype = element_type(); ti.nd = shape().n(); - if (ti.nd > (BOB_MAX_DIM+1)) { + if (ti.nd > (BOB_BLITZ_MAXDIMS+1)) { boost::format f("HDF5 type has more (%d) than the allowed maximum number of dimensions (%d)"); - f % ti.nd % (BOB_MAX_DIM+1); + f % ti.nd % (BOB_BLITZ_MAXDIMS+1); throw std::runtime_error(f.str()); } for (size_t i=0; i<ti.nd; ++i) ti.shape[i] = shape()[i]; - ti.update_strides(); + BobIoTypeinfo_UpdateStrides(&ti); } bob::io::base::HDF5Descriptor::HDF5Descriptor(const HDF5Type& type, size_t size, diff --git a/bob/io/base/cpp/TensorFile.cpp b/bob/io/base/cpp/TensorFile.cpp index 66b7216..d559ba6 100644 --- a/bob/io/base/cpp/TensorFile.cpp +++ b/bob/io/base/cpp/TensorFile.cpp @@ -7,11 +7,10 @@ * 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), @@ -25,7 +24,7 @@ bob::io::base::TensorFile::TensorFile(const std::string& filename, if(m_stream) { m_header.read(m_stream); - m_buffer.reset(new char[m_header.m_type.buffer_size()]); + m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); m_header_init = true; m_n_arrays_written = m_header.m_n_samples; @@ -40,7 +39,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[m_header.m_type.buffer_size()]); + m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); m_header_init = true; m_n_arrays_written = m_header.m_n_samples; m_stream.seekp(0, std::ios::end); @@ -53,7 +52,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[m_header.m_type.buffer_size()]); + m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); m_header_init = true; m_n_arrays_written = m_header.m_n_samples; @@ -71,7 +70,7 @@ bob::io::base::TensorFile::~TensorFile() { close(); } -void bob::io::base::TensorFile::peek(bob::io::base::array::typeinfo& info) const { +void bob::io::base::TensorFile::peek(BobIoTypeinfo& info) const { info = m_header.m_type; } @@ -83,7 +82,7 @@ void bob::io::base::TensorFile::close() { m_stream.close(); } -void bob::io::base::TensorFile::initHeader(const bob::io::base::array::typeinfo& info) { +void bob::io::base::TensorFile::initHeader(const BobIoTypeinfo& 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"); @@ -95,25 +94,25 @@ void bob::io::base::TensorFile::initHeader(const bob::io::base::array::typeinfo& m_header.write(m_stream); // Temporary buffer to help with data transposition... - m_buffer.reset(new char[m_header.m_type.buffer_size()]); + m_buffer.reset(new char[BobIoTypeinfo_BufferSize(&m_header.m_type)]); m_header_init = true; } void bob::io::base::TensorFile::write(const bob::io::base::array::interface& data) { - const bob::io::base::array::typeinfo& info = data.type(); + const BobIoTypeinfo& info = data.type(); if (!m_header_init) initHeader(info); else { //checks compatibility with previously written stuff - if (!m_header.m_type.is_compatible(info)) + if (!BobIoTypeinfo_IsCompatible(&m_header.m_type, &info)) throw std::runtime_error("buffer does not conform to expected type"); } - bob::io::base::row_to_col_order(data.ptr(), m_buffer.get(), info); + BobIoReorder_RowToCol(data.ptr(), m_buffer.get(), &info); - m_stream.write(static_cast<const char*>(m_buffer.get()), info.buffer_size()); + m_stream.write(static_cast<const char*>(m_buffer.get()), BobIoTypeinfo_BufferSize(&info)); // increment m_n_arrays_written and m_current_array ++m_current_array; @@ -125,12 +124,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(!buf.type().is_compatible(m_header.m_type)) buf.set(m_header.m_type); + if(!BobIoTypeinfo_IsCompatible(&buf.type(), &m_header.m_type)) buf.set(m_header.m_type); m_stream.read(reinterpret_cast<char*>(m_buffer.get()), - m_header.m_type.buffer_size()); + BobIoTypeinfo_BufferSize(&m_header.m_type)); - bob::io::base::col_to_row_order(m_buffer.get(), buf.ptr(), m_header.m_type); + BobIoReorder_ColToRow(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 35d42bf..2c342a4 100644 --- a/bob/io/base/cpp/TensorFile.h +++ b/bob/io/base/cpp/TensorFile.h @@ -10,12 +10,11 @@ #ifndef BOB_IO_TENSORFILE_H #define BOB_IO_TENSORFILE_H -#include <boost/format.hpp> -#include <stdexcept> +#include "TensorFileHeader.h" #include <bob.io.base/blitz_array.h> - -#include "TensorFileHeader.h" +#include <boost/format.hpp> +#include <stdexcept> namespace bob { namespace io { namespace base { @@ -94,9 +93,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 typeinfo + * Peeks the file and returns the currently set type information */ - void peek(bob::io::base::array::typeinfo& info) const; + void peek(BobIoTypeinfo& info) const; /** * Gets the number of samples/arrays written so far @@ -130,7 +129,7 @@ namespace bob { namespace io { namespace base { /** * Initializes the tensor file with the given type and shape. */ - inline void initTensorFile(const bob::io::base::array::typeinfo& info) { + inline void initTensorFile(const BobIoTypeinfo& info) { initHeader(info); } @@ -161,7 +160,7 @@ namespace bob { namespace io { namespace base { * Initializes the header of the (output) stream with the given type * and shape */ - void initHeader(const bob::io::base::array::typeinfo& info); + void initHeader(const BobIoTypeinfo& info); public: @@ -186,7 +185,7 @@ namespace bob { namespace io { namespace base { * multiarrays saved have the same dimensions. */ template <typename T, int D> inline blitz::Array<T,D> read() { - bob::io::base::array::typeinfo info; + BobIoTypeinfo info; peek(info); bob::io::base::array::blitz_array buf(info); read(buf); @@ -195,7 +194,7 @@ namespace bob { namespace io { namespace base { template <typename T, int D> inline blitz::Array<T,D> read(size_t index) { - bob::io::base::array::typeinfo info; + BobIoTypeinfo 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 fb96a13..8d8dfee 100644 --- a/bob/io/base/cpp/TensorFileHeader.cpp +++ b/bob/io/base/cpp/TensorFileHeader.cpp @@ -7,9 +7,10 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#include <boost/format.hpp> - +#define BOB_IO_BASE_MODULE #include "TensorFileHeader.h" +#include <bob.blitz/capi.h> +#include <boost/format.hpp> bob::io::base::detail::TensorFileHeader::TensorFileHeader() : m_tensor_type(bob::io::base::Char), @@ -31,28 +32,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; - int nd; - str.read(reinterpret_cast<char*>(&nd), sizeof(int)); + str.read(reinterpret_cast<char*>(&val), sizeof(int)); + size_t nd = (size_t)val; - int shape[BOB_MAX_DIM]; + size_t shape[BOB_BLITZ_MAXDIMS]; - 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; - m_type.set_shape(nd, shape); + BobIoTypeinfo_Set(&m_type, m_type.dtype, nd, shape); header_ok(); } @@ -64,19 +65,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() @@ -100,7 +101,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 % m_type.str(); + m % BobIoTypeinfo_Str(&m_type); throw std::runtime_error(m.str()); } @@ -130,43 +131,43 @@ void bob::io::base::detail::TensorFileHeader::update() } -bob::io::base::TensorType bob::io::base::arrayTypeToTensorType(bob::io::base::array::ElementType eltype) +bob::io::base::TensorType bob::io::base::arrayTypeToTensorType(int dtype) { - switch(eltype) + switch(dtype) { - case bob::io::base::array::t_int8: + case NPY_INT8: return bob::io::base::Char; - case bob::io::base::array::t_int16: + case NPY_INT16: return bob::io::base::Short; - case bob::io::base::array::t_int32: + case NPY_INT32: return bob::io::base::Int; - case bob::io::base::array::t_int64: + case NPY_INT64: return bob::io::base::Long; - case bob::io::base::array::t_float32: + case NPY_FLOAT32: return bob::io::base::Float; - case bob::io::base::array::t_float64: + case NPY_FLOAT64: return bob::io::base::Double; default: throw std::runtime_error("unsupported data type found while converting array type to tensor type"); } } -bob::io::base::array::ElementType bob::io::base::tensorTypeToArrayType(bob::io::base::TensorType tensortype) +int bob::io::base::tensorTypeToArrayType(bob::io::base::TensorType tensortype) { switch(tensortype) { case bob::io::base::Char: - return bob::io::base::array::t_int8; + return NPY_INT8; case bob::io::base::Short: - return bob::io::base::array::t_int16; + return NPY_INT16; case bob::io::base::Int: - return bob::io::base::array::t_int32; + return NPY_INT32; case bob::io::base::Long: - return bob::io::base::array::t_int64; + return NPY_INT64; case bob::io::base::Float: - return bob::io::base::array::t_float32; + return NPY_FLOAT32; case bob::io::base::Double: - return bob::io::base::array::t_float64; + return NPY_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 7e852b8..7f3275d 100644 --- a/bob/io/base/cpp/TensorFileHeader.h +++ b/bob/io/base/cpp/TensorFileHeader.h @@ -11,10 +11,9 @@ #ifndef BOB_IO_BASE_TENSORFILEHEADER_H #define BOB_IO_BASE_TENSORFILEHEADER_H -#include <fstream> +#include <bob.io.base/api.h> #include <blitz/array.h> - -#include <bob.io.base/array.h> +#include <fstream> namespace bob { namespace io { namespace base { @@ -29,8 +28,8 @@ namespace bob { namespace io { namespace base { Double }; - TensorType arrayTypeToTensorType(bob::io::base::array::ElementType eltype); - bob::io::base::array::ElementType tensorTypeToArrayType(bob::io::base::TensorType tensortype); + TensorType arrayTypeToTensorType(int dtype); + int tensorTypeToArrayType(bob::io::base::TensorType tensortype); namespace detail { /** @@ -85,7 +84,7 @@ namespace bob { namespace io { namespace base { //representation TensorType m_tensor_type; ///< array element type - bob::io::base::array::typeinfo m_type; ///< the type information + BobIoTypeinfo 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 deleted file mode 100644 index 2ffc94d..0000000 --- a/bob/io/base/cpp/array.cpp +++ /dev/null @@ -1,134 +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 - */ - -#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 deleted file mode 100644 index d42368e..0000000 --- a/bob/io/base/cpp/array_type.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @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 2bc723a..0fd2837 100644 --- a/bob/io/base/cpp/blitz_array.cpp +++ b/bob/io/base/cpp/blitz_array.cpp @@ -27,21 +27,26 @@ bob::io::base::array::blitz_array::blitz_array(const interface& other) { set(other); } -bob::io::base::array::blitz_array::blitz_array(const typeinfo& info) { +bob::io::base::array::blitz_array::blitz_array(const BobIoTypeinfo& info) { set(info); } -bob::io::base::array::blitz_array::blitz_array(void* data, const typeinfo& info): - m_type(info), +bob::io::base::array::blitz_array::blitz_array(void* data, const BobIoTypeinfo& info): + m_type(), 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) { - m_type = other->m_type; + if (!BobIoTypeinfo_Copy(&m_type, &other->m_type)) { + throw std::runtime_error("error already set"); + } m_ptr = other->m_ptr; m_is_blitz = other->m_is_blitz; m_data = other->m_data; @@ -49,11 +54,13 @@ 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(), m_type.buffer_size()); + memcpy(m_ptr, other.ptr(), BobIoTypeinfo_BufferSize(&m_type)); } void bob::io::base::array::blitz_array::set(boost::shared_ptr<interface> other) { - m_type = other->type(); + if (!BobIoTypeinfo_Copy(&m_type, &other->type())) { + throw std::runtime_error("error already set"); + } m_ptr = other->ptr(); m_is_blitz = false; m_data = other; @@ -105,58 +112,66 @@ 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 bob::io::base::array::typeinfo& req) { - if (m_type.is_compatible(req)) return; ///< double-check requirement first! +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"); + } - //ok, have to go through reallocation - m_type = req; m_is_blitz = true; + switch (m_type.dtype) { - case bob::io::base::array::t_bool: + case NPY_BOOL: m_data = make_array<bool>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_int8: + case NPY_INT8: m_data = make_array<int8_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_int16: + case NPY_INT16: m_data = make_array<int16_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_int32: + case NPY_INT32: m_data = make_array<int32_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_int64: + case NPY_INT64: m_data = make_array<int64_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_uint8: + case NPY_UINT8: m_data = make_array<uint8_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_uint16: + case NPY_UINT16: m_data = make_array<uint16_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_uint32: + case NPY_UINT32: m_data = make_array<uint32_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_uint64: + case NPY_UINT64: m_data = make_array<uint64_t>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_float32: + case NPY_FLOAT32: m_data = make_array<float>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_float64: + case NPY_FLOAT64: m_data = make_array<double>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_float128: +# ifdef NPY_FLOAT128 + case NPY_FLOAT128: m_data = make_array<long double>(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_complex64: +# endif + case NPY_COMPLEX64: m_data = make_array<std::complex<float> >(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_complex128: + case NPY_COMPLEX128: m_data = make_array<std::complex<double> >(req.nd, req.shape, m_ptr); return; - case bob::io::base::array::t_complex256: +# ifdef NPY_COMPLEX256 + case NPY_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 deleted file mode 100644 index cda5ab3..0000000 --- a/bob/io/base/cpp/reorder.cpp +++ /dev/null @@ -1,288 +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 - */ - -#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/cpp/CSVFile.cpp b/bob/io/base/csv.cpp similarity index 73% rename from bob/io/base/cpp/CSVFile.cpp rename to bob/io/base/csv.cpp index 1200523..7932ad8 100644 --- a/bob/io/base/cpp/CSVFile.cpp +++ b/bob/io/base/csv.cpp @@ -8,6 +8,10 @@ * 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> @@ -20,8 +24,6 @@ #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 { @@ -62,16 +64,16 @@ class CSVFile: public bob::io::base::File { return; } - m_arrayset_type.dtype = bob::io::base::array::t_float64; + m_arrayset_type.dtype = NPY_FLOAT64; m_arrayset_type.nd = 1; m_arrayset_type.shape[0] = entries; - m_arrayset_type.update_strides(); + BobIoTypeinfo_UpdateStrides(&m_arrayset_type); 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; - m_array_type.update_strides(); + BobIoTypeinfo_UpdateStrides(&m_array_type); } CSVFile(const char* path, char mode): @@ -116,11 +118,11 @@ class CSVFile: public bob::io::base::File { return m_filename.c_str(); } - virtual const bob::io::base::array::typeinfo& type() const { + virtual const BobIoTypeinfo& type() const { return m_arrayset_type; } - virtual const bob::io::base::array::typeinfo& type_all() const { + virtual const BobIoTypeinfo& type_all() const { return m_array_type; } @@ -136,7 +138,7 @@ class CSVFile: public bob::io::base::File { if (m_newfile) throw std::runtime_error("uninitialized CSV file cannot be read"); - if (!buffer.type().is_compatible(m_array_type)) buffer.set(m_array_type); + if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_array_type)) buffer.set(m_array_type); //read contents std::string line; @@ -156,7 +158,7 @@ class CSVFile: public bob::io::base::File { if (m_newfile) throw std::runtime_error("uninitialized CSV file cannot be read"); - if (!buffer.type().is_compatible(m_arrayset_type)) + if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_arrayset_type)) buffer.set(m_arrayset_type); if (index >= m_pos.size()) { @@ -184,12 +186,12 @@ class CSVFile: public bob::io::base::File { virtual size_t append (const bob::io::base::array::interface& buffer) { - const bob::io::base::array::typeinfo& type = buffer.type(); + const BobIoTypeinfo& type = buffer.type(); if (m_newfile) { - if (type.nd != 1 || type.dtype != bob::io::base::array::t_float64) { + if (type.nd != 1 || type.dtype != NPY_FLOAT64) { boost::format m("cannot append %s to file '%s' - CSV files only accept 1D double precision float arrays"); - m % type.str() % m_filename; + m % BobIoTypeinfo_Str(&type) % m_filename; throw std::runtime_error(m.str()); } m_pos.clear(); @@ -201,9 +203,9 @@ class CSVFile: public bob::io::base::File { else { //check compatibility - if (!m_arrayset_type.is_compatible(buffer.type())) { + if (!BobIoTypeinfo_IsCompatible(&m_arrayset_type, &buffer.type())) { boost::format m("CSV file '%s' only accepts arrays of type %s"); - m % m_filename % m_arrayset_type.str(); + m % m_filename % BobIoTypeinfo_Str(&m_arrayset_type); throw std::runtime_error(m.str()); } @@ -215,19 +217,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(); - m_array_type.update_strides(); + BobIoTypeinfo_UpdateStrides(&m_array_type); return (m_pos.size()-1); } virtual void write (const bob::io::base::array::interface& buffer) { - const bob::io::base::array::typeinfo& type = buffer.type(); + const BobIoTypeinfo& type = buffer.type(); if (m_newfile) { - if (type.nd != 2 || type.dtype != bob::io::base::array::t_float64) { + if (type.nd != 2 || type.dtype != NPY_FLOAT64) { boost::format m("cannot write %s to file '%s' - CSV files only accept a single 2D double precision float array as input"); - m % type.str() % m_filename; + m % BobIoTypeinfo_Str(&type) % m_filename; throw std::runtime_error(m.str()); } const double* p = static_cast<const double*>(buffer.ptr()); @@ -241,7 +243,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]; - m_arrayset_type.update_strides(); + BobIoTypeinfo_UpdateStrides(&m_arrayset_type); m_array_type = type; m_newfile = false; return; @@ -256,8 +258,8 @@ class CSVFile: public bob::io::base::File { std::fstream m_file; std::string m_filename; bool m_newfile; - bob::io::base::array::typeinfo m_array_type; - bob::io::base::array::typeinfo m_arrayset_type; + BobIoTypeinfo m_array_type; + BobIoTypeinfo m_arrayset_type; std::vector<std::streampos> m_pos; ///< dictionary of line starts static std::string s_codecname; @@ -267,48 +269,10 @@ class CSVFile: public bob::io::base::File { std::string CSVFile::s_codecname = "bob.csv"; /** - * 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. + * Registration method: use an unique name. Copy the definition to "plugin.h" + * and then call it on "main.cpp" to register the codec. */ -static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { +boost::shared_ptr<bob::io::base::File> + make_csv_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/file.cpp b/bob/io/base/file.cpp index 58d760c..321bcad 100644 --- a/bob/io/base/file.cpp +++ b/bob/io/base/file.cpp @@ -13,9 +13,6 @@ #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); @@ -121,10 +118,10 @@ static int PyBobIoFile_Init(PyBobIoFileObject* self, PyObject *args, PyObject* k try { if (pretend_extension) { - self->f = bob::io::base::open(c_filename, mode, pretend_extension); + self->f = BobIo_OpenWithExtension(c_filename, mode, pretend_extension); } else { - self->f = bob::io::base::open(c_filename, mode); + self->f = BobIo_Open(c_filename, mode); } } catch (std::exception& e) { @@ -193,51 +190,6 @@ 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 @@ -247,15 +199,14 @@ static PyObject* PyBobIoFile_GetIndex (PyBobIoFileObject* self, Py_ssize_t i) { return 0; } - const bob::io::base::array::typeinfo& info = self->f->type(); + const BobIoTypeinfo& info = self->f->type(); npy_intp shape[NPY_MAXDIMS]; for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k]; - int type_num = PyBobIo_AsTypenum(info.dtype); - if (type_num == NPY_NOTYPE) return 0; ///< failure + if (info.dtype == NPY_NOTYPE) return 0; ///< failure - PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num); + PyObject* retval = PyArray_SimpleNew(info.nd, shape, info.dtype); if (!retval) return 0; auto retval_ = make_safe(retval); @@ -288,18 +239,17 @@ static PyObject* PyBobIoFile_GetSlice (PyBobIoFileObject* self, PySliceObject* s self->f->size(), &start, &stop, &step, &slicelength) < 0) return 0; //creates the return array - const bob::io::base::array::typeinfo& info = self->f->type(); + const BobIoTypeinfo& info = self->f->type(); - int type_num = PyBobIo_AsTypenum(info.dtype); - if (type_num == NPY_NOTYPE) return 0; ///< failure + if (info.dtype == NPY_NOTYPE) return 0; ///< failure - if (slicelength <= 0) return PyArray_SimpleNew(0, 0, type_num); + if (slicelength <= 0) return PyArray_SimpleNew(0, 0, info.dtype); 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, type_num); + PyObject* retval = PyArray_SimpleNew(info.nd+1, shape, info.dtype); if (!retval) return 0; auto retval_ = make_safe(retval); @@ -383,15 +333,14 @@ static PyObject* PyBobIoFile_Read(PyBobIoFileObject* self, PyObject *args, PyObj // reads the whole file in a single shot - const bob::io::base::array::typeinfo& info = self->f->type_all(); + const BobIoTypeinfo& info = self->f->type_all(); npy_intp shape[NPY_MAXDIMS]; for (size_t k=0; k<info.nd; ++k) shape[k] = info.shape[k]; - int type_num = PyBobIo_AsTypenum(info.dtype); - if (type_num == NPY_NOTYPE) return 0; ///< failure + if (info.dtype == NPY_NOTYPE) return 0; ///< failure - PyObject* retval = PyArray_SimpleNew(info.nd, shape, type_num); + PyObject* retval = PyArray_SimpleNew(info.nd, shape, info.dtype); if (!retval) return 0; auto retval_ = make_safe(retval); @@ -544,13 +493,12 @@ Returns the current position of the newly written array.\n\ " ); -PyObject* PyBobIo_TypeInfoAsTuple (const bob::io::base::array::typeinfo& ti) { +PyObject* PyBobIo_TypeInfoAsTuple (const BobIoTypeinfo& ti) { - int type_num = PyBobIo_AsTypenum(ti.dtype); - if (type_num == NPY_NOTYPE) return 0; + if (ti.dtype == NPY_NOTYPE) return 0; PyObject* retval = Py_BuildValue("NNN", - reinterpret_cast<PyObject*>(PyArray_DescrFromType(type_num)), + reinterpret_cast<PyObject*>(PyArray_DescrFromType(ti.dtype)), PyTuple_New(ti.nd), //shape PyTuple_New(ti.nd) //strides ); @@ -576,7 +524,7 @@ static PyObject* PyBobIoFile_Describe(PyBobIoFileObject* self, PyObject *args, P PyObject* all = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &all)) return 0; - const bob::io::base::array::typeinfo* info = 0; + const BobIoTypeinfo* info = 0; if (all && PyObject_IsTrue(all)) info = &self->f->type_all(); else info = &self->f->type(); diff --git a/bob/io/base/hdf5.cpp b/bob/io/base/hdf5.cpp index dcb4249..1b56fa6 100644 --- a/bob/io/base/hdf5.cpp +++ b/bob/io/base/hdf5.cpp @@ -7,6 +7,7 @@ #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/HDF5ArrayFile.cpp b/bob/io/base/hdf5plugin.cpp similarity index 70% rename from bob/io/base/cpp/HDF5ArrayFile.cpp rename to bob/io/base/hdf5plugin.cpp index 8a9aa97..5982adf 100644 --- a/bob/io/base/cpp/HDF5ArrayFile.cpp +++ b/bob/io/base/hdf5plugin.cpp @@ -7,13 +7,15 @@ * 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 */ @@ -65,11 +67,11 @@ class HDF5ArrayFile: public bob::io::base::File { return m_filename.c_str(); } - virtual const bob::io::base::array::typeinfo& type_all () const { + virtual const BobIoTypeinfo& type_all () const { return m_type_array; } - virtual const bob::io::base::array::typeinfo& type () const { + virtual const BobIoTypeinfo& type () const { return m_type_arrayset; } @@ -89,7 +91,7 @@ class HDF5ArrayFile: public bob::io::base::File { throw std::runtime_error(f.str()); } - if(!buffer.type().is_compatible(m_type_array)) buffer.set(m_type_array); + if(!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_type_array)) buffer.set(m_type_array); m_file.read_buffer(m_path, 0, buffer.type(), buffer.ptr()); } @@ -102,7 +104,7 @@ class HDF5ArrayFile: public bob::io::base::File { throw std::runtime_error(f.str()); } - if(!buffer.type().is_compatible(m_type_arrayset)) buffer.set(m_type_arrayset); + if(!BobIoTypeinfo_IsCompatible(&buffer.type(), &m_type_arrayset)) buffer.set(m_type_arrayset); m_file.read_buffer(m_path, index, buffer.type(), buffer.ptr()); } @@ -152,8 +154,8 @@ class HDF5ArrayFile: public bob::io::base::File { bob::io::base::HDF5File m_file; std::string m_filename; - 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 + BobIoTypeinfo m_type_array; ///< type for reading all data at once + BobIoTypeinfo 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 @@ -165,32 +167,11 @@ class HDF5ArrayFile: public bob::io::base::File { std::string HDF5ArrayFile::s_codecname = "bob.hdf5"; /** - * 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. + * Registration method: use an unique name. Copy the definition to "plugin.h" + * and then call it on "main.cpp" to register the codec. */ -static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { +boost::shared_ptr<bob::io::base::File> + make_hdf5_file (const char* path, char mode) { bob::io::base::HDF5File::mode_t h5mode; if (mode == 'r') h5mode = bob::io::base::HDF5File::in; @@ -201,22 +182,3 @@ static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char 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/include/bob.io.base/File.h b/bob/io/base/include/bob.io.base/File.h index bd58ff5..1b71c93 100644 --- a/bob/io/base/include/bob.io.base/File.h +++ b/bob/io/base/include/bob.io.base/File.h @@ -11,9 +11,8 @@ #ifndef BOB_IO_BASE_FILE_H #define BOB_IO_BASE_FILE_H -#include <boost/shared_ptr.hpp> -#include <bob.io.base/array.h> #include <bob.io.base/blitz_array.h> +#include <boost/shared_ptr.hpp> namespace bob { namespace io { namespace base { @@ -33,16 +32,16 @@ namespace bob { namespace io { namespace base { virtual const char* filename() const =0; /** - * The typeinfo of data within this file, if it is supposed to be read as - * as a sequence of arrays + * The type information of data within this file, if it is supposed to be + * read as as a sequence of arrays */ - virtual const bob::io::base::array::typeinfo& type() const =0; + virtual const BobIoTypeinfo& type() const =0; /** - * The typeinfo of data within this file, if it is supposed to be read as - * a single array. + * The type information of data within this file, if it is supposed to be + * read as a single array. */ - virtual const bob::io::base::array::typeinfo& type_all() const =0; + virtual const BobIoTypeinfo& type_all() const =0; /** * The number of arrays available in this file, if it is supposed to be @@ -157,28 +156,6 @@ 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/HDF5File.h b/bob/io/base/include/bob.io.base/HDF5File.h index 31c6594..4c80604 100644 --- a/bob/io/base/include/bob.io.base/HDF5File.h +++ b/bob/io/base/include/bob.io.base/HDF5File.h @@ -12,9 +12,8 @@ #ifndef BOB_IO_BASE_HDF5FILE_H #define BOB_IO_BASE_HDF5FILE_H -#include <boost/format.hpp> - #include <bob.io.base/HDF5Utils.h> +#include <boost/format.hpp> 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 9dcd7a6..9071403 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 <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> +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <hdf5.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 d19eab3..81e1b6b 100644 --- a/bob/io/base/include/bob.io.base/HDF5Types.h +++ b/bob/io/base/include/bob.io.base/HDF5Types.h @@ -340,14 +340,14 @@ namespace bob { namespace io { namespace base { HDF5Type(hdf5type type); /** - * Creates a HDF5Type from an bob::io::base::array::typeinfo + * Creates a HDF5Type from an BobIoTypeinfo */ - HDF5Type(const bob::io::base::array::typeinfo& ti); + HDF5Type(const BobIoTypeinfo& ti); /** * Creates a HDF5Type from a type enumeration and an explicit shape */ - HDF5Type(bob::io::base::array::ElementType eltype, const HDF5Shape& extents); + HDF5Type(int dtype, 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 bob::io::base::array::typeinfo& value) const; + bool compatible (const BobIoTypeinfo& 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 */ - bob::io::base::array::ElementType element_type() const; + int element_type() const; /** - * Copies this type information to a stock bob::io::base::array::typeinfo + * Copies this type information to a stock BobIoTypeinfo */ - void copy_to (bob::io::base::array::typeinfo& ti) const; + void copy_to (BobIoTypeinfo& 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 670430e..d380dfd 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 001e8d4..9f6551b 100644 --- a/bob/io/base/include/bob.io.base/api.h +++ b/bob/io/base/include/bob.io.base/api.h @@ -13,13 +13,11 @@ #define BOB_IO_BASE_PREFIX "bob.io.base" #define BOB_IO_BASE_FULL_NAME "bob.io.base._library" -#include <Python.h> +/* 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> /******************* @@ -29,12 +27,37 @@ /* 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_AsTypenum_NUM, - PyBobIo_TypeInfoAsTuple_NUM, + PyBobIo_TypeinfoAsTuple_NUM, PyBobIo_FilenameConverter_NUM, // HDF5 bindings PyBobIoHDF5File_Type_NUM, @@ -55,11 +78,88 @@ 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*, const BobIoTypeinfo*) + +#define BobIoReorder_ColToRowComplex_RET int +#define BobIoReorder_ColToRowComplex_PROTO (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 @@ -81,15 +181,28 @@ 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_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_TypeinfoAsTuple_RET PyObject* +#define PyBobIo_TypeinfoAsTuple_PROTO (const BobIoTypeinfo& ti) #define PyBobIo_FilenameConverter_RET int #define PyBobIo_FilenameConverter_PROTO (PyObject* o, PyObject** b) @@ -98,6 +211,7 @@ typedef struct { * HDF5 bindings * *****************/ +namespace bob { namespace io { namespace base { class HDF5File; }}} typedef struct { PyObject_HEAD @@ -118,8 +232,30 @@ 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, bob::io::base::file_factory_t factory) +#define PyBobIoCodec_Register_PROTO (const char* extension, const char* description, BobIoFileFactory factory) #define PyBobIoCodec_Deregister_RET int #define PyBobIoCodec_Deregister_PROTO (const char* extension) @@ -140,6 +276,52 @@ typedef struct { 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 * **********************************/ @@ -147,19 +329,29 @@ typedef struct { 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_AsTypenum_RET PyBobIo_AsTypenum PyBobIo_AsTypenum_PROTO; - - PyBobIo_TypeInfoAsTuple_RET PyBobIo_TypeInfoAsTuple PyBobIo_TypeInfoAsTuple_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; @@ -167,17 +359,17 @@ typedef struct { 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 @@ -199,6 +391,52 @@ typedef struct { # 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 * *****************************/ @@ -206,13 +444,23 @@ typedef struct { # 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_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_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 570c09f..5bbe268 100644 --- a/bob/io/base/include/bob.io.base/array.h +++ b/bob/io/base/include/bob.io.base/array.h @@ -11,14 +11,15 @@ #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 @@ -29,170 +30,6 @@ */ 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 @@ -225,12 +62,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 typeinfo& req) =0; + virtual void set (const BobIoTypeinfo& req) =0; /** * @brief Type information for this interface. */ - virtual const typeinfo& type() const =0; + virtual const BobIoTypeinfo& 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 deleted file mode 100644 index 89eb1e2..0000000 --- a/bob/io/base/include/bob.io.base/array_type.h +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @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 8fdfa77..2ccf320 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 typeinfo object + * @brief Fills in shape and stride starting from a type information object */ - template <int N> void set_shape_and_stride(const typeinfo& info, + template <int N> void set_shape_and_stride(const BobIoTypeinfo& 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 typeinfo& type = buf.type(); + const BobIoTypeinfo& type = buf.type(); if (!buf.ptr()) throw std::runtime_error("empty buffer"); - if (type.dtype != bob::io::base::array::getElementType<T>()) { + if (type.dtype != PyBlitzArrayCxx_CToTypenum<T>()) { boost::format m("cannot efficiently retrieve blitz::Array<%s,%d> from buffer of type '%s'"); - m % stringize<T>() % N % type.str(); + m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&type); 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 % stringize<T>() % N % type.str(); + m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&type); throw std::runtime_error(m.str()); } @@ -80,45 +80,49 @@ namespace bob { namespace io { namespace base { namespace array { template <typename T, int N> blitz::Array<T,N> cast(const interface& buf) { - const typeinfo& type = buf.type(); + const BobIoTypeinfo& type = buf.type(); if (type.nd != N) { boost::format m("cannot cast blitz::Array<%s,%d> from buffer of type '%s'"); - m % stringize<T>() % N % type.str(); + m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&type); throw std::runtime_error(m.str()); } switch (type.dtype) { - case bob::io::base::array::t_bool: + case NPY_BOOL: return bob::core::array::cast<T>(wrap<bool,N>(buf)); - case bob::io::base::array::t_int8: + case NPY_INT8: return bob::core::array::cast<T>(wrap<int8_t,N>(buf)); - case bob::io::base::array::t_int16: + case NPY_INT16: return bob::core::array::cast<T>(wrap<int16_t,N>(buf)); - case bob::io::base::array::t_int32: + case NPY_INT32: return bob::core::array::cast<T>(wrap<int32_t,N>(buf)); - case bob::io::base::array::t_int64: + case NPY_INT64: return bob::core::array::cast<T>(wrap<int64_t,N>(buf)); - case bob::io::base::array::t_uint8: + case NPY_UINT8: return bob::core::array::cast<T>(wrap<uint8_t,N>(buf)); - case bob::io::base::array::t_uint16: + case NPY_UINT16: return bob::core::array::cast<T>(wrap<uint16_t,N>(buf)); - case bob::io::base::array::t_uint32: + case NPY_UINT32: return bob::core::array::cast<T>(wrap<uint32_t,N>(buf)); - case bob::io::base::array::t_uint64: + case NPY_UINT64: return bob::core::array::cast<T>(wrap<uint64_t,N>(buf)); - case bob::io::base::array::t_float32: + case NPY_FLOAT32: return bob::core::array::cast<T>(wrap<float,N>(buf)); - case bob::io::base::array::t_float64: + case NPY_FLOAT64: return bob::core::array::cast<T>(wrap<double,N>(buf)); - case bob::io::base::array::t_float128: +# ifdef NPY_FLOAT128 + case NPY_FLOAT128: return bob::core::array::cast<T>(wrap<long double,N>(buf)); - case bob::io::base::array::t_complex64: +# endif + case NPY_COMPLEX64: return bob::core::array::cast<T>(wrap<std::complex<float>,N>(buf)); - case bob::io::base::array::t_complex128: + case NPY_COMPLEX128: return bob::core::array::cast<T>(wrap<std::complex<double>,N>(buf)); - case bob::io::base::array::t_complex256: +# ifdef NPY_COMPLEX256 + case NPY_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 9927e00..052c30d 100644 --- a/bob/io/base/include/bob.io.base/blitz_array.h +++ b/bob/io/base/include/bob.io.base/blitz_array.h @@ -22,7 +22,6 @@ #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 { @@ -56,13 +55,13 @@ namespace bob { namespace io { namespace base { namespace array { /** * @brief Starts with an uninitialized, pre-allocated array. */ - blitz_array(const typeinfo& info); + blitz_array(const BobIoTypeinfo& 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 typeinfo& info); + blitz_array(void* data, const BobIoTypeinfo& info); /** * @brief Destroyes me @@ -83,7 +82,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 typeinfo& req); + virtual void set (const BobIoTypeinfo& req); /** * @brief Refers to the data of another blitz array. @@ -91,9 +90,9 @@ namespace bob { namespace io { namespace base { namespace array { void set(boost::shared_ptr<blitz_array> other); /** - * @brief Element type + * @brief type information */ - virtual const typeinfo& type() const { return m_type; } + virtual const BobIoTypeinfo& type() const { return m_type; } /** * @brief Borrows a reference from the underlying memory. This means @@ -152,16 +151,20 @@ namespace bob { namespace io { namespace base { namespace array { template <typename T, int N> void set(boost::shared_ptr<blitz::Array<T,N> > data) { - if (getElementType<T>() == t_unknown) + if (PyBlitzArrayCxx_CToTypenum<T>() == NPY_NOTYPE) throw std::runtime_error("unsupported element type on blitz::Array<>"); - if (N > BOB_MAX_DIM) + if (N > BOB_BLITZ_MAXDIMS) 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.set(data); - + 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_data = data; m_ptr = reinterpret_cast<void*>(data->data()); m_is_blitz = true; @@ -209,15 +212,15 @@ namespace bob { namespace io { namespace base { namespace array { if (!m_data) throw std::runtime_error("empty blitz array"); - if (m_type.dtype != getElementType<T>()) { + if (m_type.dtype != PyBlitzArrayCxx_CToTypenum<T>()) { boost::format m("cannot efficiently retrieve blitz::Array<%s,%d> from buffer of type '%s'"); - m % stringize<T>() % N % m_type.str(); + m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&m_type); 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 % stringize<T>() % N % m_type.str(); + m % PyBlitzArray_TypenumAsString(PyBlitzArrayCxx_CToTypenum<T>()) % N % BobIoTypeinfo_Str(&m_type); throw std::runtime_error(m.str()); } @@ -249,7 +252,7 @@ namespace bob { namespace io { namespace base { namespace array { private: //representation - typeinfo m_type; ///< type information + BobIoTypeinfo 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 deleted file mode 100644 index 09ebf50..0000000 --- a/bob/io/base/include/bob.io.base/reorder.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @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 index c42b1fa..04931e0 100644 --- a/bob/io/base/include/bob.io.base/utils.h +++ b/bob/io/base/include/bob.io.base/utils.h @@ -8,9 +8,8 @@ #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> +#include <boost/shared_ptr.hpp> namespace bob { namespace io { namespace base { @@ -42,22 +41,22 @@ namespace bob { namespace io { namespace base { const char* pretend_extension); /** - * Peeks the file and returns the typeinfo for reading individual frames (or - * samples) from the file. + * Peeks the file and returns the type information 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); + BobIoTypeinfo peek (const char* filename); /** - * Peeks the file and returns the typeinfo for reading the whole contents in - * a single shot. + * Peeks the file and returns the type information 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); + BobIoTypeinfo peek_all (const char* filename); /** * Opens for reading and load all contents diff --git a/bob/io/base/main.cpp b/bob/io/base/main.cpp index 27f18a0..50eaabd 100644 --- a/bob/io/base/main.cpp +++ b/bob/io/base/main.cpp @@ -15,6 +15,9 @@ #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 * reference**. @@ -121,6 +124,52 @@ 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 * **********************************/ @@ -129,13 +178,23 @@ 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_AsTypenum_NUM] = (void *)PyBobIo_AsTypenum; - - PyBobIo_API[PyBobIo_TypeInfoAsTuple_NUM] = (void *)PyBobIo_TypeInfoAsTuple; + PyBobIo_API[PyBobIo_TypeinfoAsTuple_NUM] = (void *)PyBobIo_TypeinfoAsTuple; PyBobIo_API[PyBobIo_FilenameConverter_NUM] = (void *)PyBobIo_FilenameConverter; @@ -149,9 +208,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; @@ -192,6 +251,41 @@ 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 new file mode 100644 index 0000000..735ff37 --- /dev/null +++ b/bob/io/base/plugin.h @@ -0,0 +1,39 @@ +/** + * @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 new file mode 100644 index 0000000..b07ac50 --- /dev/null +++ b/bob/io/base/reorder.cpp @@ -0,0 +1,317 @@ +/** + * @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/cpp/TensorArrayFile.cpp b/bob/io/base/tensor.cpp similarity index 56% rename from bob/io/base/cpp/TensorArrayFile.cpp rename to bob/io/base/tensor.cpp index d0cb72d..8d51dbc 100644 --- a/bob/io/base/cpp/TensorArrayFile.cpp +++ b/bob/io/base/tensor.cpp @@ -7,8 +7,11 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#include "TensorFile.h" -#include <bob.io.base/CodecRegistry.h> +#define BOB_IO_BASE_MODULE +#include <bob.io.base/api.h> +#include <bob.io.base/File.h> + +#include "cpp/TensorFile.h" class TensorArrayFile: public bob::io::base::File { @@ -26,11 +29,11 @@ class TensorArrayFile: public bob::io::base::File { return m_filename.c_str(); } - virtual const bob::io::base::array::typeinfo& type_all () const { + virtual const BobIoTypeinfo& type_all () const { return m_type; } - virtual const bob::io::base::array::typeinfo& type () const { + virtual const BobIoTypeinfo& type () const { return m_type; } @@ -80,7 +83,7 @@ class TensorArrayFile: public bob::io::base::File { private: //representation bob::io::base::TensorFile m_file; - bob::io::base::array::typeinfo m_type; + BobIoTypeinfo m_type; std::string m_filename; static std::string s_codecname; @@ -90,32 +93,11 @@ class TensorArrayFile: public bob::io::base::File { std::string TensorArrayFile::s_codecname = "bob.tensor"; /** - * 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. + * Registration method: use an unique name. Copy the definition to "plugin.h" + * and then call it on "main.cpp" to register the codec. */ - -/** - * 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) { +boost::shared_ptr<bob::io::base::File> + make_tensor_file (const char* path, char mode) { bob::io::base::TensorFile::openmode _mode; if (mode == 'r') _mode = bob::io::base::TensorFile::in; @@ -126,19 +108,3 @@ static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char 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/T3File.cpp b/bob/io/base/torch3.cpp similarity index 68% rename from bob/io/base/cpp/T3File.cpp rename to bob/io/base/torch3.cpp index 8380a62..5910da8 100644 --- a/bob/io/base/cpp/T3File.cpp +++ b/bob/io/base/torch3.cpp @@ -18,6 +18,11 @@ * 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> @@ -30,9 +35,6 @@ #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); @@ -69,12 +71,12 @@ class T3File: public bob::io::base::File { // are those floats or doubles? if (fsize == (nsamples*framesize*sizeof(float))) { - m_type_array.dtype = bob::io::base::array::t_float32; - m_type_arrayset.dtype = bob::io::base::array::t_float32; + m_type_array.dtype = NPY_FLOAT32; + m_type_arrayset.dtype = NPY_FLOAT32; } else if (fsize == (nsamples*framesize*sizeof(double))) { - m_type_array.dtype = bob::io::base::array::t_float64; - m_type_arrayset.dtype = bob::io::base::array::t_float64; + m_type_array.dtype = NPY_FLOAT64; + m_type_arrayset.dtype = NPY_FLOAT64; } else { boost::format s("Cannot read file '%s', mode = '%c': fsize (%d) != %d*%d*sizeof(float32) nor *sizeof(float64)"); @@ -83,8 +85,8 @@ class T3File: public bob::io::base::File { } size_t shape[2] = {nsamples, framesize}; - m_type_array.set_shape<size_t>(2, &shape[0]); - m_type_arrayset.set_shape<size_t>(1, &shape[1]); + 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_newfile = false; } @@ -96,11 +98,11 @@ class T3File: public bob::io::base::File { return m_filename.c_str(); } - virtual const bob::io::base::array::typeinfo& type_all () const { + virtual const BobIoTypeinfo& type_all () const { return m_type_array; } - virtual const bob::io::base::array::typeinfo& type () const { + virtual const BobIoTypeinfo& type () const { return m_type_arrayset; } @@ -120,14 +122,14 @@ class T3File: public bob::io::base::File { throw std::runtime_error(f.str()); } - if (!buffer.type().is_compatible(m_type_array)) buffer.set(m_type_array); + if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &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()), buffer.type().buffer_size()); + ifile.read(static_cast<char*>(buffer.ptr()), BobIoTypeinfo_BufferSize(&buffer.type())); } @@ -139,26 +141,26 @@ class T3File: public bob::io::base::File { throw std::runtime_error(f.str()); } - const bob::io::base::array::typeinfo& type = buffer.type(); + const BobIoTypeinfo& type = buffer.type(); - if (!buffer.type().is_compatible(m_type_arrayset)) buffer.set(m_type_arrayset); + if (!BobIoTypeinfo_IsCompatible(&buffer.type(), &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*type.buffer_size()), std::ios::beg); - ifile.read(static_cast<char*>(buffer.ptr()), type.buffer_size()); + ifile.seekg(8 + (index*BobIoTypeinfo_BufferSize(&type)), std::ios::beg); + ifile.read(static_cast<char*>(buffer.ptr()), BobIoTypeinfo_BufferSize(&type)); } virtual size_t append (const bob::io::base::array::interface& buffer) { - const bob::io::base::array::typeinfo& info = buffer.type(); + const BobIoTypeinfo& info = buffer.type(); - if (!m_newfile && !info.is_compatible(m_type_arrayset)) { + if (!m_newfile && !BobIoTypeinfo_IsCompatible(&info, &m_type_arrayset)) { boost::format f("input buffer of type %s cannot be appended to already initialized torch3vision binary file of type %s"); - f % info.str() % m_type_arrayset.str(); + f % BobIoTypeinfo_Str(&info) % BobIoTypeinfo_Str(&m_type_arrayset); throw std::runtime_error(f.str()); } @@ -168,15 +170,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 % info.str(); + m % BobIoTypeinfo_Str(&info); throw std::runtime_error(m.str()); } //can only save float32 or float64, otherwise, throw. - if ((info.dtype != bob::io::base::array::t_float32) && - (info.dtype != bob::io::base::array::t_float64)) { + if ((info.dtype != NPY_FLOAT32) && + (info.dtype != NPY_FLOAT64)) { boost::format f("cannot have T3 bindata files with type %s - only float32 or float64"); - f % bob::io::base::array::stringize(info.dtype); + f % PyBlitzArray_TypenumAsString(info.dtype); throw std::runtime_error(f.str()); } @@ -205,13 +207,13 @@ class T3File: public bob::io::base::File { throw std::runtime_error(f.str()); } - ofile.write(static_cast<const char*>(buffer.ptr()), info.buffer_size()); + ofile.write(static_cast<const char*>(buffer.ptr()), BobIoTypeinfo_BufferSize(&info)); ofile.close(); //setup new type information ++m_length; size_t shape[2] = {m_length, info.shape[0]}; - m_type_array.set_shape<size_t>(2, &shape[0]); + BobIoTypeinfo_Set(&m_type_array, m_type_array.dtype, 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); @@ -230,7 +232,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 bob::io::base::array::typeinfo& info = buffer.type(); + const BobIoTypeinfo& info = buffer.type(); if (info.nd == 1) {//just do a normal append append(buffer); @@ -239,10 +241,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()); - bob::io::base::array::typeinfo slice_info(info.dtype, static_cast<size_t>(1), - &info.shape[1]); + BobIoTypeinfo slice_info; + BobIoTypeinfo_Set(&slice_info, info.dtype, 1, &info.shape[1]); for (size_t k=0; k<info.shape[0]; ++k) { - const void* slice_ptr=static_cast<const void*>(ptr+k*slice_info.buffer_size()); + const void* slice_ptr=static_cast<const void*>(ptr+k*BobIoTypeinfo_BufferSize(&slice_info)); bob::io::base::array::blitz_array slice(const_cast<void*>(slice_ptr), slice_info); append(slice); } @@ -251,7 +253,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 % info.str(); + f % BobIoTypeinfo_Str(&info); throw std::runtime_error(f.str()); } @@ -261,8 +263,8 @@ class T3File: public bob::io::base::File { std::string m_filename; bool m_newfile; - bob::io::base::array::typeinfo m_type_array; - bob::io::base::array::typeinfo m_type_arrayset; + BobIoTypeinfo m_type_array; + BobIoTypeinfo m_type_arrayset; size_t m_length; static std::string s_codecname; @@ -272,47 +274,10 @@ class T3File: public bob::io::base::File { std::string T3File::s_codecname = "torch3.binary"; /** - * 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. + * Registration method: use an unique name. Copy the definition to "plugin.h" + * and then call it on "main.cpp" to register the codec. */ -static boost::shared_ptr<bob::io::base::File> make_file (const char* path, char mode) { +boost::shared_ptr<bob::io::base::File> + make_torch3_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/typeinfo.cpp b/bob/io/base/typeinfo.cpp new file mode 100644 index 0000000..ff275c9 --- /dev/null +++ b/bob/io/base/typeinfo.cpp @@ -0,0 +1,251 @@ +/** + * @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, + 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; + +} + +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/bob/io/base/cpp/utils.cpp b/bob/io/base/utils.cpp similarity index 53% rename from bob/io/base/cpp/utils.cpp rename to bob/io/base/utils.cpp index 3467b99..17a7fde 100644 --- a/bob/io/base/cpp/utils.cpp +++ b/bob/io/base/utils.cpp @@ -7,24 +7,30 @@ * Copyright (C) Idiap Research Institute, Martigny, Switzerland */ -#include <bob.io.base/CodecRegistry.h> -#include <bob.io.base/utils.h> +#define BOB_IO_BASE_MODULE +#include <bob.io.base/api.h> +#include "cpp/CodecRegistry.h" -boost::shared_ptr<bob::io::base::File> bob::io::base::open (const char* filename, +boost::shared_ptr<bob::io::base::File> BobIoFile_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::File> BobIoFile_OpenWithExtension + (const char* filename, char mode) { + boost::shared_ptr<bob::io::base::CodecRegistry> instance = bob::io::base::CodecRegistry::instance(); return instance->findByFilenameExtension(filename)(filename, mode); + } -bob::io::base::array::typeinfo bob::io::base::peek (const char* filename) { - return open(filename, 'r')->type(); +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_all (const char* filename) { - return open(filename, 'r')->type_all(); +void BobIoFile_PeekAll (const char* filename, BobIoTypeinfo* info) { + BobIoTypeinfo_Copy(info, BobIoFile_Open(filename, 'r')->type_all()); } diff --git a/setup.py b/setup.py index df02be0..5d2078a 100644 --- a/setup.py +++ b/setup.py @@ -168,25 +168,25 @@ setup( ), Extension("bob.io.base._library", [ + "bob/io/base/utils.cpp", + "bob/io/base/cpp/TensorFileHeader.cpp", + "bob/io/base/cpp/TensorFile.cpp", + "bob/io/base/cpp/blitz_array.cpp", + "bob/io/base/cpp/CodecRegistry.cpp", - "bob/io/base/cpp/CSVFile.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/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", -- GitLab