<commit_before>#pragma once
#ifndef NIFTY_HDF5_HDF5_ARRAY
#define NIFTY_HDF5_HDF5_ARRAY

#include <string>
#include <vector>

#include "nifty/tools/block_access.hxx"
#include "nifty/tools/runtime_check.hxx"
#include "nifty/marray/marray_hdf5.hxx"

namespace nifty{
namespace hdf5{

    using namespace marray::hdf5;

    template<class T>
    class Hdf5Array{
    public:
        template<class SHAPE_ITER, class CHUNK_SHAPE_ITER>
        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName,
            SHAPE_ITER shapeBegin,
            SHAPE_ITER shapeEnd,
            CHUNK_SHAPE_ITER chunkShapeBegin
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {
            datatype_ = H5Tcopy(hdf5Type<T>());
            const auto dim = std::distance(shapeBegin, shapeEnd);

            shape_.resize(dim);
            chunkShape_.resize(dim);

            std::vector<hsize_t> shape(dim);
            std::vector<hsize_t> chunkShape(dim);

            for(auto d=0; d<dim; ++d){
                const auto s = *shapeBegin;
                const auto cs = *chunkShapeBegin;
                shape[d] = s;
                shape_[d] = s;
                chunkShape[d] = cs;
                chunkShape_[d] = cs;
                ++shapeBegin;
                ++chunkShapeBegin;
            }

            // chunk properties
            hid_t dcplId = H5Pcreate(H5P_DATASET_CREATE);
            H5Pset_chunk(dcplId, hsize_t(dim), chunkShape.data());

            // dataset shape
            auto dataspace = H5Screate_simple(hsize_t(dim), shape.data(), NULL);

            // create the dataset
            dataset_ = H5Dcreate(groupHandle_, datasetName.c_str(), datatype_, dataspace,
                        H5P_DEFAULT,dcplId, H5P_DEFAULT);

            // close the dataspace and the chunk properties
            H5Sclose(dataspace);
            H5Pclose(dcplId);
        }

        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {

            dataset_ = H5Dopen(groupHandle_, datasetName.c_str(), H5P_DEFAULT);
            if(dataset_ < 0) {
                throw std::runtime_error("Marray cannot open dataset.");
            }

            /*
            auto plist = H5Dget_access_plist(dataset_);

            //H5Pset_cache(hid_t plist_id, int mdc_nelmts, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)

            const auto anyVal = 0;
            const auto somePrime = 977;
            const auto nBytes = 36000000;
            const auto rddc = 1.0;
            auto ret = H5Pset_cache(plist, anyVal, somePrime,  nBytes, rddc);

            H5Pclose(plist);
            std::cout<<"set H5Pset_cache groupHandle_ "<<ret<<"\n";

            */

            // select dataspace hyperslab
            datatype_ = H5Dget_type(dataset_);
            if(!H5Tequal(datatype_, hdf5Type<T>())) {
                throw std::runtime_error("data type of stored hdf5 dataset and passed array do not match in loadHyperslab");
            }

            this->loadShape(shape_);
            this->loadChunkShape(chunkShape_);
        }

        int setCache(){
            //herr_t H5Pset_cache(hid_t plist_id, int mdc_nelmts, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)
        }

        ~Hdf5Array(){
            H5Tclose(datatype_);
            H5Dclose(dataset_);
        }

        uint64_t dimension()const{
            return shape_.size();
        }
        uint64_t shape(const size_t d)const{
            return shape_[d];
        }
        const std::vector<uint64_t> & shape()const{
            return shape_;
        }
        uint64_t chunkShape(const size_t d)const{
            return chunkShape_[d];
        }
        const std::vector<uint64_t> & chunkShape()const{
            return chunkShape_;
        }

        bool isChunked()const{
            return isChunked_;
        }

        template<class ITER>
        void readSubarray(
            ITER roiBeginIter,
            marray::View<T> & out
        )const{
            NIFTY_CHECK_OP(out.dimension(),==,this->dimension(),"out has wrong dimension");
            NIFTY_CHECK(out.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            //std::cout<<"load hyperslab\n";
            this->loadHyperslab(roiBeginIter, roiBeginIter+out.dimension(), out.shapeBegin(), out);
        }

        template<class ITER>
        void writeSubarray(
            ITER roiBeginIter,
            const marray::View<T> & in
        ){
            NIFTY_CHECK_OP(in.dimension(),==,this->dimension(),"in has wrong dimension");
            NIFTY_CHECK(in.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            this->saveHyperslab(roiBeginIter, roiBeginIter+in.dimension(), in.shapeBegin(), in);
        }

    private:
        template<class BaseIterator, class ShapeIterator>
        void loadHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            marray::View<T> & out
        ) const {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine shape of hyperslab and array
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            std::vector<hsize_t> marrayShape(size);
            marray::CoordinateOrder coordinateOrder;
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                // don't reverse base and shape
                coordinateOrder = marray::FirstMajorOrder;
                for(std::size_t j=0; j<size; ++j) {
                    offset[j] = hsize_t(*baseBegin);
                    slabShape[j] = hsize_t(*shapeBegin);
                    marrayShape[j] = slabShape[j];

                    ++baseBegin;
                    ++shapeBegin;
                }
            }

            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape !");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(size), &marrayShape[0], NULL);
            std::vector<hsize_t> offsetOut(size, 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &offsetOut[0],
                NULL, &marrayShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace);
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape s!");
            }

            // read from dataspace into memspace
            //out = Marray<T>(SkipInitialization, &marrayShape[0],
            //    (&marrayShape[0])+size, coordinateOrder);

            if(out.isSimple()){
                //std::cout<<"is simple\n";
                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(out(0)));

                //std::cout<<"read status "<<status<<"\n";
            }
            else{
                //std::cout<<"is not simple\n";
                marray::Marray<T> tmpOut(marray::SkipInitialization, &marrayShape[0],
                    (&marrayShape[0])+size, coordinateOrder);

                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(tmpOut(0)));

                //std::cout<<"read status "<<status<<"\n";

                out = tmpOut;
            }

            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot read from dataset.");
            }
            handleCheck.check();
        }

        template<class BaseIterator, class ShapeIterator>
        void
        saveHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            const marray::View<T> & in
        ) {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine hyperslab shape
            std::vector<hsize_t> memoryShape(in.dimension());
            for(std::size_t j=0; j<in.dimension(); ++j) {
                memoryShape[j] = in.shape(j);
            }
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            bool reverseShapeAttribute = (H5Aexists(dataset_, reverseShapeAttributeName) > 0);
            if(reverseShapeAttribute || in.coordinateOrder() == marray::LastMajorOrder) {
                NIFTY_CHECK(false, "neither reverseShapeAttribute nor LastMajorOrder are currently supported");
            }
            else{
               for(std::size_t j=0; j<size; ++j) {
                   offset[j] = hsize_t(*baseBegin);
                   slabShape[j] = hsize_t(*shapeBegin);
                   ++baseBegin;
                   ++shapeBegin;
               }
            }

            // select dataspace hyperslab
            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(in.dimension()), &memoryShape[0], NULL);
            std::vector<hsize_t> memoryOffset(int(in.dimension()), 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &memoryOffset[0], NULL,
                &memoryShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace); ;
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            if(in.isSimple()){
               status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(in(0)));
            }
            else{
                marray::Marray<T> tmp(in);
                status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(tmp(0)));
            }
            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot write to dataset.");
            }
            handleCheck.check();
        }

        void loadShape(std::vector<uint64_t> & shapeVec){

            marray::marray_detail::Assert(marray::MARRAY_NO_ARG_TEST || groupHandle_ >= 0);
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            hid_t filespace = H5Dget_space(dataset_);
            hsize_t dimension = H5Sget_simple_extent_ndims(filespace);
            hsize_t* shape = new hsize_t[(std::size_t)(dimension)];
            herr_t status = H5Sget_simple_extent_dims(filespace, shape, NULL);
            if(status < 0) {
                H5Sclose(filespace);
                delete[] shape;
                throw std::runtime_error("MarrayNifty cannot get extension of dataset.");
            }
            // write shape to shape_
            shapeVec.resize(dimension);
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                for(std::size_t j=0; j<shapeVec.size(); ++j) {
                    shapeVec[j] = uint64_t(shape[j]);
                }
            }
            // clean up
            delete[] shape;
            H5Sclose(filespace);
            handleCheck.check();
        }

        void loadChunkShape(std::vector<uint64_t> & chunkShape){
            const auto d = this->dimension();
            std::vector<hsize_t> chunkShapeTmp(d);
            auto plist = H5Dget_create_plist(dataset_);

            bool couldBeChunked = false;
            const auto layout =  H5Pget_layout(plist);
            if(layout == H5D_CHUNKED){
                couldBeChunked = true;
            }
            if(couldBeChunked){
                herr_t status = H5Pget_chunk(plist, int(d), chunkShapeTmp.data());
                if(status < 0) {
                    isChunked_ = false;
                    chunkShape_ = shape_;
                    //H5Pclose(plist);
                    //throw std::runtime_error("Nifty cannot get chunkShape of dataset");
                }
                else{
                    isChunked_ = true;
                    chunkShape_.resize(d);
                    std::copy(chunkShapeTmp.begin(), chunkShapeTmp.end(), chunkShape_.begin());
                }
            }
            else{
                isChunked_ = false;
                chunkShape_ = shape_;
            }
            H5Pclose(plist);
        }

        hid_t groupHandle_;
        hid_t dataset_;
        hid_t datatype_;
        std::vector<uint64_t> shape_;
        std::vector<uint64_t> chunkShape_;
        bool isChunked_;
    };

    namespace tools{

}

} // namespace nifty::hdf5

