text: #ifndef _BLASR_HDF_ATOM_HPP_
  #define _BLASR_HDF_ATOM_HPP_
  
  #include <cassert>
  #include <cstdint>
  #include <string>
  #include <vector>
  
  #include <H5Cpp.h>
  
  #include <hdf/HDFConfig.hpp>
  #include <hdf/HDFData.hpp>
  #include <hdf/HDFGroup.hpp>
  
  template <typename T>
  class HDFAtom : public HDFData
  {
  public:
      H5::Attribute attribute;
  
      HDFAtom() { isInitialized = false; }
      ~HDFAtom()
      {
          if (IsInitialized()) {
              attribute.close();
          }
      }
  
      H5::H5Object *GetObject() { return NULL; }
  
      int Initialize(H5::H5Object &object, const std::string &attributeName)
      {
          attribute = object.openAttribute(attributeName.c_str());
          isInitialized = true;
          return 1;
      }
  
      int Initialize(HDFGroup &group, const std::string &attributeName)
      {
          return Initialize(group.group, attributeName);
      }
  
      int Initialize(HDFData &data, const std::string &attributeName)
      {
          return Initialize(data.dataset, attributeName);
      }
  
      int Initialize(H5::Group &object, const std::string &attributeName)
      {
          try {
              attribute = object.openAttribute(attributeName.c_str());
          } catch (const H5::Exception &e) {
              std::cout << "ERROR. Could not open attribute " << attributeName << std::endl;
              std::exit(EXIT_FAILURE);
          }
          isInitialized = true;
          return 1;
      }
  
      int Initialize(H5::H5File &hdfFile, const std::string &groupName,
                     const std::string &attributeName)
      {
          HDFGroup group;
          group.Initialize(hdfFile, groupName);
          attribute = group.group.openAttribute(attributeName.c_str());
          isInitialized = true;
          return 1;
      }
  
      //
      // This handles creation of all non-std::string types.  A specialization
      // for std::strings is provided below.
      //
      void Create(H5::H5Object &object, const std::string &atomName)
      {
          hsize_t defaultDims[] = {1};
          H5::DataSpace defaultDataSpace(1, defaultDims);
          TypedCreate(object, atomName, defaultDataSpace);
      }
  
      void Create(H5::H5Object &object, const std::string &name, const std::string &value)
      {
          H5::StrType strType(0, value.size());
          attribute = object.createAttribute(name.c_str(), strType, H5::DataSpace(0, NULL));
          isInitialized = true;
          attribute.write(strType, value.c_str());
      }
  
      void Create(H5::H5Object &object, const std::string &name, std::vector<int> &vect)
      {
          hsize_t length = vect.size();
          H5::ArrayType arrayDataType(H5::PredType::NATIVE_INT, 1, &length);
          attribute = object.createAttribute(name.c_str(), H5::PredType::NATIVE_INT,
                                             H5::DataSpace(1, &length));
          attribute.write(H5::PredType::NATIVE_INT, &((vect)[0]));
      }
  
      void Create(H5::H5Object &object, const std::string &name, const std::vector<std::string> &vect)
      {
          hsize_t length = vect.size();
          H5::StrType strType(0, H5T_VARIABLE);
          H5::ArrayType arrayDataType(strType, 1, &length);
          attribute = object.createAttribute(name.c_str(), strType, H5::DataSpace(1, &length));
          attribute.write(strType, &((vect)[0]));
      }
  
      void TypedCreate(H5::H5Object &object, const std::string &atomName, H5::DataSpace &dataSpace)
      {
          (void)(object);
          (void)(atomName);
          (void)(dataSpace);
          assert("Calling HDFAtom<T>::typedCreate on an unsupported type" == 0);
      }
  
      void Write(T value)
      {
          (void)(value);
          assert("Calling HDFAtom<T>::Write on an unsupported type" == 0);
      }
  
      void Read(T &value)
      {
          (void)(value);
          assert("Calling read on an unsupported type!" == 0);
      }
  };
  
  //
  // Special create for std::strings.  Since this uses a H5::StrType for the
  // typename rather than specifying a H5::PredType, it mertis its own
  // function.
  //
  
  template <>
  void HDFAtom<std::string>::Create(H5::H5Object &object, const std::string &atomName);
  
  #define DECLARE_TYPED_CREATE_ATOM(T, predtype)                                      \
      template <>                                                                     \
      void HDFAtom<T>::TypedCreate(H5::H5Object &object, const std::string &atomName, \
                                   H5::DataSpace &defaultDataSpace);
  
  DECLARE_TYPED_CREATE_ATOM(int, H5::PredType::NATIVE_INT)
  DECLARE_TYPED_CREATE_ATOM(unsigned int, H5::PredType::NATIVE_UINT)
  DECLARE_TYPED_CREATE_ATOM(unsigned char, H5::PredType::NATIVE_UINT8)
  DECLARE_TYPED_CREATE_ATOM(char, H5::PredType::NATIVE_INT8)
  DECLARE_TYPED_CREATE_ATOM(float, H5::PredType::NATIVE_FLOAT)
  DECLARE_TYPED_CREATE_ATOM(uint16_t, H5::PredType::NATIVE_UINT16)
  DECLARE_TYPED_CREATE_ATOM(uint64_t, H5::PredType::STD_I64LE)
  
  template <>
  void HDFAtom<std::vector<int> >::Write(const std::vector<int> vect);
  
  template <>
  void HDFAtom<std::string>::Write(std::string value);
  
  template <>
  void HDFAtom<uint64_t>::Write(uint64_t value);
  
  template <>
  void HDFAtom<uint16_t>::Write(uint16_t value);
  
  template <>
  void HDFAtom<int>::Write(int value);
  
  template <>
  void HDFAtom<unsigned int>::Write(unsigned int value);
  
  template <>
  void HDFAtom<unsigned char>::Write(unsigned char value);
  
  template <>
  void HDFAtom<char>::Write(char value);
  
  template <>
  void HDFAtom<float>::Write(float value);
  
  template <>
  void HDFAtom<std::string>::Read(std::string &value);
  
  template <>
  void HDFAtom<int>::Read(int &value);
  
  template <>
  void HDFAtom<uint64_t>::Read(uint64_t &value);
  
  template <>
  void HDFAtom<uint16_t>::Read(uint16_t &value);
  
  template <>
  void HDFAtom<unsigned int>::Read(unsigned int &value);
  
  template <>
  void HDFAtom<float>::Read(float &value);
  
  template <>
  void HDFAtom<std::vector<std::string> >::Read(std::vector<std::string> &values);
  
  #endif
  