Skip to content
Snippets Groups Projects
bin-named-stamp.h 6.47 KiB
Newer Older
  • Learn to ignore specific revisions
  • Debolskiy Andrey's avatar
    Debolskiy Andrey committed
    #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]);
    	}
    }
    // -------------------------------------------------------------------------------------------- //