namespace tools{

    template<class T, class COORD>
    inline void readSubarray(
        const hdf5::Hdf5Array<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){
        array.readSubarray(beginCoord.begin(), subarray);
    }

    template<class ARRAY>
    struct BlockStorageSelector;

    template<class T>
    struct BlockStorageSelector<hdf5::Hdf5Array<T> >
    {
       typedef BlockStorage<T> type;
    };
} // namespace nifty::tools

} // namespace nifty

#endif  // NIFTY_HDF5_HDF5_ARRAY
<commit_msg>hdf5 w.i.p.<commit_after>#pragma once
#ifndef NIFTY_HDF5_HDF5_ARRAY
#define NIFTY_HDF5_HDF5_ARRAY

#include <string>
#include <vector>

#include "nifty/tools/block_access.hxx"
#include "nifty/tools/runtime_check.hxx"
#include "nifty/marray/marray_hdf5.hxx"

namespace nifty{
namespace hdf5{

    using namespace marray::hdf5;

    template<class T>
    class Hdf5Array{
    public:
        template<class SHAPE_ITER, class CHUNK_SHAPE_ITER>
        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName,
            SHAPE_ITER shapeBegin,
            SHAPE_ITER shapeEnd,
            CHUNK_SHAPE_ITER chunkShapeBegin
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {
            datatype_ = H5Tcopy(hdf5Type<T>());
            const auto dim = std::distance(shapeBegin, shapeEnd);

            shape_.resize(dim);
            chunkShape_.resize(dim);

            std::vector<hsize_t> shape(dim);
            std::vector<hsize_t> chunkShape(dim);

            for(auto d=0; d<dim; ++d){
                const auto s = *shapeBegin;
                const auto cs = *chunkShapeBegin;
                shape[d] = s;
                shape_[d] = s;
                chunkShape[d] = cs;
                chunkShape_[d] = cs;
                ++shapeBegin;
                ++chunkShapeBegin;
            }

            // chunk properties
            hid_t dcplId = H5Pcreate(H5P_DATASET_CREATE);
            H5Pset_chunk(dcplId, hsize_t(dim), chunkShape.data());

            // dataset shape
            auto dataspace = H5Screate_simple(hsize_t(dim), shape.data(), NULL);

            // create the dataset
            dataset_ = H5Dcreate(groupHandle_, datasetName.c_str(), datatype_, dataspace,
                        H5P_DEFAULT,dcplId, H5P_DEFAULT);

            // close the dataspace and the chunk properties
            H5Sclose(dataspace);
            H5Pclose(dcplId);
        }

        Hdf5Array(
            const hid_t& groupHandle,
            const std::string & datasetName
        )
        :   groupHandle_(groupHandle),
            dataset_(),
            datatype_(),
            isChunked_(true)
        {

            dataset_ = H5Dopen(groupHandle_, datasetName.c_str(), H5P_DEFAULT);
            if(dataset_ < 0) {
                throw std::runtime_error("Marray cannot open dataset.");
            }

            auto plist = H5Dget_access_plist(dataset_);
            const auto somePrime = 977;
            const auto nBytes = 36000000;
            const auto rddc = 1.0;
            auto ret = H5Pset_chunk_cache(plist, somePrime,  nBytes, rddc);
            H5Pclose(plist);
            std::cout<<"set H5Pset_chunk_cache groupHandle_ "<<ret<<"\n";

            // select dataspace hyperslab
            datatype_ = H5Dget_type(dataset_);
            if(!H5Tequal(datatype_, hdf5Type<T>())) {
                throw std::runtime_error("data type of stored hdf5 dataset and passed array do not match in loadHyperslab");
            }

            this->loadShape(shape_);
            this->loadChunkShape(chunkShape_);
        }

        int setCache(){
            //herr_t H5Pset_cache(hid_t plist_id, int mdc_nelmts, size_t rdcc_nslots, size_t rdcc_nbytes, double rdcc_w0)
        }

        ~Hdf5Array(){
            H5Tclose(datatype_);
            H5Dclose(dataset_);
        }

        uint64_t dimension()const{
            return shape_.size();
        }
        uint64_t shape(const size_t d)const{
            return shape_[d];
        }
        const std::vector<uint64_t> & shape()const{
            return shape_;
        }
        uint64_t chunkShape(const size_t d)const{
            return chunkShape_[d];
        }
        const std::vector<uint64_t> & chunkShape()const{
            return chunkShape_;
        }

        bool isChunked()const{
            return isChunked_;
        }

        template<class ITER>
        void readSubarray(
            ITER roiBeginIter,
            marray::View<T> & out
        )const{
            NIFTY_CHECK_OP(out.dimension(),==,this->dimension(),"out has wrong dimension");
            NIFTY_CHECK(out.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            //std::cout<<"load hyperslab\n";
            this->loadHyperslab(roiBeginIter, roiBeginIter+out.dimension(), out.shapeBegin(), out);
        }

        template<class ITER>
        void writeSubarray(
            ITER roiBeginIter,
            const marray::View<T> & in
        ){
            NIFTY_CHECK_OP(in.dimension(),==,this->dimension(),"in has wrong dimension");
            NIFTY_CHECK(in.coordinateOrder() == marray::FirstMajorOrder,
                "currently only views with last major order are supported"
            );
            this->saveHyperslab(roiBeginIter, roiBeginIter+in.dimension(), in.shapeBegin(), in);
        }

    private:
        template<class BaseIterator, class ShapeIterator>
        void loadHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            marray::View<T> & out
        ) const {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine shape of hyperslab and array
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            std::vector<hsize_t> marrayShape(size);
            marray::CoordinateOrder coordinateOrder;
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                // don't reverse base and shape
                coordinateOrder = marray::FirstMajorOrder;
                for(std::size_t j=0; j<size; ++j) {
                    offset[j] = hsize_t(*baseBegin);
                    slabShape[j] = hsize_t(*shapeBegin);
                    marrayShape[j] = slabShape[j];

                    ++baseBegin;
                    ++shapeBegin;
                }
            }

            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape !");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(size), &marrayShape[0], NULL);
            std::vector<hsize_t> offsetOut(size, 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &offsetOut[0],
                NULL, &marrayShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace);
                H5Sclose(dataspace);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape s!");
            }

            // read from dataspace into memspace
            //out = Marray<T>(SkipInitialization, &marrayShape[0],
            //    (&marrayShape[0])+size, coordinateOrder);

            if(out.isSimple()){
                //std::cout<<"is simple\n";
                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(out(0)));

