#pragma once // [bin-named-stamp.h]: binNamedStamp data structure for file I/O // // -------------------------------------------------------------------------------------------- // #include "grid-id.h" #include <stdio.h> #include <string> namespace nse { template< typename T > class binNamedStamp { public: binNamedStamp(); ~binNamedStamp(); bool get(const int idx, T* out) const; bool get(const std::string& name, T* out) const; int get_size() const { return size; } int get_record_size() const; bool update(const int idx, T* out) const; bool update(const std::string& name, T* out) const; void push(const std::string& name, const T in); int fwrite(FILE *ptr) const; int fread(FILE* ptr); void mpi_broadcast(const int host, const MPI_Comm comm); void debug_print() const; private: int mem_size, size; T *value; std::string *name; static const int c_alloc_step = 16; void allocate(const int msize); void resize(const int msize); }; } // -------------------------------------------------------------------------------------------- // // Implementation // -------------------------------------------------------------------------------------------- // template< typename T > nse::binNamedStamp< T >::binNamedStamp() : mem_size(0), size(0) {} template< typename T > nse::binNamedStamp< T >::~binNamedStamp() { if (mem_size > 0) delete[] value; mem_size = 0; size = 0; } // -------------------------------------------------------------------------------------------- // template< typename T > bool nse::binNamedStamp< T >::get(const int idx, T* out) const { if ((idx < 0) || (idx >= size)) return false; (*out) = value[idx]; return true; } template< typename T > bool nse::binNamedStamp< T >::get(const std::string& _name, T* out) const { for (int k = 0; k < size; k++) { if (name[k] == _name) { (*out) = value[k]; return true; } } return false; } // -------------------------------------------------------------------------------------------- // template< typename T > bool nse::binNamedStamp< T >::update(const int idx, T* out) const { if ((idx < 0) || (idx >= size)) return false; (*out) += value[idx]; return true; } template< typename T > bool nse::binNamedStamp< T >::update(const std::string& _name, T* out) const { for (int k = 0; k < size; k++) { if (name[k] == _name) { (*out) += value[k]; return true; } } return false; } // -------------------------------------------------------------------------------------------- // template< typename T > void nse::binNamedStamp< T >::push(const std::string& _name, const T in) { if (_name.empty()) return; for (int k = 0; k < size; k++) { if (name[k] == _name) { value[k] = in; return; } } resize(size + 1); value[size] = in; name[size] = _name; size++; } // -------------------------------------------------------------------------------------------- // template< typename T > void nse::binNamedStamp< T >::allocate(const int req_size) { if (req_size > mem_size) { int alloc_size = (req_size > mem_size + c_alloc_step) ? req_size : mem_size + c_alloc_step; if (mem_size > 0) { delete[] value; delete[] name; } value = new T[alloc_size]; name = new std::string[alloc_size]; mem_size = alloc_size; } } // -------------------------------------------------------------------------------------------- // template< typename T > void nse::binNamedStamp< T >::resize(const int req_size) { if (req_size > mem_size) { int alloc_size = (req_size > mem_size + c_alloc_step) ? req_size : mem_size + c_alloc_step; T *cpval = new T[alloc_size]; std::string *cpname = new std::string[alloc_size]; if (size > 0) memcpy(cpval, value, size * sizeof(T)); for (int k = 0; k < size; k++) cpname[k] = name[k]; if (mem_size > 0) { delete[] value; delete[] name; } value = cpval; name = cpname; mem_size = alloc_size; } } // -------------------------------------------------------------------------------------------- // template< typename T > int nse::binNamedStamp< T >::fwrite(FILE *ptr) const { int status = 0; status += ::fwrite(&size, sizeof(int), 1, ptr); if (size > 0) { status += ::fwrite(value, sizeof(T), size, ptr); } for (int k = 0; k < size; k++) { int c_length = strlen(name[k].c_str()); status += ::fwrite(&c_length, sizeof(int), 1, ptr); status += ::fwrite(name[k].c_str(), sizeof(char), c_length, ptr); } return status; } // -------------------------------------------------------------------------------------------- // template< typename T > int nse::binNamedStamp< T >::fread(FILE* ptr) { int status = 0; status += ::fread(&size, sizeof(int), 1, ptr); allocate(size); if (size > 0) { status += ::fread(value, sizeof(T), size, ptr); } for (int k = 0; k < size; k++) { int c_length; status += ::fread(&c_length, sizeof(int), 1, ptr); char *c_buf = new char[c_length + 1]; status += ::fread(c_buf, sizeof(char), c_length, ptr); c_buf[c_length] = '\0'; name[k] = std::string(c_buf); delete[] c_buf; } return status; } // -------------------------------------------------------------------------------------------- // template< typename T > int nse::binNamedStamp< T >::get_record_size() const { int recsize = size + 1; for (int k = 0; k < size; k++) { int name_length = strlen(name[k].c_str()); recsize += name_length + 1; } return recsize; } // -------------------------------------------------------------------------------------------- // template< typename T > void nse::binNamedStamp< T >::mpi_broadcast( const int host, const MPI_Comm comm) { int mpi_rank; MPI_Comm_rank(comm, &mpi_rank); MPI_Bcast(&size, 1, MPI_INT, host, comm); if (mpi_rank != host) allocate(size); if (size > 0) { MPI_Bcast(value, size, mpi_type< T >(), host, comm); } for (int k = 0; k < size; k++) { int c_length = 0; if (mpi_rank == host) c_length = strlen(name[k].c_str()); MPI_Bcast(&c_length, 1, MPI_INT, host, comm); char *c_buf = new char[c_length + 1]; strcpy(c_buf, name[k].c_str()); MPI_Bcast(c_buf, c_length + 1, MPI_CHAR, host, comm); if (mpi_rank != host) { name[k] = std::string(c_buf); } delete[] c_buf; } } // -------------------------------------------------------------------------------------------- // template< typename T > void nse::binNamedStamp< T >::debug_print() const { for (int k = 0; k < size; k++) { printf(" idx = %i, name = %s, value = %.5f\n", k, name[k].c_str(), value[k]); } } // -------------------------------------------------------------------------------------------- //