/* # <> # Copyright 2019, Lawrence Livermore National Security, LLC. # This file is part of the gidiplus package (https://github.com/LLNL/gidiplus). # gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT). # SPDX-License-Identifier: MIT # <> */ #ifndef HAPI_hpp_included #define HAPI_hpp_included 1 #include #include #include #include #include #include #define HAPI_USE_PUGIXML 1 #ifdef HAPI_USE_PUGIXML #include #endif #ifdef HAPI_USE_HDF5 #include #endif #include namespace HAPI { enum class NodeInteralType { pugiXML, HDF5 }; // container classes for reading in from various data sources: /* ============================================================ ========================= Attribute ======================== ============================================================ */ class Node_internal; class Attribute { private: Node_internal *m_node; std::string m_name; //std::string m_value; public: inline Attribute() : m_node(nullptr), m_name() {} inline Attribute(Node_internal *a_node, std::string const &a_name) : m_node(a_node), m_name(a_name) { } ~Attribute() = default; //std::string const &name() const { return( m_name ); } inline std::string const value() const; inline int as_int() const; inline long as_long() const; inline double as_double() const; }; /* ============================================================ =========================== Text =========================== ============================================================ */ class Text { private: std::string m_text; public: Text(); Text(std::string const &a_text); ~Text(); std::string const &get() const { return( m_text ); } }; /* ============================================================ ================== Data_internal (base class) ============== ============================================================ */ class Data_internal { public: Data_internal() { }; virtual ~Data_internal() = 0; //std::string const getDataType(); //virtual template T read() = 0; virtual void getDoubles(nf_Buffer &buffer) = 0; virtual void getInts(nf_Buffer &buffer) = 0; virtual size_t length() const = 0; }; /* ============================================================ =================== Node_internal (base class) ============= ============================================================ */ class Node_internal { private: NodeInteralType m_type; public: Node_internal( NodeInteralType a_type ); Node_internal( Node_internal const &a_node ); virtual ~Node_internal() = 0; NodeInteralType type( ) const { return( m_type ); } virtual std::string attribute(const char* name) = 0; virtual int attribute_as_int(const char* name) = 0; virtual long attribute_as_long(const char* name) = 0; virtual double attribute_as_double(const char* name) = 0; virtual Node_internal *child(const char* name) = 0; virtual Node_internal *first_child() = 0; virtual Node_internal *next_sibling() = 0; virtual void to_next_sibling() = 0; virtual Node_internal *copy() = 0; virtual std::string name() const = 0; virtual bool empty() const = 0; virtual Text text() const = 0; virtual Data_internal *data() const = 0; }; inline std::string const Attribute::value() const { return( m_node->attribute( m_name.c_str()) ); } inline int Attribute::as_int() const { return( m_node->attribute_as_int(m_name.c_str()) ); } inline long Attribute::as_long() const { return( m_node->attribute_as_long(m_name.c_str()) ); } inline double Attribute::as_double() const { return( m_node->attribute_as_double(m_name.c_str()) ); } /* ============================================================ =========================== Data =========================== ============================================================ */ class Data { private: Data_internal *m_data; public: Data(); Data( Data_internal *a_data ); ~Data(); void getDoubles(nf_Buffer &buffer); void getInts(nf_Buffer &buffer); size_t length() const; }; /* ============================================================ ============================ Node ========================== ============================================================ */ class Node { private: Node_internal *m_node; public: Node(); Node( Node_internal *a_node ); Node( Node const &a_node ); ~Node(); inline Attribute attribute(const char* a_name) const{ return Attribute(m_node, a_name); } inline std::string attribute_as_string(const char* a_name) const{ if(m_node == nullptr){ return ""; } return m_node->attribute(a_name); } inline int attribute_as_int(const char* a_name) const{ if(m_node == nullptr){ return 0; } return m_node->attribute_as_int(a_name); } inline long attribute_as_long(const char* a_name) const{ if(m_node == nullptr){ return 0; } return m_node->attribute_as_long(a_name); } inline double attribute_as_double(const char* a_name) const{ if(m_node == nullptr){ return 0.0; } return m_node->attribute_as_double(a_name); } Node child(const char* name) const; Node first_child() const; Node next_sibling() const; void to_next_sibling() const; Node &operator=(const Node &other); std::string name() const; bool empty() const; Text text() const; Data data() const; }; /* ============================================================ ======================= File (base class) ================== ============================================================ */ class File { public: File() { }; virtual ~File() = 0; virtual Node child(const char* name) = 0; virtual Node first_child() = 0; virtual std::string name() const = 0; }; /* ============================================================ =============== Data Manager (for hybrid files) ============ ============================================================ */ class DataManager { public: DataManager() {}; virtual ~DataManager() {}; static DataManager* m_instance; public: virtual void getDoubles(nf_Buffer &result, size_t startIndex, size_t endIndex) = 0; virtual void getInts(nf_Buffer &result, size_t startIndex, size_t endIndex) = 0; }; #ifdef HAPI_USE_PUGIXML /* ============================================================ ===================== XML using Pugi ======================= ============================================================ */ class PugiXMLNode : public Node_internal { private: pugi::xml_node m_node; public: PugiXMLNode(); PugiXMLNode(pugi::xml_node a_node); PugiXMLNode(const PugiXMLNode &other); virtual ~PugiXMLNode(); std::string attribute(const char* name); int attribute_as_int(const char* name); long attribute_as_long(const char* name); double attribute_as_double(const char* name); Node_internal *child(char const *name); Node_internal *first_child(); Node_internal *next_sibling(); void to_next_sibling(); Node_internal *copy(); Node_internal &operator=(const PugiXMLNode &other); std::string name() const; bool empty() const; Text text() const; Data_internal *data() const; }; class PugiXMLData : public Data_internal { private: pugi::xml_node m_node; size_t m_length; bool m_dataRead; public: PugiXMLData(); PugiXMLData(pugi::xml_node a_node); virtual ~PugiXMLData(); void getDoubles(nf_Buffer &buffer); void getInts(nf_Buffer &buffer); size_t length() const; }; class PugiXMLFile : public File { private: std::string m_name; pugi::xml_document m_doc; public: PugiXMLFile(); PugiXMLFile(char const *filename, std::string const &a_callingFunctionName); virtual ~PugiXMLFile(); Node child(char const *name); Node first_child(); std::string name() const; }; #endif #ifdef HAPI_USE_HDF5 /* ============================================================ =========================== HDF ============================ ============================================================ */ typedef struct { std::string name; std::string xmlName; // HDF sometimes mangles names, need original name here size_t index; hid_t node_id; } childInfo; class HDFNode : public Node_internal { private: hid_t m_node_id; hid_t m_parent_id; size_t m_index; std::vector m_siblings; std::vector m_children; public: HDFNode(); HDFNode(hid_t a_node_id, hid_t a_parent_id, size_t a_index, std::vector a_siblings); explicit HDFNode(hid_t a_file_id); HDFNode(const HDFNode &other); virtual ~HDFNode(); //Attribute attribute(char const *name); std::string attribute(const char* name); int attribute_as_int(const char* name); long attribute_as_long(const char* name); double attribute_as_double(const char* name); Node_internal *child(char const *name); Node_internal *first_child(); Node_internal *next_sibling(); void to_next_sibling(); Node_internal *copy(); Node_internal &operator=(const HDFNode &other); std::string name() const; bool empty() const; Text text() const; Data_internal *data() const; }; class HDFData : public Data_internal { private: hid_t m_node_id; hid_t m_dataspace_id; size_t m_length; public: HDFData(); explicit HDFData(hid_t node_id); virtual ~HDFData(); void getDoubles(nf_Buffer &buffer); void getInts(nf_Buffer &buffer); size_t length() const; }; class HDFFile : public File { private: std::string m_name; hid_t m_doc; HDFNode *m_doc_as_node; public: HDFFile(); explicit HDFFile(char const *filename); virtual ~HDFFile(); Node child(char const *name); Node first_child(); std::string name() const; }; class HDFDataManager : public DataManager{ private: std::string m_filename; bool m_iDataPresent; bool m_dDataPresent; hid_t m_file_id; hid_t m_dataset_ints, m_dataset_doubles; hid_t m_dataspace_ints, m_dataspace_doubles; hsize_t m_stride[1], m_block[1]; size_t m_num_double_reads; size_t m_num_double_elem; size_t m_num_int_reads; size_t m_num_int_elem; public: HDFDataManager(std::string const &filename); virtual ~HDFDataManager(); virtual void getDoubles(nf_Buffer &result, size_t startIndex, size_t endIndex); virtual void getInts(nf_Buffer &result, size_t startIndex, size_t endIndex); }; #endif } // end of namespace 'HAPI' #endif // End of HAPI_hpp_included