                //std::cout<<"read status "<<status<<"\n";
            }
            else{
                //std::cout<<"is not simple\n";
                marray::Marray<T> tmpOut(marray::SkipInitialization, &marrayShape[0],
                    (&marrayShape[0])+size, coordinateOrder);

                status = H5Dread(dataset_, datatype_, memspace, dataspace,
                    H5P_DEFAULT, &(tmpOut(0)));

                //std::cout<<"read status "<<status<<"\n";

                out = tmpOut;
            }

            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot read from dataset.");
            }
            handleCheck.check();
        }

        template<class BaseIterator, class ShapeIterator>
        void
        saveHyperslab(
            BaseIterator baseBegin,
            BaseIterator baseEnd,
            ShapeIterator shapeBegin,
            const marray::View<T> & in
        ) {
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            // determine hyperslab shape
            std::vector<hsize_t> memoryShape(in.dimension());
            for(std::size_t j=0; j<in.dimension(); ++j) {
                memoryShape[j] = in.shape(j);
            }
            std::size_t size = std::distance(baseBegin, baseEnd);
            std::vector<hsize_t> offset(size);
            std::vector<hsize_t> slabShape(size);
            bool reverseShapeAttribute = (H5Aexists(dataset_, reverseShapeAttributeName) > 0);
            if(reverseShapeAttribute || in.coordinateOrder() == marray::LastMajorOrder) {
                NIFTY_CHECK(false, "neither reverseShapeAttribute nor LastMajorOrder are currently supported");
            }
            else{
               for(std::size_t j=0; j<size; ++j) {
                   offset[j] = hsize_t(*baseBegin);
                   slabShape[j] = hsize_t(*shapeBegin);
                   ++baseBegin;
                   ++shapeBegin;
               }
            }

            // select dataspace hyperslab
            hid_t dataspace = H5Dget_space(dataset_);
            herr_t status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
                &offset[0], NULL, &slabShape[0], NULL);
            if(status < 0) {
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            // select memspace hyperslab
            hid_t memspace = H5Screate_simple(int(in.dimension()), &memoryShape[0], NULL);
            std::vector<hsize_t> memoryOffset(int(in.dimension()), 0); // no offset
            status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, &memoryOffset[0], NULL,
                &memoryShape[0], NULL);
            if(status < 0) {
                H5Sclose(memspace); ;
                H5Sclose(dataspace);
                H5Dclose(dataset_);
                throw std::runtime_error("Marray cannot select hyperslab. Check offset and shape!");
            }

            if(in.isSimple()){
               status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(in(0)));
            }
            else{
                marray::Marray<T> tmp(in);
                status = H5Dwrite(dataset_, datatype_, memspace, dataspace, H5P_DEFAULT, &(tmp(0)));
            }
            // clean up
            H5Sclose(memspace);
            H5Sclose(dataspace);
            if(status < 0) {
                throw std::runtime_error("Marray cannot write to dataset.");
            }
            handleCheck.check();
        }

        void loadShape(std::vector<uint64_t> & shapeVec){

            marray::marray_detail::Assert(marray::MARRAY_NO_ARG_TEST || groupHandle_ >= 0);
            HandleCheck<marray::MARRAY_NO_DEBUG> handleCheck;

            hid_t filespace = H5Dget_space(dataset_);
            hsize_t dimension = H5Sget_simple_extent_ndims(filespace);
            hsize_t* shape = new hsize_t[(std::size_t)(dimension)];
            herr_t status = H5Sget_simple_extent_dims(filespace, shape, NULL);
            if(status < 0) {
                H5Sclose(filespace);
                delete[] shape;
                throw std::runtime_error("MarrayNifty cannot get extension of dataset.");
            }
            // write shape to shape_
            shapeVec.resize(dimension);
            if(H5Aexists(dataset_, reverseShapeAttributeName) > 0) {
                NIFTY_CHECK(false, "currently we do not allow to load from datasets with reverseShapeAttribute")
            }
            else {
                for(std::size_t j=0; j<shapeVec.size(); ++j) {
                    shapeVec[j] = uint64_t(shape[j]);
                }
            }
            // clean up
            delete[] shape;
            H5Sclose(filespace);
            handleCheck.check();
        }

        void loadChunkShape(std::vector<uint64_t> & chunkShape){
            const auto d = this->dimension();
            std::vector<hsize_t> chunkShapeTmp(d);
            auto plist = H5Dget_create_plist(dataset_);

            bool couldBeChunked = false;
            const auto layout =  H5Pget_layout(plist);
            if(layout == H5D_CHUNKED){
                couldBeChunked = true;
            }
            if(couldBeChunked){
                herr_t status = H5Pget_chunk(plist, int(d), chunkShapeTmp.data());
                if(status < 0) {
                    isChunked_ = false;
                    chunkShape_ = shape_;
                    //H5Pclose(plist);
                    //throw std::runtime_error("Nifty cannot get chunkShape of dataset");
                }
                else{
                    isChunked_ = true;
                    chunkShape_.resize(d);
                    std::copy(chunkShapeTmp.begin(), chunkShapeTmp.end(), chunkShape_.begin());
                }
            }
            else{
                isChunked_ = false;
                chunkShape_ = shape_;
            }
            H5Pclose(plist);
        }

        hid_t groupHandle_;
        hid_t dataset_;
        hid_t datatype_;
        std::vector<uint64_t> shape_;
        std::vector<uint64_t> chunkShape_;
        bool isChunked_;
    };

    namespace tools{

}

} // namespace nifty::hdf5

namespace tools{

    template<class T, class COORD>
    inline void readSubarray(
        const hdf5::Hdf5Array<T> array,
        const COORD & beginCoord,
        const COORD & endCoord,
        marray::View<T> & subarray
    ){
        array.readSubarray(beginCoord.begin(), subarray);
    }

    template<class ARRAY>
    struct BlockStorageSelector;

    template<class T>
    struct BlockStorageSelector<hdf5::Hdf5Array<T> >
    {
       typedef BlockStorage<T> type;
    };
} // namespace nifty::tools

} // namespace nifty

#endif  // NIFTY_HDF5_HDF5_ARRAY
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: borderlineprimitive2d.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: aw $ $Date: 2008-04-08 05:51:22 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_drawinglayer.hxx"

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
#endif

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PRIMITIVETYPES2D_HXX
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX
#include <basegfx/polygon/b2dpolygon.hxx>
#endif

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYGONPRIMITIVE2D_HXX
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#endif

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYPOLYGONPRIMITIVE2D_HXX
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#endif

#include <numeric>

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace primitive2d
    {
        Primitive2DSequence BorderLinePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
        {
            Primitive2DSequence xRetval;

            if(!getStart().equal(getEnd()) && (getCreateInside() || getCreateOutside()))
            {
                const bool bInsideUsed(!basegfx::fTools::equalZero(getLeftWidth()));

                if(bInsideUsed)
                {
                    // get data and vectors
                    const bool bOutsideUsed(!basegfx::fTools::equalZero(getRightWidth()));
                    const double fWidth(getWidth());
                    basegfx::B2DVector aVector(getEnd() - getStart());
                    aVector.normalize();
                    const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector));

                    if(bOutsideUsed)
                    {
                        // both used, double line definition. Create left and right offset
                        xRetval.realloc(getCreateInside() && getCreateOutside() ? 2 : 1);
                        sal_uInt32 nInsert(0);

                        if(getCreateInside())
                        {
                            // create geometry for left
                            const basegfx::B2DVector aLeftOff(aPerpendicular * (0.5 * (getLeftWidth() - fWidth)));
                            basegfx::B2DPolygon aLeft;
                            aLeft.append(getStart() + aLeftOff - (getExtendInnerStart() * aVector));
                            aLeft.append(getEnd() + aLeftOff + (getExtendInnerEnd() * aVector));

                            if(basegfx::fTools::equal(1.0, getLeftWidth()))
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D(
                                    aLeft,
                                    getRGBColor()));
                            }
                            else
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonStrokePrimitive2D(
                                    aLeft,
                                    attribute::LineAttribute(getRGBColor(), getLeftWidth()),
                                    attribute::StrokeAttribute()));
                            }
                        }

                        if(getCreateOutside())
                        {
                            // create geometry for right
                            const basegfx::B2DVector aRightOff(aPerpendicular * (0.5 * (fWidth - getRightWidth())));
                            basegfx::B2DPolygon aRight;
                            aRight.append(getStart() + aRightOff - (getExtendOuterStart() * aVector));
                            aRight.append(getEnd() + aRightOff + (getExtendOuterEnd() * aVector));

                            if(basegfx::fTools::equal(1.0, getRightWidth()))
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D(
                                    aRight,
                                    getRGBColor()));
                            }
                            else
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonStrokePrimitive2D(
                                    aRight,
                                    attribute::LineAttribute(getRGBColor(), getRightWidth()),
                                    attribute::StrokeAttribute()));
                            }
                        }
                    }
                    else
                    {
                        // single line, create geometry
                        basegfx::B2DPolygon aPolygon;
                        const double fMaxExtStart(::std::max(getExtendInnerStart(), getExtendOuterStart()));
                        const double fMaxExtEnd(::std::max(getExtendInnerEnd(), getExtendOuterEnd()));
                        aPolygon.append(getStart() - (fMaxExtStart * aVector));
                        aPolygon.append(getEnd() + (fMaxExtEnd * aVector));
                        xRetval.realloc(1);

                        if(basegfx::fTools::equal(1.0, getLeftWidth()))
                        {
                            xRetval[0] = Primitive2DReference(new PolygonHairlinePrimitive2D(
                                aPolygon,
                                getRGBColor()));
                        }
                        else
                        {
                            xRetval[0] = Primitive2DReference(new PolygonStrokePrimitive2D(
                                aPolygon,
                                attribute::LineAttribute(getRGBColor(), getLeftWidth()),
                                attribute::StrokeAttribute()));
                        }
                    }
                }
            }

            return xRetval;
        }

        BorderLinePrimitive2D::BorderLinePrimitive2D(
            const basegfx::B2DPoint& rStart,
            const basegfx::B2DPoint& rEnd,
            double fLeftWidth,
            double fDistance,
            double fRightWidth,
            double fExtendInnerStart,
            double fExtendInnerEnd,
            double fExtendOuterStart,
            double fExtendOuterEnd,
            bool bCreateInside,
            bool bCreateOutside,
            const basegfx::BColor& rRGBColor)
        :   BasePrimitive2D(),
            maStart(rStart),
            maEnd(rEnd),
            mfLeftWidth(fLeftWidth),
            mfDistance(fDistance),
            mfRightWidth(fRightWidth),
            mfExtendInnerStart(fExtendInnerStart),
            mfExtendInnerEnd(fExtendInnerEnd),
            mfExtendOuterStart(fExtendOuterStart),
            mfExtendOuterEnd(fExtendOuterEnd),
            mbCreateInside(bCreateInside),
            mbCreateOutside(bCreateOutside),
            maRGBColor(rRGBColor)
        {
        }

        bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
        {
            if(BasePrimitive2D::operator==(rPrimitive))
            {
                const BorderLinePrimitive2D& rCompare = (BorderLinePrimitive2D&)rPrimitive;

                return (getStart() == rCompare.getStart()
                    && getEnd() == rCompare.getEnd()
                    && getLeftWidth() == rCompare.getLeftWidth()
                    && getDistance() == rCompare.getDistance()
                    && getRightWidth() == rCompare.getRightWidth()
                    && getExtendInnerStart() == rCompare.getExtendInnerStart()
                    && getExtendInnerEnd() == rCompare.getExtendInnerEnd()
                    && getExtendOuterStart() == rCompare.getExtendOuterStart()
                    && getExtendOuterEnd() == rCompare.getExtendOuterEnd()
                    && getCreateInside() == rCompare.getCreateInside()
                    && getCreateOutside() == rCompare.getCreateOutside()
                    && getRGBColor() == rCompare.getRGBColor());
            }

            return false;
        }

        // provide unique ID
        ImplPrimitrive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D)

    } // end of namespace primitive2d
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////
// eof
<commit_msg>#i39532# warning change to constructor<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: borderlineprimitive2d.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: aw $ $Date: 2008-04-08 05:58:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_drawinglayer.hxx"

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BORDERLINEPRIMITIVE2D_HXX
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
#endif

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PRIMITIVETYPES2D_HXX
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX
#include <basegfx/polygon/b2dpolygon.hxx>
#endif

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYGONPRIMITIVE2D_HXX
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#endif

