mirror of
				https://github.com/paboyle/Grid.git
				synced 2025-11-03 21:44:33 +00:00 
			
		
		
		
	Merge branch 'develop' into feature/bgq-asm
This commit is contained in:
		@@ -32,6 +32,7 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
  // Vector IO utilities ///////////////////////////////////////////////////////
 | 
			
		||||
  // helper function to read space-separated values
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  std::vector<T> strToVec(const std::string s)
 | 
			
		||||
@@ -67,6 +68,77 @@ namespace Grid {
 | 
			
		||||
    return os;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Vector element trait //////////////////////////////////////////////////////  
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  struct element
 | 
			
		||||
  {
 | 
			
		||||
    typedef T type;
 | 
			
		||||
    static constexpr bool is_number = false;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  struct element<std::vector<T>>
 | 
			
		||||
  {
 | 
			
		||||
    typedef typename element<T>::type type;
 | 
			
		||||
    static constexpr bool is_number = std::is_arithmetic<T>::value
 | 
			
		||||
                                      or is_complex<T>::value
 | 
			
		||||
                                      or element<T>::is_number;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // Vector flatening utility class ////////////////////////////////////////////
 | 
			
		||||
  // Class to flatten a multidimensional std::vector
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  class Flatten
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    typedef typename element<V>::type Element;
 | 
			
		||||
  public:
 | 
			
		||||
    explicit                     Flatten(const V &vector);
 | 
			
		||||
    const V &                    getVector(void);
 | 
			
		||||
    const std::vector<Element> & getFlatVector(void);
 | 
			
		||||
    const std::vector<size_t>  & getDim(void);
 | 
			
		||||
  private:
 | 
			
		||||
    void accumulate(const Element &e);
 | 
			
		||||
    template <typename W>
 | 
			
		||||
    void accumulate(const W &v);
 | 
			
		||||
    void accumulateDim(const Element &e);
 | 
			
		||||
    template <typename W>
 | 
			
		||||
    void accumulateDim(const W &v);
 | 
			
		||||
  private:
 | 
			
		||||
    const V              &vector_;
 | 
			
		||||
    std::vector<Element> flatVector_;
 | 
			
		||||
    std::vector<size_t>  dim_;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  // Class to reconstruct a multidimensional std::vector
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  class Reconstruct
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    typedef typename element<V>::type Element;
 | 
			
		||||
  public:
 | 
			
		||||
    Reconstruct(const std::vector<Element> &flatVector,
 | 
			
		||||
                const std::vector<size_t> &dim);
 | 
			
		||||
    const V &                    getVector(void);
 | 
			
		||||
    const std::vector<Element> & getFlatVector(void);
 | 
			
		||||
    const std::vector<size_t>  & getDim(void);
 | 
			
		||||
  private:
 | 
			
		||||
    void fill(std::vector<Element> &v);
 | 
			
		||||
    template <typename W>
 | 
			
		||||
    void fill(W &v);
 | 
			
		||||
    void resize(std::vector<Element> &v, const unsigned int dim);
 | 
			
		||||
    template <typename W>
 | 
			
		||||
    void resize(W &v, const unsigned int dim);
 | 
			
		||||
  private:
 | 
			
		||||
    V                          vector_;
 | 
			
		||||
    const std::vector<Element> &flatVector_;
 | 
			
		||||
    std::vector<size_t>        dim_;
 | 
			
		||||
    size_t                     ind_{0};
 | 
			
		||||
    unsigned int               dimInd_{0};
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // Abstract writer/reader classes ////////////////////////////////////////////
 | 
			
		||||
  // static polymorphism implemented using CRTP idiom
 | 
			
		||||
  class Serializable;
 | 
			
		||||
  
 | 
			
		||||
@@ -83,12 +155,7 @@ namespace Grid {
 | 
			
		||||
    typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
 | 
			
		||||
    write(const std::string& s, const U &output);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<std::is_enum<U>::value, void>::type
 | 
			
		||||
    write(const std::string& s, const U &output);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<
 | 
			
		||||
      !(std::is_base_of<Serializable, U>::value or std::is_enum<U>::value),
 | 
			
		||||
      void>::type
 | 
			
		||||
    typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
 | 
			
		||||
    write(const std::string& s, const U &output);
 | 
			
		||||
  private:
 | 
			
		||||
    T *upcast;
 | 
			
		||||
@@ -107,12 +174,7 @@ namespace Grid {
 | 
			
		||||
    typename std::enable_if<std::is_base_of<Serializable, U>::value, void>::type
 | 
			
		||||
    read(const std::string& s, U &output);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<std::is_enum<U>::value, void>::type
 | 
			
		||||
    read(const std::string& s, U &output);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<
 | 
			
		||||
      !(std::is_base_of<Serializable, U>::value or std::is_enum<U>::value),
 | 
			
		||||
      void>::type
 | 
			
		||||
    typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
 | 
			
		||||
    read(const std::string& s, U &output);
 | 
			
		||||
  protected:
 | 
			
		||||
    template <typename U>
 | 
			
		||||
@@ -142,7 +204,128 @@ namespace Grid {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // Generic writer interface
 | 
			
		||||
  // Flatten class template implementation /////////////////////////////////////
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  void Flatten<V>::accumulate(const Element &e)
 | 
			
		||||
  {
 | 
			
		||||
    flatVector_.push_back(e);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  template <typename W>
 | 
			
		||||
  void Flatten<V>::accumulate(const W &v)
 | 
			
		||||
  {
 | 
			
		||||
    for (auto &e: v)
 | 
			
		||||
    {
 | 
			
		||||
      accumulate(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  void Flatten<V>::accumulateDim(const Element &e) {};
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  template <typename W>
 | 
			
		||||
  void Flatten<V>::accumulateDim(const W &v)
 | 
			
		||||
  {
 | 
			
		||||
    dim_.push_back(v.size());
 | 
			
		||||
    accumulateDim(v[0]);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  Flatten<V>::Flatten(const V &vector)
 | 
			
		||||
  : vector_(vector)
 | 
			
		||||
  {
 | 
			
		||||
    accumulate(vector_);
 | 
			
		||||
    accumulateDim(vector_);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  const V & Flatten<V>::getVector(void)
 | 
			
		||||
  {
 | 
			
		||||
    return vector_;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  const std::vector<typename Flatten<V>::Element> &
 | 
			
		||||
  Flatten<V>::getFlatVector(void)
 | 
			
		||||
  {
 | 
			
		||||
    return flatVector_;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  const std::vector<size_t> & Flatten<V>::getDim(void)
 | 
			
		||||
  {
 | 
			
		||||
    return dim_;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Reconstruct class template implementation /////////////////////////////////
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  void Reconstruct<V>::fill(std::vector<Element> &v)
 | 
			
		||||
  {
 | 
			
		||||
    for (auto &e: v)
 | 
			
		||||
    {
 | 
			
		||||
      e = flatVector_[ind_++];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  template <typename W>
 | 
			
		||||
  void Reconstruct<V>::fill(W &v)
 | 
			
		||||
  {
 | 
			
		||||
    for (auto &e: v)
 | 
			
		||||
    {
 | 
			
		||||
      fill(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  void Reconstruct<V>::resize(std::vector<Element> &v, const unsigned int dim)
 | 
			
		||||
  {
 | 
			
		||||
    v.resize(dim_[dim]);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  template <typename W>
 | 
			
		||||
  void Reconstruct<V>::resize(W &v, const unsigned int dim)
 | 
			
		||||
  {
 | 
			
		||||
    v.resize(dim_[dim]);
 | 
			
		||||
    for (auto &e: v)
 | 
			
		||||
    {
 | 
			
		||||
      resize(e, dim + 1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  Reconstruct<V>::Reconstruct(const std::vector<Element> &flatVector,
 | 
			
		||||
                              const std::vector<size_t> &dim)
 | 
			
		||||
  : flatVector_(flatVector)
 | 
			
		||||
  , dim_(dim)
 | 
			
		||||
  {
 | 
			
		||||
    resize(vector_, 0);
 | 
			
		||||
    fill(vector_);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  const V & Reconstruct<V>::getVector(void)
 | 
			
		||||
  {
 | 
			
		||||
    return vector_;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  const std::vector<typename Reconstruct<V>::Element> &
 | 
			
		||||
  Reconstruct<V>::getFlatVector(void)
 | 
			
		||||
  {
 | 
			
		||||
    return flatVector_;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename V>
 | 
			
		||||
  const std::vector<size_t> & Reconstruct<V>::getDim(void)
 | 
			
		||||
  {
 | 
			
		||||
    return dim_;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Generic writer interface //////////////////////////////////////////////////
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  inline void push(Writer<T> &w, const std::string &s)
 | 
			
		||||
  {
 | 
			
		||||
@@ -221,23 +404,13 @@ namespace Grid {
 | 
			
		||||
  
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<std::is_enum<U>::value, void>::type
 | 
			
		||||
  Writer<T>::write(const std::string &s, const U &output)
 | 
			
		||||
  {
 | 
			
		||||
    EnumIO<U>::write(*this, s, output);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<
 | 
			
		||||
    !(std::is_base_of<Serializable, U>::value or std::is_enum<U>::value),
 | 
			
		||||
    void>::type
 | 
			
		||||
  typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
 | 
			
		||||
  Writer<T>::write(const std::string &s, const U &output)
 | 
			
		||||
  {
 | 
			
		||||
    upcast->writeDefault(s, output);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Reader template implementation ////////////////////////////////////////////
 | 
			
		||||
  // Reader template implementation
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  Reader<T>::Reader(void)
 | 
			
		||||
  {
 | 
			
		||||
@@ -266,17 +439,7 @@ namespace Grid {
 | 
			
		||||
  
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<std::is_enum<U>::value, void>::type
 | 
			
		||||
  Reader<T>::read(const std::string &s, U &output)
 | 
			
		||||
  {
 | 
			
		||||
    EnumIO<U>::read(*this, s, output);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<
 | 
			
		||||
    !(std::is_base_of<Serializable, U>::value or std::is_enum<U>::value),
 | 
			
		||||
    void>::type
 | 
			
		||||
  typename std::enable_if<!std::is_base_of<Serializable, U>::value, void>::type
 | 
			
		||||
  Reader<T>::read(const std::string &s, U &output)
 | 
			
		||||
  {
 | 
			
		||||
    upcast->readDefault(s, output);
 | 
			
		||||
@@ -300,7 +463,6 @@ namespace Grid {
 | 
			
		||||
      abort();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@ Author: paboyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
    See the full license in the file "LICENSE" in the top level distribution directory
 | 
			
		||||
    *************************************************************************************/
 | 
			
		||||
    /*  END LEGAL */
 | 
			
		||||
 | 
			
		||||
#include <Grid/GridCore.h>
 | 
			
		||||
 | 
			
		||||
using namespace Grid;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								lib/serialisation/Hdf5IO.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								lib/serialisation/Hdf5IO.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
#include <Grid/Grid.h>
 | 
			
		||||
 | 
			
		||||
using namespace Grid;
 | 
			
		||||
#ifndef H5_NO_NAMESPACE
 | 
			
		||||
using namespace H5NS;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Writer implementation ///////////////////////////////////////////////////////
 | 
			
		||||
Hdf5Writer::Hdf5Writer(const std::string &fileName)
 | 
			
		||||
: fileName_(fileName)
 | 
			
		||||
, file_(fileName.c_str(), H5F_ACC_TRUNC)
 | 
			
		||||
{
 | 
			
		||||
  group_ = file_.openGroup("/");
 | 
			
		||||
  writeSingleAttribute(dataSetThres_, HDF5_GRID_GUARD "dataset_threshold",
 | 
			
		||||
                       Hdf5Type<unsigned int>::type());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hdf5Writer::push(const std::string &s)
 | 
			
		||||
{
 | 
			
		||||
  group_ = group_.createGroup(s);
 | 
			
		||||
  path_.push_back(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hdf5Writer::pop(void)
 | 
			
		||||
{
 | 
			
		||||
  path_.pop_back();
 | 
			
		||||
  if (path_.empty())
 | 
			
		||||
  {
 | 
			
		||||
    group_ = file_.openGroup("/");
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    auto binOp = [](const std::string &a, const std::string &b)->std::string
 | 
			
		||||
    {
 | 
			
		||||
      return a + "/" + b;
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    group_ = group_.openGroup(std::accumulate(path_.begin(), path_.end(),
 | 
			
		||||
                                              std::string(""), binOp));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
void Hdf5Writer::writeDefault(const std::string &s, const std::string &x)
 | 
			
		||||
{
 | 
			
		||||
  StrType     strType(PredType::C_S1, x.size());
 | 
			
		||||
  
 | 
			
		||||
  writeSingleAttribute(*(x.data()), s, strType);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hdf5Writer::writeDefault(const std::string &s, const char *x)
 | 
			
		||||
{
 | 
			
		||||
  std::string sx(x);
 | 
			
		||||
  
 | 
			
		||||
  writeDefault(s, sx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reader implementation ///////////////////////////////////////////////////////
 | 
			
		||||
Hdf5Reader::Hdf5Reader(const std::string &fileName)
 | 
			
		||||
: fileName_(fileName)
 | 
			
		||||
, file_(fileName.c_str(), H5F_ACC_RDONLY)
 | 
			
		||||
{
 | 
			
		||||
  group_ = file_.openGroup("/");
 | 
			
		||||
  readSingleAttribute(dataSetThres_, HDF5_GRID_GUARD "dataset_threshold",
 | 
			
		||||
                      Hdf5Type<unsigned int>::type());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hdf5Reader::push(const std::string &s)
 | 
			
		||||
{
 | 
			
		||||
  group_ = group_.openGroup(s);
 | 
			
		||||
  path_.push_back(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hdf5Reader::pop(void)
 | 
			
		||||
{
 | 
			
		||||
  path_.pop_back();
 | 
			
		||||
  if (path_.empty())
 | 
			
		||||
  {
 | 
			
		||||
    group_ = file_.openGroup("/");
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    auto binOp = [](const std::string &a, const std::string &b)->std::string
 | 
			
		||||
    {
 | 
			
		||||
      return a + "/" + b;
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    group_ = group_.openGroup(std::accumulate(path_.begin(), path_.end(),
 | 
			
		||||
                                              std::string(""), binOp));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
void Hdf5Reader::readDefault(const std::string &s, std::string &x)
 | 
			
		||||
{
 | 
			
		||||
  Attribute attribute;
 | 
			
		||||
  
 | 
			
		||||
  attribute       = group_.openAttribute(s);
 | 
			
		||||
  StrType strType = attribute.getStrType();
 | 
			
		||||
  
 | 
			
		||||
  x.resize(strType.getSize());
 | 
			
		||||
  attribute.read(strType, &(x[0]));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										242
									
								
								lib/serialisation/Hdf5IO.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								lib/serialisation/Hdf5IO.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,242 @@
 | 
			
		||||
#ifndef GRID_SERIALISATION_HDF5_H
 | 
			
		||||
#define GRID_SERIALISATION_HDF5_H
 | 
			
		||||
 | 
			
		||||
#include <stack>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <H5Cpp.h>
 | 
			
		||||
#include "Hdf5Type.h"
 | 
			
		||||
 | 
			
		||||
#ifndef H5_NO_NAMESPACE
 | 
			
		||||
#define H5NS H5
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// default thresold above which datasets are used instead of attributes
 | 
			
		||||
#ifndef HDF5_DEF_DATASET_THRES
 | 
			
		||||
#define HDF5_DEF_DATASET_THRES 6u
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// name guard for Grid metadata
 | 
			
		||||
#define HDF5_GRID_GUARD "_Grid_"
 | 
			
		||||
 | 
			
		||||
namespace Grid
 | 
			
		||||
{
 | 
			
		||||
  class Hdf5Writer: public Writer<Hdf5Writer>
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    Hdf5Writer(const std::string &fileName);
 | 
			
		||||
    virtual ~Hdf5Writer(void) = default;
 | 
			
		||||
    void push(const std::string &s);
 | 
			
		||||
    void pop(void);
 | 
			
		||||
    void writeDefault(const std::string &s, const char *x);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    void writeDefault(const std::string &s, const U &x);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
    writeDefault(const std::string &s, const std::vector<U> &x);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
    writeDefault(const std::string &s, const std::vector<U> &x);
 | 
			
		||||
  private:
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    void writeSingleAttribute(const U &x, const std::string &name,
 | 
			
		||||
                              const H5NS::DataType &type);
 | 
			
		||||
  private:
 | 
			
		||||
    std::string              fileName_;
 | 
			
		||||
    std::vector<std::string> path_;
 | 
			
		||||
    H5NS::H5File             file_;
 | 
			
		||||
    H5NS::Group              group_;
 | 
			
		||||
    unsigned int             dataSetThres_{HDF5_DEF_DATASET_THRES};
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  class Hdf5Reader: public Reader<Hdf5Reader>
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    Hdf5Reader(const std::string &fileName);
 | 
			
		||||
    virtual ~Hdf5Reader(void) = default;
 | 
			
		||||
    void push(const std::string &s);
 | 
			
		||||
    void pop(void);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    void readDefault(const std::string &s, U &output);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
    readDefault(const std::string &s, std::vector<U> &x);
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
    readDefault(const std::string &s, std::vector<U> &x);
 | 
			
		||||
  private:
 | 
			
		||||
    template <typename U>
 | 
			
		||||
    void readSingleAttribute(U &x, const std::string &name,
 | 
			
		||||
                             const H5NS::DataType &type);
 | 
			
		||||
  private:
 | 
			
		||||
    std::string              fileName_;
 | 
			
		||||
    std::vector<std::string> path_;
 | 
			
		||||
    H5NS::H5File             file_;
 | 
			
		||||
    H5NS::Group              group_;
 | 
			
		||||
    unsigned int             dataSetThres_;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  // Writer template implementation ////////////////////////////////////////////
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  void Hdf5Writer::writeSingleAttribute(const U &x, const std::string &name,
 | 
			
		||||
                                        const H5NS::DataType &type)
 | 
			
		||||
  {
 | 
			
		||||
    H5NS::Attribute attribute;
 | 
			
		||||
    hsize_t         attrDim = 1;
 | 
			
		||||
    H5NS::DataSpace attrSpace(1, &attrDim);
 | 
			
		||||
    
 | 
			
		||||
    attribute = group_.createAttribute(name, type, attrSpace);
 | 
			
		||||
    attribute.write(type, &x);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  void Hdf5Writer::writeDefault(const std::string &s, const U &x)
 | 
			
		||||
  {
 | 
			
		||||
    writeSingleAttribute(x, s, Hdf5Type<U>::type());
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <>
 | 
			
		||||
  void Hdf5Writer::writeDefault(const std::string &s, const std::string &x);
 | 
			
		||||
  
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
  Hdf5Writer::writeDefault(const std::string &s, const std::vector<U> &x)
 | 
			
		||||
  {
 | 
			
		||||
    // alias to element type
 | 
			
		||||
    typedef typename element<std::vector<U>>::type Element;
 | 
			
		||||
    
 | 
			
		||||
    // flatten the vector and getting dimensions
 | 
			
		||||
    Flatten<std::vector<U>> flat(x);
 | 
			
		||||
    std::vector<hsize_t> dim;
 | 
			
		||||
    const auto           &flatx = flat.getFlatVector();
 | 
			
		||||
    
 | 
			
		||||
    for (auto &d: flat.getDim())
 | 
			
		||||
    {
 | 
			
		||||
      dim.push_back(d);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // write to file
 | 
			
		||||
    H5NS::DataSpace dataSpace(dim.size(), dim.data());
 | 
			
		||||
    
 | 
			
		||||
    if (flatx.size() > dataSetThres_)
 | 
			
		||||
    {
 | 
			
		||||
      H5NS::DataSet dataSet;
 | 
			
		||||
      
 | 
			
		||||
      dataSet = group_.createDataSet(s, Hdf5Type<Element>::type(), dataSpace);
 | 
			
		||||
      dataSet.write(flatx.data(), Hdf5Type<Element>::type());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      H5NS::Attribute attribute;
 | 
			
		||||
      
 | 
			
		||||
      attribute = group_.createAttribute(s, Hdf5Type<Element>::type(), dataSpace);
 | 
			
		||||
      attribute.write(Hdf5Type<Element>::type(), flatx.data());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
  Hdf5Writer::writeDefault(const std::string &s, const std::vector<U> &x)
 | 
			
		||||
  {
 | 
			
		||||
    push(s);
 | 
			
		||||
    writeSingleAttribute(x.size(), HDF5_GRID_GUARD "vector_size",
 | 
			
		||||
                         Hdf5Type<uint64_t>::type());
 | 
			
		||||
    for (hsize_t i = 0; i < x.size(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
      write(s + "_" + std::to_string(i), x[i]);
 | 
			
		||||
    }
 | 
			
		||||
    pop();
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Reader template implementation ////////////////////////////////////////////
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  void Hdf5Reader::readSingleAttribute(U &x, const std::string &name,
 | 
			
		||||
                                       const H5NS::DataType &type)
 | 
			
		||||
  {
 | 
			
		||||
    H5NS::Attribute attribute;
 | 
			
		||||
    
 | 
			
		||||
    attribute = group_.openAttribute(name);
 | 
			
		||||
    attribute.read(type, &x);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  void Hdf5Reader::readDefault(const std::string &s, U &output)
 | 
			
		||||
  {
 | 
			
		||||
    readSingleAttribute(output, s, Hdf5Type<U>::type());
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <>
 | 
			
		||||
  void Hdf5Reader::readDefault(const std::string &s, std::string &x);
 | 
			
		||||
  
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
  Hdf5Reader::readDefault(const std::string &s, std::vector<U> &x)
 | 
			
		||||
  {
 | 
			
		||||
    // alias to element type
 | 
			
		||||
    typedef typename element<std::vector<U>>::type Element;
 | 
			
		||||
    
 | 
			
		||||
    // read the dimensions
 | 
			
		||||
    H5NS::DataSpace       dataSpace;
 | 
			
		||||
    std::vector<hsize_t>  hdim;
 | 
			
		||||
    std::vector<size_t>   dim;
 | 
			
		||||
    hsize_t               size = 1;
 | 
			
		||||
    
 | 
			
		||||
    if (group_.attrExists(s))
 | 
			
		||||
    {
 | 
			
		||||
      dataSpace = group_.openAttribute(s).getSpace();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      dataSpace = group_.openDataSet(s).getSpace();
 | 
			
		||||
    }
 | 
			
		||||
    hdim.resize(dataSpace.getSimpleExtentNdims());
 | 
			
		||||
    dataSpace.getSimpleExtentDims(hdim.data());
 | 
			
		||||
    for (auto &d: hdim)
 | 
			
		||||
    {
 | 
			
		||||
      dim.push_back(d);
 | 
			
		||||
      size *= d;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // read the flat vector
 | 
			
		||||
    std::vector<Element> buf(size);
 | 
			
		||||
 | 
			
		||||
    if (size > dataSetThres_)
 | 
			
		||||
    {
 | 
			
		||||
      H5NS::DataSet dataSet;
 | 
			
		||||
      
 | 
			
		||||
      dataSet = group_.openDataSet(s);
 | 
			
		||||
      dataSet.read(buf.data(), Hdf5Type<Element>::type());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      H5NS::Attribute attribute;
 | 
			
		||||
      
 | 
			
		||||
      attribute = group_.openAttribute(s);
 | 
			
		||||
      attribute.read(Hdf5Type<Element>::type(), buf.data());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // reconstruct the multidimensional vector
 | 
			
		||||
    Reconstruct<std::vector<U>> r(buf, dim);
 | 
			
		||||
    
 | 
			
		||||
    x = r.getVector();
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  typename std::enable_if<!element<std::vector<U>>::is_number, void>::type
 | 
			
		||||
  Hdf5Reader::readDefault(const std::string &s, std::vector<U> &x)
 | 
			
		||||
  {
 | 
			
		||||
    uint64_t size;
 | 
			
		||||
    
 | 
			
		||||
    push(s);
 | 
			
		||||
    readSingleAttribute(size, HDF5_GRID_GUARD "vector_size",
 | 
			
		||||
                        Hdf5Type<uint64_t>::type());
 | 
			
		||||
    x.resize(size);
 | 
			
		||||
    for (hsize_t i = 0; i < x.size(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
      read(s + "_" + std::to_string(i), x[i]);
 | 
			
		||||
    }
 | 
			
		||||
    pop();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										77
									
								
								lib/serialisation/Hdf5Type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								lib/serialisation/Hdf5Type.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
#ifndef GRID_SERIALISATION_HDF5_TYPE_H
 | 
			
		||||
#define GRID_SERIALISATION_HDF5_TYPE_H
 | 
			
		||||
 | 
			
		||||
#include <H5Cpp.h>
 | 
			
		||||
#include <complex>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#ifndef H5_NO_NAMESPACE
 | 
			
		||||
#define H5NS H5
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define HDF5_NATIVE_TYPE(predType, cType)\
 | 
			
		||||
template <>\
 | 
			
		||||
class Hdf5Type<cType>\
 | 
			
		||||
{\
 | 
			
		||||
public:\
 | 
			
		||||
  static inline const H5NS::DataType & type(void)\
 | 
			
		||||
  {\
 | 
			
		||||
    return H5NS::PredType::predType;\
 | 
			
		||||
  }\
 | 
			
		||||
  static constexpr bool isNative = true;\
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DEFINE_HDF5_NATIVE_TYPES \
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_B8,      bool);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_CHAR,    char);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_SCHAR,   signed char);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_UCHAR,   unsigned char);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_SHORT,   short);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_USHORT,  unsigned short);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_INT,     int);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_UINT,    unsigned int);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_LONG,    long);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_ULONG,   unsigned long);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_LLONG,   long long);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_ULLONG,  unsigned long long);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_FLOAT,   float);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_DOUBLE,  double);\
 | 
			
		||||
HDF5_NATIVE_TYPE(NATIVE_LDOUBLE, long double);
 | 
			
		||||
 | 
			
		||||
namespace Grid
 | 
			
		||||
{
 | 
			
		||||
  template <typename T> class Hdf5Type
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    static constexpr bool isNative = false;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  DEFINE_HDF5_NATIVE_TYPES;
 | 
			
		||||
  
 | 
			
		||||
  template <typename R>
 | 
			
		||||
  class Hdf5Type<std::complex<R>>
 | 
			
		||||
  {
 | 
			
		||||
  public:
 | 
			
		||||
    static inline const H5NS::DataType & type(void)
 | 
			
		||||
    {
 | 
			
		||||
      if (typePtr_ == nullptr)
 | 
			
		||||
      {
 | 
			
		||||
        typePtr_.reset(new H5NS::CompType(sizeof(std::complex<R>)));
 | 
			
		||||
        typePtr_->insertMember("re", 0,         Hdf5Type<R>::type());
 | 
			
		||||
        typePtr_->insertMember("im", sizeof(R), Hdf5Type<R>::type());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return *typePtr_;
 | 
			
		||||
    }
 | 
			
		||||
    static constexpr bool isNative = false;
 | 
			
		||||
  private:
 | 
			
		||||
    static std::unique_ptr<H5NS::CompType> typePtr_;
 | 
			
		||||
  };
 | 
			
		||||
  
 | 
			
		||||
  template <typename R>
 | 
			
		||||
  std::unique_ptr<H5NS::CompType> Hdf5Type<std::complex<R>>::typePtr_ = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef HDF5_NATIVE_TYPE
 | 
			
		||||
 | 
			
		||||
#endif /* GRID_SERIALISATION_HDF5_TYPE_H */
 | 
			
		||||
@@ -109,40 +109,36 @@ THE SOFTWARE.
 | 
			
		||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#define GRID_MACRO_MEMBER(A,B)        A B;
 | 
			
		||||
#define GRID_MACRO_COMP_MEMBER(A,B) result = (result and (lhs. B == rhs. B));
 | 
			
		||||
#define GRID_MACRO_OS_WRITE_MEMBER(A,B) os<< #A <<" "#B <<" = "<< obj. B <<" ; " <<std::endl;
 | 
			
		||||
#define GRID_MACRO_READ_MEMBER(A,B) Grid::read(RD,#B,obj. B);
 | 
			
		||||
#define GRID_MACRO_WRITE_MEMBER(A,B) Grid::write(WR,#B,obj. B);
 | 
			
		||||
 | 
			
		||||
#define GRID_SERIALIZABLE_CLASS_MEMBERS(cname,...)		\
 | 
			
		||||
  \
 | 
			
		||||
  \
 | 
			
		||||
  GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_MEMBER,__VA_ARGS__))		\
 | 
			
		||||
  \
 | 
			
		||||
  \
 | 
			
		||||
  template <typename T>\
 | 
			
		||||
  static inline void write(Writer<T> &WR,const std::string &s, const cname &obj){ \
 | 
			
		||||
    push(WR,s);\
 | 
			
		||||
    GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_WRITE_MEMBER,__VA_ARGS__))	\
 | 
			
		||||
    pop(WR);\
 | 
			
		||||
  } \
 | 
			
		||||
  \
 | 
			
		||||
  \
 | 
			
		||||
  template <typename T>\
 | 
			
		||||
  static inline void read(Reader<T> &RD,const std::string &s, cname &obj){	\
 | 
			
		||||
    push(RD,s);\
 | 
			
		||||
    GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_READ_MEMBER,__VA_ARGS__))	\
 | 
			
		||||
    pop(RD);\
 | 
			
		||||
  } \
 | 
			
		||||
  \
 | 
			
		||||
  \
 | 
			
		||||
  friend inline std::ostream & operator << (std::ostream &os, const cname &obj ) { \
 | 
			
		||||
    os<<"class "<<#cname<<" {"<<std::endl;\
 | 
			
		||||
    GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_OS_WRITE_MEMBER,__VA_ARGS__))	\
 | 
			
		||||
      os<<"}";								\
 | 
			
		||||
    return os;\
 | 
			
		||||
  };  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define GRID_SERIALIZABLE_CLASS_MEMBERS(cname,...)\
 | 
			
		||||
GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_MEMBER,__VA_ARGS__))\
 | 
			
		||||
template <typename T>\
 | 
			
		||||
static inline void write(Writer<T> &WR,const std::string &s, const cname &obj){ \
 | 
			
		||||
  push(WR,s);\
 | 
			
		||||
  GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_WRITE_MEMBER,__VA_ARGS__))	\
 | 
			
		||||
  pop(WR);\
 | 
			
		||||
}\
 | 
			
		||||
template <typename T>\
 | 
			
		||||
static inline void read(Reader<T> &RD,const std::string &s, cname &obj){	\
 | 
			
		||||
  push(RD,s);\
 | 
			
		||||
  GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_READ_MEMBER,__VA_ARGS__))	\
 | 
			
		||||
  pop(RD);\
 | 
			
		||||
}\
 | 
			
		||||
friend inline std::ostream & operator << (std::ostream &os, const cname &obj ) { \
 | 
			
		||||
  os<<"class "<<#cname<<" {"<<std::endl;\
 | 
			
		||||
  GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_OS_WRITE_MEMBER,__VA_ARGS__))	\
 | 
			
		||||
    os<<"}";								\
 | 
			
		||||
  return os;\
 | 
			
		||||
}\
 | 
			
		||||
friend inline bool operator==(const cname &lhs, const cname &rhs) {\
 | 
			
		||||
  bool result = true;\
 | 
			
		||||
  GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_COMP_MEMBER,__VA_ARGS__))\
 | 
			
		||||
  return result;\
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define GRID_ENUM_TYPE(obj) std::remove_reference<decltype(obj)>::type
 | 
			
		||||
#define GRID_MACRO_ENUMVAL(A,B) A = B,
 | 
			
		||||
@@ -150,44 +146,61 @@ THE SOFTWARE.
 | 
			
		||||
#define GRID_MACRO_ENUMTEST(A,B) else if (buf == #A) {obj = GRID_ENUM_TYPE(obj)::A;}
 | 
			
		||||
#define GRID_MACRO_ENUMCASEIO(A,B) case GRID_ENUM_TYPE(obj)::A: os << #A; break;
 | 
			
		||||
 | 
			
		||||
namespace Grid {
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  class EnumIO {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define GRID_SERIALIZABLE_ENUM(name,undefname,...)\
 | 
			
		||||
  enum class name {\
 | 
			
		||||
      GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMVAL,__VA_ARGS__))\
 | 
			
		||||
      undefname = -1\
 | 
			
		||||
class name: public Grid::Serializable\
 | 
			
		||||
{\
 | 
			
		||||
public:\
 | 
			
		||||
  enum\
 | 
			
		||||
  {\
 | 
			
		||||
    GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMVAL,__VA_ARGS__))\
 | 
			
		||||
    undefname = -1\
 | 
			
		||||
  };\
 | 
			
		||||
public:\
 | 
			
		||||
  name(void): value_(undefname) {};\
 | 
			
		||||
  name(int value): value_(value) {};\
 | 
			
		||||
  template <typename T>\
 | 
			
		||||
  static inline void write(Grid::Writer<T> &WR,const std::string &s, const name &obj)\
 | 
			
		||||
  {\
 | 
			
		||||
    switch (obj.value_)\
 | 
			
		||||
    {\
 | 
			
		||||
      GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMCASE,__VA_ARGS__))\
 | 
			
		||||
      default: Grid::write(WR,s,#undefname); break;\
 | 
			
		||||
    }\
 | 
			
		||||
  }\
 | 
			
		||||
  \
 | 
			
		||||
  template<>\
 | 
			
		||||
  class EnumIO<name> {\
 | 
			
		||||
    public:\
 | 
			
		||||
      template <typename T>\
 | 
			
		||||
      static inline void write(Writer<T> &WR,const std::string &s, const name &obj){ \
 | 
			
		||||
        switch (obj) {\
 | 
			
		||||
          GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMCASE,__VA_ARGS__))\
 | 
			
		||||
          default: Grid::write(WR,s,#undefname); break;\
 | 
			
		||||
        }\
 | 
			
		||||
      }\
 | 
			
		||||
      \
 | 
			
		||||
      template <typename T>\
 | 
			
		||||
      static inline void read(Reader<T> &RD,const std::string &s, name &obj){ \
 | 
			
		||||
        std::string buf;\
 | 
			
		||||
        Grid::read(RD, s, buf);\
 | 
			
		||||
        if (buf == #undefname) {obj = name::undefname;}\
 | 
			
		||||
        GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMTEST,__VA_ARGS__))\
 | 
			
		||||
        else {obj = name::undefname;}\
 | 
			
		||||
      }\
 | 
			
		||||
  };\
 | 
			
		||||
  \
 | 
			
		||||
  inline std::ostream & operator << (std::ostream &os, const name &obj ) { \
 | 
			
		||||
  template <typename T>\
 | 
			
		||||
  static inline void read(Grid::Reader<T> &RD,const std::string &s, name &obj)\
 | 
			
		||||
  {\
 | 
			
		||||
    std::string buf;\
 | 
			
		||||
    Grid::read(RD, s, buf);\
 | 
			
		||||
    if (buf == #undefname) {obj = name::undefname;}\
 | 
			
		||||
    GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMTEST,__VA_ARGS__))\
 | 
			
		||||
    else {obj = name::undefname;}\
 | 
			
		||||
  }\
 | 
			
		||||
  inline operator int(void) const\
 | 
			
		||||
  {\
 | 
			
		||||
    return value_;\
 | 
			
		||||
  }\
 | 
			
		||||
  inline friend std::ostream & operator<<(std::ostream &os, const name &obj)\
 | 
			
		||||
  {\
 | 
			
		||||
    switch (obj) {\
 | 
			
		||||
        GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMCASEIO,__VA_ARGS__))\
 | 
			
		||||
        default: os << #undefname; break;\
 | 
			
		||||
      GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMCASEIO,__VA_ARGS__))\
 | 
			
		||||
      default: os << #undefname; break;\
 | 
			
		||||
    }\
 | 
			
		||||
    return os;\
 | 
			
		||||
  };
 | 
			
		||||
  }\
 | 
			
		||||
  inline friend std::istream & operator>>(std::istream &is, name &obj)\
 | 
			
		||||
  {\
 | 
			
		||||
    std::string buf;\
 | 
			
		||||
    is >> buf;\
 | 
			
		||||
    if (buf == #undefname) {obj = name::undefname;}\
 | 
			
		||||
    GRID_MACRO_EVAL(GRID_MACRO_MAP(GRID_MACRO_ENUMTEST,__VA_ARGS__))\
 | 
			
		||||
    else {obj = name::undefname;}\
 | 
			
		||||
    return is;\
 | 
			
		||||
  }\
 | 
			
		||||
private:\
 | 
			
		||||
  int value_;\
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,9 @@ Author: Peter Boyle <paboyle@ph.ed.ac.uk>
 | 
			
		||||
#include "BinaryIO.h"
 | 
			
		||||
#include "TextIO.h"
 | 
			
		||||
#include "XmlIO.h"
 | 
			
		||||
#ifdef HAVE_HDF5
 | 
			
		||||
#include "Hdf5IO.h"
 | 
			
		||||
#endif
 | 
			
		||||
//////////////////////////////////////////
 | 
			
		||||
// Todo:
 | 
			
		||||
//////////////////////////////////////////
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user