#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYPOLYGONPRIMITIVE2D_HXX
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#endif

#include <numeric>

//////////////////////////////////////////////////////////////////////////////

namespace drawinglayer
{
    namespace primitive2d
    {
        Primitive2DSequence BorderLinePrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
        {
            Primitive2DSequence xRetval;

            if(!getStart().equal(getEnd()) && (getCreateInside() || getCreateOutside()))
            {
                const bool bInsideUsed(!basegfx::fTools::equalZero(getLeftWidth()));

                if(bInsideUsed)
                {
                    // get data and vectors
                    const bool bOutsideUsed(!basegfx::fTools::equalZero(getRightWidth()));
                    const double fWidth(getWidth());
                    basegfx::B2DVector aVector(getEnd() - getStart());
                    aVector.normalize();
                    const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector));

                    if(bOutsideUsed)
                    {
                        // both used, double line definition. Create left and right offset
                        xRetval.realloc(getCreateInside() && getCreateOutside() ? 2 : 1);
                        sal_uInt32 nInsert(0);

                        if(getCreateInside())
                        {
                            // create geometry for left
                            const basegfx::B2DVector aLeftOff(aPerpendicular * (0.5 * (getLeftWidth() - fWidth)));
                            basegfx::B2DPolygon aLeft;
                            aLeft.append(getStart() + aLeftOff - (getExtendInnerStart() * aVector));
                            aLeft.append(getEnd() + aLeftOff + (getExtendInnerEnd() * aVector));

                            if(basegfx::fTools::equal(1.0, getLeftWidth()))
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D(
                                    aLeft,
                                    getRGBColor()));
                            }
                            else
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonStrokePrimitive2D(
                                    aLeft,
                                    attribute::LineAttribute(getRGBColor(), getLeftWidth()),
                                    attribute::StrokeAttribute()));
                            }
                        }

                        if(getCreateOutside())
                        {
                            // create geometry for right
                            const basegfx::B2DVector aRightOff(aPerpendicular * (0.5 * (fWidth - getRightWidth())));
                            basegfx::B2DPolygon aRight;
                            aRight.append(getStart() + aRightOff - (getExtendOuterStart() * aVector));
                            aRight.append(getEnd() + aRightOff + (getExtendOuterEnd() * aVector));

                            if(basegfx::fTools::equal(1.0, getRightWidth()))
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonHairlinePrimitive2D(
                                    aRight,
                                    getRGBColor()));
                            }
                            else
                            {
                                xRetval[nInsert++] = Primitive2DReference(new PolygonStrokePrimitive2D(
                                    aRight,
                                    attribute::LineAttribute(getRGBColor(), getRightWidth()),
                                    attribute::StrokeAttribute()));
                            }
                        }
                    }
                    else
                    {
                        // single line, create geometry
                        basegfx::B2DPolygon aPolygon;
                        const double fMaxExtStart(::std::max(getExtendInnerStart(), getExtendOuterStart()));
                        const double fMaxExtEnd(::std::max(getExtendInnerEnd(), getExtendOuterEnd()));
                        aPolygon.append(getStart() - (fMaxExtStart * aVector));
                        aPolygon.append(getEnd() + (fMaxExtEnd * aVector));
                        xRetval.realloc(1);

                        if(basegfx::fTools::equal(1.0, getLeftWidth()))
                        {
                            xRetval[0] = Primitive2DReference(new PolygonHairlinePrimitive2D(
                                aPolygon,
                                getRGBColor()));
                        }
                        else
                        {
                            xRetval[0] = Primitive2DReference(new PolygonStrokePrimitive2D(
                                aPolygon,
                                attribute::LineAttribute(getRGBColor(), getLeftWidth()),
                                attribute::StrokeAttribute()));
                        }
                    }
                }
            }

            return xRetval;
        }

        BorderLinePrimitive2D::BorderLinePrimitive2D(
            const basegfx::B2DPoint& rStart,
            const basegfx::B2DPoint& rEnd,
            double fLeftWidth,
            double fDistance,
            double fRightWidth,
            double fExtendInnerStart,
            double fExtendInnerEnd,
            double fExtendOuterStart,
            double fExtendOuterEnd,
            bool bCreateInside,
            bool bCreateOutside,
            const basegfx::BColor& rRGBColor)
        :   BasePrimitive2D(),
            maStart(rStart),
            maEnd(rEnd),
            mfLeftWidth(fLeftWidth),
            mfDistance(fDistance),
            mfRightWidth(fRightWidth),
            mfExtendInnerStart(fExtendInnerStart),
            mfExtendInnerEnd(fExtendInnerEnd),
            mfExtendOuterStart(fExtendOuterStart),
            mfExtendOuterEnd(fExtendOuterEnd),
            maRGBColor(rRGBColor),
            mbCreateInside(bCreateInside),
            mbCreateOutside(bCreateOutside)
        {
        }

        bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
        {
            if(BasePrimitive2D::operator==(rPrimitive))
            {
                const BorderLinePrimitive2D& rCompare = (BorderLinePrimitive2D&)rPrimitive;

                return (getStart() == rCompare.getStart()
                    && getEnd() == rCompare.getEnd()
                    && getLeftWidth() == rCompare.getLeftWidth()
                    && getDistance() == rCompare.getDistance()
                    && getRightWidth() == rCompare.getRightWidth()
                    && getExtendInnerStart() == rCompare.getExtendInnerStart()
                    && getExtendInnerEnd() == rCompare.getExtendInnerEnd()
                    && getExtendOuterStart() == rCompare.getExtendOuterStart()
                    && getExtendOuterEnd() == rCompare.getExtendOuterEnd()
                    && getCreateInside() == rCompare.getCreateInside()
                    && getCreateOutside() == rCompare.getCreateOutside()
                    && getRGBColor() == rCompare.getRGBColor());
            }

            return false;
        }

        // provide unique ID
        ImplPrimitrive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D)

    } // end of namespace primitive2d
} // end of namespace drawinglayer

//////////////////////////////////////////////////////////////////////////////
// eof
<|endoftext|>


<commit_before>/* /////////////////////////////////////////////////////////////////////////
 * File:        vole/error/exceptions.hpp
 *
 * Purpose:     Exceptions used by VOLE.
 *
 * Created:     4th January 2007
 * Updated:     4th June 2010
 *
 * Home:        http://vole.sourceforge.net/
 *
 * Copyright (c) 2007-2010, Matthew Wilson and Synesis Software
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
 *   any contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * ////////////////////////////////////////////////////////////////////// */

/** \file vole/error/exceptions.hpp
 *
 * \brief Exceptions used by VOLE.
 */

#ifndef VOLE_INCL_VOLE_UTIL_HPP_EXCEPTIONS
#define VOLE_INCL_VOLE_UTIL_HPP_EXCEPTIONS

#ifndef VOLE_DOCUMENTATION_SKIP_SECTION
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_MAJOR    1
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_MINOR    5
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_REVISION 3
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_EDIT     12
#endif /* !VOLE_DOCUMENTATION_SKIP_SECTION */

/* /////////////////////////////////////////////////////////////////////////
 * Includes
 */

#include <vole/util/common.hpp>

#ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
# include <comstl/error/exceptions.hpp>
#endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
#ifndef COMSTL_INCL_COMSTL_ERROR_HPP_ERRORINFO_DESC
# include <comstl/error/errorinfo_desc.hpp>
#endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_ERRORINFO_DESC */
#ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING
# include <stlsoft/util/exception_string.hpp>
#endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING */
//#ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING_CREATOR
//# include <stlsoft/util/exception_string_creator.hpp>
//#endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING_CREATOR */
#ifndef WINSTL_INCL_CONVERSION_HPP_W2M
# include <winstl/conversion/w2m.hpp>
#endif /* !WINSTL_INCL_CONVERSION_HPP_W2M */
#ifdef STLSOFT_CF_THROW_BAD_ALLOC
# include <new>
#endif /* STLSOFT_CF_THROW_BAD_ALLOC */
#include <string>

/* /////////////////////////////////////////////////////////////////////////
 * Namespace
 */

#ifndef VOLE_NO_NAMESPACE
namespace vole
{
#endif /* !VOLE_NO_NAMESPACE */

/* /////////////////////////////////////////////////////////////////////////
 * Macros
 */

/* /////////////////////////////////////////////////////////////////////////
 * Functions
 */

/* /////////////////////////////////////////////////////////////////////////
 * Classes
 */

/// Root exception class for VOLE
class vole_exception
    : public comstl::com_exception
{
/// \name Member Types
/// @{
protected:
    typedef char                        char_type;
public:
    typedef vole_exception              class_type;
    typedef comstl::com_exception       parent_class_type;
protected:
    typedef stlsoft::exception_string   string_type;
    struct ctor_args_type
    {
        string_type message;
        HRESULT     hr;

        ctor_args_type()
            : message()
            , hr(E_FAIL)
        {}
        explicit ctor_args_type(string_type const& message, HRESULT hr)
            : message(message)
            , hr(hr)
        {}
    };
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    vole_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
protected:
    vole_exception(ctor_args_type const& args)
        : parent_class_type(args.message.c_str(), args.hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a vole::object (or vole::collection) instance is
/// not connected to its underlying COM Automation server
class object_not_connected_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef object_not_connected_exception  class_type;
    typedef vole_exception                  parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    object_not_connected_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a COM Automation server instance cannot be created
class creation_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef creation_exception      class_type;
    typedef vole_exception          parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    creation_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a type conversion cannot be performed
class type_conversion_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef type_conversion_exception   class_type;
    typedef vole_exception              parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    type_conversion_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a method/property cannot be described or invoked
class invocation_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef invocation_exception            class_type;
    typedef vole_exception                  parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The \c HRESULT associated with the exception
    /// \param xinfo Optional pointer to an EXCEPINFO structure
    ///   associated with the failed operation
    invocation_exception(char const* message, HRESULT hr, EXCEPINFO const* xinfo = NULL)
        : parent_class_type(create_reason_(DISPID_UNKNOWN, message, hr, xinfo))
        , m_dispid(DISPID_UNKNOWN)
    {}
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param dispid The \c DISPID of the method/property invoked
    /// \param message The message to be carried in the exception
    /// \param hr The \c HRESULT associated with the exception
    /// \param xinfo Optional pointer to an EXCEPINFO structure
    ///   associated with the failed operation
    invocation_exception(DISPID dispid, char const* message, HRESULT hr, EXCEPINFO const* xinfo = NULL)
        : parent_class_type(create_reason_(dispid, message, hr, xinfo))
        , m_dispid(dispid)
    {}
/// @}

/// \name Accessors
/// @{
public:
    /// The \c DISPID associated with the exception, or \c DISPID_UNKNOWN if
    /// no identifier was given/specified.
    HRESULT get_dispid() const
    {
        return m_dispid;
    }

/// @}

/// \name Implementation
/// @{
private:
    static ctor_args_type create_reason_(DISPID dispid, char const* message, HRESULT hr, EXCEPINFO const* xinfo);
/// @}

/// \name Members
/// @{
private:
    DISPID const    m_dispid;
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/* /////////////////////////////////////////////////////////////////////////
 * Implementation
 */

#ifndef VOLE_DOCUMENTATION_SKIP_SECTION

inline /* static */ invocation_exception::ctor_args_type invocation_exception::create_reason_(
    DISPID              /* dispid */
,   char const*         message
,   HRESULT             hr
,   EXCEPINFO const*    xinfo
)
{
    // TODO: incorporate DISPID into message (it not DISPID_UNKNOWN)

    if( DISP_E_EXCEPTION == hr &&
        NULL != xinfo)
    {
        if(FAILED(xinfo->scode))
        {
            hr = xinfo->scode;
        }
    }

#ifdef STLSOFT_CF_THROW_BAD_ALLOC
    try
    {
#endif /* STLSOFT_CF_THROW_BAD_ALLOC */

        typedef std::basic_string<char_type>  string_t;

#if 1
        if( NULL != xinfo &&
            0 != ::SysStringLen(xinfo->bstrDescription))
        {
            string_t reason(message);

            reason += ": ";
            reason += winstl::w2m(xinfo->bstrDescription, ::SysStringLen(xinfo->bstrDescription));

            // Now trim off all trailing periods
            for(; '.' == reason.c_str()[reason.length() - 1]; )
            {
                reason.resize(reason.length() - 1);
            }

            return ctor_args_type(string_type(reason.data(), reason.size()), hr);
        }
        else
        {
            comstl::errorinfo_desc  eid;

            if(0 != eid.length())
            {
                string_t reason(message);

                reason += ": ";
                reason += eid.c_str_a();

                return ctor_args_type(string_type(reason.data(), reason.size()), hr);
            }
        }
#else /* ? 0 */
        using stlsoft::exception_string_creator;

        UINT const len = (NULL != xinfo) ? ::SysStringLen(xinfo->bstrDescription) : 0u;

        if(0 != len)
        {
            exception_string_creator reason(message);

            reason.reserve(reason.size() + 2 + len);

            reason += ": ";
            reason.append(xinfo->bstrDescription, len);

            // Now trim off all trailing periods
            for(; '.' == reason.c_str()[reason.length() - 1]; )
            {
                reason.truncate(reason.length() - 1);
            }

            return ctor_args_type(reason.create(), hr);
        }
        else
        {
            comstl::errorinfo_desc  eid;

            if(0 != eid.length())
            {
                exception_string_creator reason(message);

                reason.reserve(reason.size() + 2 + eid.length());

                reason += ": ";
                reason += eid;

                return ctor_args_type(reason.create(), hr);
            }
        }
#endif /* 0 */

#ifdef STLSOFT_CF_THROW_BAD_ALLOC
    }
    catch(std::bad_alloc&)
    {
        // Consume
    }
#endif /* STLSOFT_CF_THROW_BAD_ALLOC */

    return ctor_args_type(string_type(message), hr);
}

#endif /* !VOLE_DOCUMENTATION_SKIP_SECTION */

/* ////////////////////////////////////////////////////////////////////// */

#ifndef VOLE_NO_NAMESPACE
} // namespace vole
#endif /* !VOLE_NO_NAMESPACE */

/* ////////////////////////////////////////////////////////////////////// */

#endif /* !VOLE_INCL_VOLE_UTIL_HPP_EXCEPTIONS */

/* ///////////////////////////// end of file //////////////////////////// */
<commit_msg>~ compatibility with STLSoft 1.10 beta 1<commit_after>/* /////////////////////////////////////////////////////////////////////////
 * File:        vole/error/exceptions.hpp
 *
 * Purpose:     Exceptions used by VOLE.
 *
 * Created:     4th January 2007
 * Updated:     18th December 2016
 *
 * Home:        http://vole.sourceforge.net/
 *
 * Copyright (c) 2007-2016, Matthew Wilson and Synesis Software
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
 *   any contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * ////////////////////////////////////////////////////////////////////// */

/** \file vole/error/exceptions.hpp
 *
 * \brief Exceptions used by VOLE.
 */

#ifndef VOLE_INCL_VOLE_UTIL_HPP_EXCEPTIONS
#define VOLE_INCL_VOLE_UTIL_HPP_EXCEPTIONS

#ifndef VOLE_DOCUMENTATION_SKIP_SECTION
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_MAJOR    1
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_MINOR    5
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_REVISION 4
# define VOLE_VER_VOLE_UTIL_HPP_EXCEPTIONS_EDIT     13
#endif /* !VOLE_DOCUMENTATION_SKIP_SECTION */

/* /////////////////////////////////////////////////////////////////////////
 * Includes
 */

#include <vole/util/common.hpp>

#if 0
#elif defined(VOLE_STLSOFT_1_10_B01_OR_LATER)
# ifndef COMSTL_INCL_COMSTL_EXCEPTION_HPP_COMSTL_EXCEPTION
#  include <comstl/exception/comstl_exception.hpp>
# endif /* !COMSTL_INCL_COMSTL_EXCEPTION_HPP_COMSTL_EXCEPTION */
#else
# ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
#  include <comstl/error/exceptions.hpp>
# endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
#endif
#ifndef COMSTL_INCL_COMSTL_ERROR_HPP_ERRORINFO_DESC
# include <comstl/error/errorinfo_desc.hpp>
#endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_ERRORINFO_DESC */
#ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING
# include <stlsoft/util/exception_string.hpp>
#endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING */
//#ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING_CREATOR
//# include <stlsoft/util/exception_string_creator.hpp>
//#endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING_CREATOR */
#ifndef WINSTL_INCL_CONVERSION_HPP_W2M
# include <winstl/conversion/w2m.hpp>
#endif /* !WINSTL_INCL_CONVERSION_HPP_W2M */
#ifdef STLSOFT_CF_THROW_BAD_ALLOC
# include <new>
#endif /* STLSOFT_CF_THROW_BAD_ALLOC */
#include <string>

/* /////////////////////////////////////////////////////////////////////////
 * Namespace
 */

#ifndef VOLE_NO_NAMESPACE
namespace vole
{
#endif /* !VOLE_NO_NAMESPACE */

/* /////////////////////////////////////////////////////////////////////////
 * Macros
 */

/* /////////////////////////////////////////////////////////////////////////
 * Functions
 */

/* /////////////////////////////////////////////////////////////////////////
 * Classes
 */

/// Root exception class for VOLE
class vole_exception
    : public comstl::com_exception
{
/// \name Member Types
/// @{
protected:
    typedef char                        char_type;
public:
    typedef vole_exception              class_type;
    typedef comstl::com_exception       parent_class_type;
protected:
    typedef stlsoft::exception_string   string_type;
    struct ctor_args_type
    {
        string_type message;
        HRESULT     hr;

        ctor_args_type()
            : message()
            , hr(E_FAIL)
        {}
        explicit ctor_args_type(string_type const& message, HRESULT hr)
            : message(message)
            , hr(hr)
        {}
    };
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    vole_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
protected:
    vole_exception(ctor_args_type const& args)
        : parent_class_type(args.message.c_str(), args.hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a vole::object (or vole::collection) instance is
/// not connected to its underlying COM Automation server
class object_not_connected_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef object_not_connected_exception  class_type;
    typedef vole_exception                  parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    object_not_connected_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a COM Automation server instance cannot be created
class creation_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef creation_exception      class_type;
    typedef vole_exception          parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    creation_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a type conversion cannot be performed
class type_conversion_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef type_conversion_exception   class_type;
    typedef vole_exception              parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The HRESULT associated with the exception
    type_conversion_exception(char const* message, HRESULT hr)
        : parent_class_type(message, hr)
    {}
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/// Exception thrown when a method/property cannot be described or invoked
class invocation_exception
    : public vole_exception
{
/// \name Member Types
/// @{
public:
    typedef invocation_exception            class_type;
    typedef vole_exception                  parent_class_type;
/// @}

/// \name Construction
/// @{
public:
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param message The message to be carried in the exception
    /// \param hr The \c HRESULT associated with the exception
    /// \param xinfo Optional pointer to an EXCEPINFO structure
    ///   associated with the failed operation
    invocation_exception(char const* message, HRESULT hr, EXCEPINFO const* xinfo = NULL)
        : parent_class_type(create_reason_(DISPID_UNKNOWN, message, hr, xinfo))
        , m_dispid(DISPID_UNKNOWN)
    {}
    /// Construct an instance of the exception from a message and an HRESULT
    ///
    /// \param dispid The \c DISPID of the method/property invoked
    /// \param message The message to be carried in the exception
    /// \param hr The \c HRESULT associated with the exception
    /// \param xinfo Optional pointer to an EXCEPINFO structure
    ///   associated with the failed operation
    invocation_exception(DISPID dispid, char const* message, HRESULT hr, EXCEPINFO const* xinfo = NULL)
        : parent_class_type(create_reason_(dispid, message, hr, xinfo))
        , m_dispid(dispid)
    {}
/// @}

/// \name Accessors
/// @{
public:
    /// The \c DISPID associated with the exception, or \c DISPID_UNKNOWN if
    /// no identifier was given/specified.
    HRESULT get_dispid() const
    {
        return m_dispid;
    }

/// @}

/// \name Implementation
/// @{
private:
    static ctor_args_type create_reason_(DISPID dispid, char const* message, HRESULT hr, EXCEPINFO const* xinfo);
/// @}

/// \name Members
/// @{
private:
    DISPID const    m_dispid;
/// @}

/// \name Not to be implemented
/// @{
private:
    class_type& operator =(class_type const&);
/// @}
};

/* /////////////////////////////////////////////////////////////////////////
 * Implementation
 */

#ifndef VOLE_DOCUMENTATION_SKIP_SECTION

inline /* static */ invocation_exception::ctor_args_type invocation_exception::create_reason_(
    DISPID              /* dispid */
,   char const*         message
,   HRESULT             hr
,   EXCEPINFO const*    xinfo
)
{
    // TODO: incorporate DISPID into message (it not DISPID_UNKNOWN)

    if( DISP_E_EXCEPTION == hr &&
        NULL != xinfo)
    {
        if(FAILED(xinfo->scode))
        {
            hr = xinfo->scode;
        }
    }

#ifdef STLSOFT_CF_THROW_BAD_ALLOC
    try
    {
#endif /* STLSOFT_CF_THROW_BAD_ALLOC */

        typedef std::basic_string<char_type>  string_t;

#if 1
        if( NULL != xinfo &&
            0 != ::SysStringLen(xinfo->bstrDescription))
        {
            string_t reason(message);

            reason += ": ";
            reason += winstl::w2m(xinfo->bstrDescription, ::SysStringLen(xinfo->bstrDescription));

            // Now trim off all trailing periods
            for(; '.' == reason.c_str()[reason.length() - 1]; )
            {
                reason.resize(reason.length() - 1);
            }

            return ctor_args_type(string_type(reason.data(), reason.size()), hr);
        }
        else
        {
            comstl::errorinfo_desc  eid;

            if(0 != eid.length())
            {
                string_t reason(message);

                reason += ": ";
                reason += eid.c_str_a();

                return ctor_args_type(string_type(reason.data(), reason.size()), hr);
            }
        }
#else /* ? 0 */
        using stlsoft::exception_string_creator;

        UINT const len = (NULL != xinfo) ? ::SysStringLen(xinfo->bstrDescription) : 0u;

        if(0 != len)
        {
            exception_string_creator reason(message);

            reason.reserve(reason.size() + 2 + len);

            reason += ": ";
            reason.append(xinfo->bstrDescription, len);

            // Now trim off all trailing periods
            for(; '.' == reason.c_str()[reason.length() - 1]; )
            {
                reason.truncate(reason.length() - 1);
            }

            return ctor_args_type(reason.create(), hr);
        }
        else
        {
            comstl::errorinfo_desc  eid;

            if(0 != eid.length())
            {
                exception_string_creator reason(message);

                reason.reserve(reason.size() + 2 + eid.length());

                reason += ": ";
                reason += eid;

                return ctor_args_type(reason.create(), hr);
            }
        }
#endif /* 0 */

#ifdef STLSOFT_CF_THROW_BAD_ALLOC
    }
    catch(std::bad_alloc&)
    {
        // Consume
    }
#endif /* STLSOFT_CF_THROW_BAD_ALLOC */

    return ctor_args_type(string_type(message), hr);
}

#endif /* !VOLE_DOCUMENTATION_SKIP_SECTION */

/* ////////////////////////////////////////////////////////////////////// */

#ifndef VOLE_NO_NAMESPACE
} // namespace vole
#endif /* !VOLE_NO_NAMESPACE */

/* ////////////////////////////////////////////////////////////////////// */

#endif /* !VOLE_INCL_VOLE_UTIL_HPP_EXCEPTIONS */

/* ///////////////////////////// end of file //////////////////////////// */
<|endoftext|>


<commit_before><commit_msg>*** empty log message ***<commit_after><|endoftext|>


<commit_before>#include "libtest.h"

using namespace std;
#include "../lib/json/json.h"

void test_empty_dict(){

    string message = "{}";

    JsonValue * value = JsonValue::fromString(message);

    ASSERT_NOT_NULL(value, "Parsing not null");

    JsonDict* dict_p = JDICT(value);
    ASSERT_NOT_NULL(dict_p, "Dict not null");

    ASSERT(dict_p->size() == 0, "Empty dict");
}

void test_empty_list(){
    string message = "[]";

    JsonValue * value = JsonValue::fromString(message);
    ASSERT_NOT_NULL(value, "Parsing not null");

    JsonDict* dict_p = JDICT(value);
    ASSERT_NOT_NULL(dict_p, "List not null");

    ASSERT(dict_p->size() == 0, "Empty list");
}

void test_assert_equal(){
    ASSERT_EQUAL(5.0, 5, "egaux");
}

#define TESTVEC {T(test_empty_dict), T(test_empty_list), T(test_assert_equal)}
TEST();
<commit_msg>[code/test] Added empty string test for JsonString.<commit_after>#include "libtest.h"

using namespace std;
#include "../lib/json/json.h"

void test_empty_dict(){

    string message = "{}";

    JsonValue * value = JsonValue::fromString(message);

    ASSERT_NOT_NULL(value, "Parsing not null");

    JsonDict* dict_p = JDICT(value);
    ASSERT_NOT_NULL(dict_p, "Dict not null");

    ASSERT(dict_p->size() == 0, "Empty dict");
}

void test_empty_list(){
    string message = "[]";

    JsonValue * value = JsonValue::fromString(message);
    ASSERT_NOT_NULL(value, "Parsing not null");

    JsonDict* dict_p = JDICT(value);
    ASSERT_NOT_NULL(dict_p, "List not null");

    ASSERT(dict_p->size() == 0, "Empty list");
}

void test_empty_string(){
    string message = "\"\"";

    JsonValue * value = JsonValue::fromString(message);
    ASSERT_NOT_NULL(value, "Parsing not null");

    JsonString* string_p = JSTRING(value);
    ASSERT_NOT_NULL(string_p, "String not null");

    ASSERT_EQUAL((string) *string_p, "", "Empty string");

}

#define TESTVEC {T(test_empty_dict), T(test_empty_list), T(test_empty_string)}
TEST();
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "DriverStation.h"

#include "LibDS/DS_Timers.h"
#include "LibDS/DS_Client.h"
#include "LibDS/DS_NetConsole.h"
#include "LibDS/DS_ElapsedTime.h"
#include "LibDS/DS_ProtocolManager.h"

#include "LibDS/DS_Protocol.h"
#include "LibDS/DS_Protocol2014.h"
#include "LibDS/DS_Protocol2015.h"

#include <QDebug>

DriverStation* DriverStation::m_instance = Q_NULLPTR;

DriverStation::DriverStation() {
    m_init = false;

    /* Initialize private members */
    m_client      = new DS_Client;
    m_netConsole  = new DS_NetConsole;
    m_elapsedTime = new DS_ElapsedTime;
    m_manager     = new DS_ProtocolManager;

    /* Update internal values and notify object on robot status events */
    connect (m_manager, SIGNAL (codeChanged           (bool)),
             this,      SLOT   (updateStatus          (bool)));
    connect (m_manager, SIGNAL (communicationsChanged (bool)),
             this,      SLOT   (updateStatus          (bool)));
    connect (m_manager, SIGNAL (controlModeChanged    (DS_ControlMode)),
             this,      SLOT   (onControlModeChanged  (DS_ControlMode)));
    connect (m_manager, SIGNAL (codeChanged           (bool)),
             this,      SIGNAL (codeChanged           (bool)));
    connect (m_manager, SIGNAL (communicationsChanged (bool)),
             this,      SIGNAL (communicationsChanged (bool)));
    connect (m_manager, SIGNAL (controlModeChanged    (DS_ControlMode)),
             this,      SIGNAL (controlModeChanged    (DS_ControlMode)));
    connect (m_manager, SIGNAL (diskUsageChanged      (int, int)),
             this,      SIGNAL (diskUsageChanged      (int, int)));
    connect (m_manager, SIGNAL (ramUsageChanged       (int, int)),
             this,      SIGNAL (ramUsageChanged       (int, int)));
    connect (m_manager, SIGNAL (voltageChanged        (QString)),
             this,      SIGNAL (voltageChanged        (QString)));

    /* Robot information has changed */
    connect (m_manager, SIGNAL (libVersionChanged (QString)),
             this,      SIGNAL (libVersionChanged (QString)));
    connect (m_manager, SIGNAL (rioVersionChanged (QString)),
             this,      SIGNAL (rioVersionChanged (QString)));
    connect (m_manager, SIGNAL (pcmVersionChanged (QString)),
             this,      SIGNAL (pcmVersionChanged (QString)));
    connect (m_manager, SIGNAL (pdpVersionChanged (QString)),
             this,      SIGNAL (pdpVersionChanged (QString)));

    /* Sync robot address and calculated IPs automatically */
    connect (m_manager, SIGNAL (robotAddressChanged (QString)),
             m_client,  SLOT   (setRobotAddress     (QString)));

    /* Update the elapsed time text automatically */
    connect (m_elapsedTime, SIGNAL (elapsedTimeChanged (QString)),
             this,          SIGNAL (elapsedTimeChanged (QString)));

    /* New NetConsole message received */
    connect (m_netConsole,  SIGNAL (newMessage (QString)),
             this,          SIGNAL (newNetConsoleMessage (QString)));

    /* Send and read robot packets */
    connect (m_manager, SIGNAL (packetReceived()),
             this,      SLOT   (sendRobotPackets()));
    connect (m_client,  SIGNAL (dataReceived  (QByteArray)),
             m_manager, SLOT   (readRobotData (QByteArray)));
    connect (DS_Timers::getInstance(), SIGNAL (timeout20()),
             this,                     SLOT   (contactRobot()));
}

DriverStation::~DriverStation() {
    delete m_client;
    delete m_manager;
    delete m_netConsole;
    delete m_elapsedTime;

    delete m_instance;
}

DriverStation* DriverStation::getInstance() {
    if (m_instance == Q_NULLPTR)
        m_instance = new DriverStation();

    return m_instance;
}

bool DriverStation::canBeEnabled() {
    return m_manager->protocol()->robotCode() &&
           m_manager->protocol()->robotCommunication();
}

QStringList DriverStation::alliances() {
    QStringList list;

    list.append ("Red 1");
    list.append ("Red 2");
    list.append ("Red 3");
    list.append ("Blue 1");
    list.append ("Blue 2");
    list.append ("Blue 3");

    return list;
}

QStringList DriverStation::protocols() {
    QStringList list;

    list.append ("2014 Protocol");
    list.append ("2015 Protocol");

    return list;
}

QString DriverStation::radioAddress() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->radioAddress();

    return "";
}

QString DriverStation::robotAddress() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->robotAddress();

    return "";
}

DS_ControlMode DriverStation::controlMode() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->controlMode();

    return DS_ControlNoCommunication;
}

bool DriverStation::robotHasCode() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->robotCode();

    return false;
}

bool DriverStation::networkAvailable() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->robotCommunication();

    return false;
}

void DriverStation::init() {
    if (!m_init) {
        m_init = true;
        resetInternalValues();
        DS_Timers::getInstance()->start();
    }
}

void DriverStation::reboot() {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->reboot();
}

void DriverStation::restartCode() {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->restartCode();
}

void DriverStation::startPractice (int countdown,
                                   int autonomous,
                                   int delay,
                                   int teleop,
                                   int endgame) {
    Q_UNUSED (countdown);
    Q_UNUSED (autonomous);
    Q_UNUSED (delay);
    Q_UNUSED (teleop);
    Q_UNUSED (endgame);
}

void DriverStation::setProtocol (DS_Protocol* protocol) {
    if (protocol != Q_NULLPTR) {
        m_manager->setProtocol (protocol);
        m_client->setRobotPort (protocol->robotPort());
        m_client->setClientPort (protocol->clientPort());
    }
}

void DriverStation::setProtocol (ProtocolType protocol) {
    switch (protocol) {
    case Protocol2014:
        setProtocol (new DS_Protocol2014);
        break;
    case Protocol2015:
        setProtocol (new DS_Protocol2015);
        break;
    default:
        qWarning() << Q_FUNC_INFO << "Invalid protocol" << protocol;
        break;
    }
}

void DriverStation::setTeamNumber (int team) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->setTeamNumber (team);
}

void DriverStation::setAlliance (AllianceType allianceType) {
    DS_Alliance alliance;

    switch (allianceType) {
    case Red1:
        alliance = DS_AllianceRed1;
        break;
    case Red2:
        alliance = DS_AllianceRed2;
        break;
    case Red3:
        alliance = DS_AllianceRed3;
        break;
    case Blue1:
        alliance = DS_AllianceBlue1;
        break;
    case Blue2:
        alliance = DS_AllianceBlue2;
        break;
    case Blue3:
        alliance = DS_AllianceBlue3;
        break;
    default:
        alliance = DS_AllianceRed1;
        break;
    }

    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->setAlliance (alliance);
}

void DriverStation::setControlMode (DS_ControlMode mode) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->setControlMode (mode);
}

void DriverStation::setCustomAddress (QString address) {
    if (m_manager->protocolIsValid())
        m_manager->protocol()->setRobotAddress (address);
}

void DriverStation::clearJoysticks() {
    m_manager->clearJoysticks();
}

void DriverStation::updateJoystickPovHat (int js, int hat, int angle) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->updateJoystickPovHat (js, hat, angle);
}

void DriverStation::addJoystick (int axes, int buttons, int povHats) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->addJoystick (axes, buttons, povHats);
}

void DriverStation::updateJoystickAxis (int js, int axis, double value) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->updateJoystickAxis (js, axis, value);
}

void DriverStation::updateJoystickButton (int js, int button, bool state) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->updateJoystickButton (js, button, state);
}

void DriverStation::resetInternalValues() {
    m_elapsedTime->reset();
    m_elapsedTime->stop();

    emit codeChanged (false);
    emit communicationsChanged (false);
    emit voltageChanged (QString (""));
    emit elapsedTimeChanged ("00:00.0");
}

void DriverStation::sendRobotPackets() {
    if (m_manager->protocolIsValid() && m_init)
        m_client->sendToRobot (m_manager->protocol()->generateClientPacket());
}

void DriverStation::contactRobot() {
    if (m_manager->protocolIsValid() && m_init) {
        if (!m_manager->protocol()->robotCommunication())
            sendRobotPackets();
    }
}

QString DriverStation::getStatus() {
    if (m_manager->protocolIsValid() && m_init) {
        if (m_manager->protocol()->robotCommunication()
                && !m_manager->protocol()->robotCode())
            return "No Robot Code";

        return DS_GetControlModeString (m_manager->protocol()->controlMode());
    }

    return DS_GetControlModeString (DS_ControlNoCommunication);
}

void DriverStation::updateStatus (bool ignore_me) {
    Q_UNUSED (ignore_me);
    emit robotStatusChanged (getStatus());
}

void DriverStation::onControlModeChanged (DS_ControlMode mode) {
    if ((mode == DS_ControlDisabled
            || mode == DS_ControlEmergencyStop
            || mode == DS_ControlNoCommunication))
        m_elapsedTime->stop();

    else
        m_elapsedTime->reset();

    emit robotStatusChanged (getStatus());
}
<commit_msg>Update DriverStation.cpp<commit_after>/*
 * Copyright (c) 2015 WinT 3794 <http://wint3794.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "DriverStation.h"

#include "LibDS/DS_Timers.h"
#include "LibDS/DS_Client.h"
#include "LibDS/DS_NetConsole.h"
#include "LibDS/DS_ElapsedTime.h"
#include "LibDS/DS_ProtocolManager.h"

#include "LibDS/DS_Protocol.h"
#include "LibDS/DS_Protocol2014.h"
#include "LibDS/DS_Protocol2015.h"

#include <QDebug>
#include <QStringList>

DriverStation* DriverStation::m_instance = Q_NULLPTR;

DriverStation::DriverStation() {
    m_init = false;

    /* Initialize private members */
    m_client      = new DS_Client;
    m_netConsole  = new DS_NetConsole;
    m_elapsedTime = new DS_ElapsedTime;
    m_manager     = new DS_ProtocolManager;

    /* Update internal values and notify object on robot status events */
    connect (m_manager, SIGNAL (codeChanged           (bool)),
             this,      SLOT   (updateStatus          (bool)));
    connect (m_manager, SIGNAL (communicationsChanged (bool)),
             this,      SLOT   (updateStatus          (bool)));
    connect (m_manager, SIGNAL (controlModeChanged    (DS_ControlMode)),
             this,      SLOT   (onControlModeChanged  (DS_ControlMode)));
    connect (m_manager, SIGNAL (codeChanged           (bool)),
             this,      SIGNAL (codeChanged           (bool)));
    connect (m_manager, SIGNAL (communicationsChanged (bool)),
             this,      SIGNAL (communicationsChanged (bool)));
    connect (m_manager, SIGNAL (controlModeChanged    (DS_ControlMode)),
             this,      SIGNAL (controlModeChanged    (DS_ControlMode)));
    connect (m_manager, SIGNAL (diskUsageChanged      (int, int)),
             this,      SIGNAL (diskUsageChanged      (int, int)));
    connect (m_manager, SIGNAL (ramUsageChanged       (int, int)),
             this,      SIGNAL (ramUsageChanged       (int, int)));
    connect (m_manager, SIGNAL (voltageChanged        (QString)),
             this,      SIGNAL (voltageChanged        (QString)));

    /* Robot information has changed */
    connect (m_manager, SIGNAL (libVersionChanged (QString)),
             this,      SIGNAL (libVersionChanged (QString)));
    connect (m_manager, SIGNAL (rioVersionChanged (QString)),
             this,      SIGNAL (rioVersionChanged (QString)));
    connect (m_manager, SIGNAL (pcmVersionChanged (QString)),
             this,      SIGNAL (pcmVersionChanged (QString)));
    connect (m_manager, SIGNAL (pdpVersionChanged (QString)),
             this,      SIGNAL (pdpVersionChanged (QString)));

    /* Sync robot address and calculated IPs automatically */
    connect (m_manager, SIGNAL (robotAddressChanged (QString)),
             m_client,  SLOT   (setRobotAddress     (QString)));

    /* Update the elapsed time text automatically */
    connect (m_elapsedTime, SIGNAL (elapsedTimeChanged (QString)),
             this,          SIGNAL (elapsedTimeChanged (QString)));

    /* New NetConsole message received */
    connect (m_netConsole,  SIGNAL (newMessage (QString)),
             this,          SIGNAL (newNetConsoleMessage (QString)));

    /* Send and read robot packets */
    connect (m_manager, SIGNAL (packetReceived()),
             this,      SLOT   (sendRobotPackets()));
    connect (m_client,  SIGNAL (dataReceived  (QByteArray)),
             m_manager, SLOT   (readRobotData (QByteArray)));
    connect (DS_Timers::getInstance(), SIGNAL (timeout20()),
             this,                     SLOT   (contactRobot()));
}

DriverStation::~DriverStation() {
    delete m_client;
    delete m_manager;
    delete m_netConsole;
    delete m_elapsedTime;

    delete m_instance;
}

DriverStation* DriverStation::getInstance() {
    if (m_instance == Q_NULLPTR)
        m_instance = new DriverStation();

    return m_instance;
}

bool DriverStation::canBeEnabled() {
    return m_manager->protocol()->robotCode() &&
           m_manager->protocol()->robotCommunication();
}

QStringList DriverStation::alliances() {
    QStringList list;

    list.append ("Red 1");
    list.append ("Red 2");
    list.append ("Red 3");
    list.append ("Blue 1");
    list.append ("Blue 2");
    list.append ("Blue 3");

    return list;
}

QStringList DriverStation::protocols() {
    QStringList list;

    list.append ("2014 Protocol");
    list.append ("2015 Protocol");

    return list;
}

QString DriverStation::radioAddress() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->radioAddress();

    return "";
}

QString DriverStation::robotAddress() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->robotAddress();

    return "";
}

DS_ControlMode DriverStation::controlMode() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->controlMode();

    return DS_ControlNoCommunication;
}

bool DriverStation::robotHasCode() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->robotCode();

    return false;
}

bool DriverStation::networkAvailable() {
    if (m_manager->protocolIsValid())
        return m_manager->protocol()->robotCommunication();

    return false;
}

void DriverStation::init() {
    if (!m_init) {
        m_init = true;
        resetInternalValues();
        DS_Timers::getInstance()->start();
    }
}

void DriverStation::reboot() {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->reboot();
}

void DriverStation::restartCode() {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->restartCode();
}

void DriverStation::startPractice (int countdown,
                                   int autonomous,
                                   int delay,
                                   int teleop,
                                   int endgame) {
    Q_UNUSED (countdown);
    Q_UNUSED (autonomous);
    Q_UNUSED (delay);
    Q_UNUSED (teleop);
    Q_UNUSED (endgame);
}

void DriverStation::setProtocol (DS_Protocol* protocol) {
    if (protocol != Q_NULLPTR) {
        m_manager->setProtocol (protocol);
        m_client->setRobotPort (protocol->robotPort());
        m_client->setClientPort (protocol->clientPort());
    }
}

void DriverStation::setProtocol (ProtocolType protocol) {
    switch (protocol) {
    case Protocol2014:
        setProtocol (new DS_Protocol2014);
        break;
    case Protocol2015:
        setProtocol (new DS_Protocol2015);
        break;
    default:
        qWarning() << Q_FUNC_INFO << "Invalid protocol" << protocol;
        break;
    }
}

void DriverStation::setTeamNumber (int team) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->setTeamNumber (team);
}

void DriverStation::setAlliance (AllianceType allianceType) {
    DS_Alliance alliance;

    switch (allianceType) {
    case Red1:
        alliance = DS_AllianceRed1;
        break;
    case Red2:
        alliance = DS_AllianceRed2;
        break;
    case Red3:
        alliance = DS_AllianceRed3;
        break;
    case Blue1:
        alliance = DS_AllianceBlue1;
        break;
    case Blue2:
        alliance = DS_AllianceBlue2;
        break;
    case Blue3:
        alliance = DS_AllianceBlue3;
        break;
    default:
        alliance = DS_AllianceRed1;
        break;
    }

    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->setAlliance (alliance);
}

void DriverStation::setControlMode (DS_ControlMode mode) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->protocol()->setControlMode (mode);
}

void DriverStation::setCustomAddress (QString address) {
    if (m_manager->protocolIsValid())
        m_manager->protocol()->setRobotAddress (address);
}

void DriverStation::clearJoysticks() {
    m_manager->clearJoysticks();
}

void DriverStation::updateJoystickPovHat (int js, int hat, int angle) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->updateJoystickPovHat (js, hat, angle);
}

void DriverStation::addJoystick (int axes, int buttons, int povHats) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->addJoystick (axes, buttons, povHats);
}

void DriverStation::updateJoystickAxis (int js, int axis, double value) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->updateJoystickAxis (js, axis, value);
}

void DriverStation::updateJoystickButton (int js, int button, bool state) {
    if (m_manager->protocolIsValid() && m_init)
        m_manager->updateJoystickButton (js, button, state);
}

void DriverStation::resetInternalValues() {
    m_elapsedTime->reset();
    m_elapsedTime->stop();

    emit codeChanged (false);
    emit communicationsChanged (false);
    emit voltageChanged (QString (""));
    emit elapsedTimeChanged ("00:00.0");
}

void DriverStation::sendRobotPackets() {
    if (m_manager->protocolIsValid() && m_init)
        m_client->sendToRobot (m_manager->protocol()->generateClientPacket());
}

void DriverStation::contactRobot() {
    if (m_manager->protocolIsValid() && m_init) {
        if (!m_manager->protocol()->robotCommunication())
            sendRobotPackets();
    }
}

QString DriverStation::getStatus() {
    if (m_manager->protocolIsValid() && m_init) {
        if (m_manager->protocol()->robotCommunication()
                && !m_manager->protocol()->robotCode())
            return "No Robot Code";

        return DS_GetControlModeString (m_manager->protocol()->controlMode());
    }

    return DS_GetControlModeString (DS_ControlNoCommunication);
}

void DriverStation::updateStatus (bool ignore_me) {
    Q_UNUSED (ignore_me);
    emit robotStatusChanged (getStatus());
}

void DriverStation::onControlModeChanged (DS_ControlMode mode) {
    if ((mode == DS_ControlDisabled
            || mode == DS_ControlEmergencyStop
            || mode == DS_ControlNoCommunication))
        m_elapsedTime->stop();

    else
        m_elapsedTime->reset();

    emit robotStatusChanged (getStatus());
}
<|endoftext|>


<commit_before><commit_msg>am 2ed7af23: am 7326ff0a: Merge "Fix build, missing spaces around =/<."<commit_after><|endoftext|>