github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/array.hpp (about)

     1  #pragma once
     2  
     3  /**
     4  	@file
     5  	@brief scoped array and aligned array
     6  
     7  	@author MITSUNARI Shigeo(@herumi)
     8  */
     9  #include <new>
    10  #include <utility>
    11  #ifdef _WIN32
    12  	#include <malloc.h>
    13  #else
    14  	#include <stdlib.h>
    15  #endif
    16  #include <cybozu/inttype.hpp>
    17  
    18  namespace cybozu {
    19  
    20  inline void *AlignedMalloc(size_t size, size_t alignment)
    21  {
    22  #ifdef _WIN32
    23  	return _aligned_malloc(size, alignment);
    24  #else
    25  	void *p;
    26  	int ret = posix_memalign(&p, alignment, size);
    27  	return (ret == 0) ? p : 0;
    28  #endif
    29  }
    30  
    31  inline void AlignedFree(void *p)
    32  {
    33  #ifdef _WIN32
    34  	if (p == 0) return;
    35  	_aligned_free(p);
    36  #else
    37  	free(p);
    38  #endif
    39  }
    40  
    41  template<class T>
    42  class ScopedArray {
    43  	T *p_;
    44  	size_t size_;
    45  	ScopedArray(const ScopedArray&);
    46  	void operator=(const ScopedArray&);
    47  public:
    48  	explicit ScopedArray(size_t size)
    49  		: p_(new T[size])
    50  		, size_(size)
    51  	{
    52  	}
    53  	~ScopedArray()
    54  	{
    55  		delete[] p_;
    56  	}
    57  	T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; }
    58  	const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; }
    59  	size_t size() const CYBOZU_NOEXCEPT { return size_; }
    60  	bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; }
    61  	T* begin() CYBOZU_NOEXCEPT { return p_; }
    62  	T* end() CYBOZU_NOEXCEPT { return p_ + size_; }
    63  	const T* begin() const CYBOZU_NOEXCEPT { return p_; }
    64  	const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; }
    65      T* data() CYBOZU_NOEXCEPT { return p_; }
    66      const T* data() const CYBOZU_NOEXCEPT { return p_; }
    67  };
    68  
    69  /**
    70  	T must be POD type
    71  	16byte aligment array
    72  */
    73  template<class T, size_t N = 16, bool defaultDoClear = true>
    74  class AlignedArray {
    75  	T *p_;
    76  	size_t size_;
    77  	size_t allocSize_;
    78  	T *alloc(size_t size) const
    79  	{
    80  		T *p = static_cast<T*>(AlignedMalloc(size * sizeof(T), N));
    81  		if (p == 0) throw std::bad_alloc();
    82  		return p;
    83  	}
    84  	void copy(T *dst, const T *src, size_t n) const
    85  	{
    86  		for (size_t i = 0; i < n; i++) dst[i] = src[i];
    87  	}
    88  	void setZero(T *p, size_t n) const
    89  	{
    90  		for (size_t i = 0; i < n; i++) p[i] = 0;
    91  	}
    92  	/*
    93  		alloc allocN and copy [p, p + copyN) to new p_
    94  		don't modify size_
    95  	*/
    96  	void allocCopy(size_t allocN, const T *p, size_t copyN)
    97  	{
    98  		T *q = alloc(allocN);
    99  		copy(q, p, copyN);
   100  		AlignedFree(p_);
   101  		p_ = q;
   102  		allocSize_ = allocN;
   103  	}
   104  public:
   105  	/*
   106  		don't clear buffer with zero if doClear is false
   107  	*/
   108  	explicit AlignedArray(size_t size = 0, bool doClear = defaultDoClear)
   109  		: p_(0)
   110  		, size_(0)
   111  		, allocSize_(0)
   112  	{
   113  		resize(size, doClear);
   114  	}
   115  	AlignedArray(const AlignedArray& rhs)
   116  		: p_(0)
   117  		, size_(0)
   118  		, allocSize_(0)
   119  	{
   120  		*this = rhs;
   121  	}
   122  	AlignedArray& operator=(const AlignedArray& rhs)
   123  	{
   124  		if (allocSize_ < rhs.size_) {
   125  			allocCopy(rhs.size_, rhs.p_, rhs.size_);
   126  		} else {
   127  			copy(p_, rhs.p_, rhs.size_);
   128  		}
   129  		size_ = rhs.size_;
   130  		return *this;
   131  	}
   132  #if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11)
   133  	AlignedArray(AlignedArray&& rhs) CYBOZU_NOEXCEPT
   134  		: p_(rhs.p_)
   135  		, size_(rhs.size_)
   136  		, allocSize_(rhs.allocSize_)
   137  	{
   138  		rhs.p_ = 0;
   139  		rhs.size_ = 0;
   140  		rhs.allocSize_ = 0;
   141  	}
   142  	AlignedArray& operator=(AlignedArray&& rhs) CYBOZU_NOEXCEPT
   143  	{
   144  		swap(rhs);
   145  		rhs.clear();
   146  		return *this;
   147  	}
   148  #endif
   149  	/*
   150  		don't clear buffer with zero if doClear is false
   151  		@note don't free if shrinked
   152  	*/
   153  	void resize(size_t size, bool doClear = defaultDoClear)
   154  	{
   155  		// shrink
   156  		if (size <= size_) {
   157  			size_ = size;
   158  			return;
   159  		}
   160  		// realloc if necessary
   161  		if (size > allocSize_) {
   162  			allocCopy(size, p_, size_);
   163  		}
   164  		if (doClear) setZero(p_ + size_, size - size_);
   165  		size_ = size;
   166  	}
   167  	void clear() // not free
   168  	{
   169  		size_ = 0;
   170  	}
   171  	~AlignedArray()
   172  	{
   173  		AlignedFree(p_);
   174  	}
   175  	void swap(AlignedArray& rhs) CYBOZU_NOEXCEPT
   176  	{
   177  		std::swap(p_, rhs.p_);
   178  		std::swap(size_, rhs.size_);
   179  		std::swap(allocSize_, rhs.allocSize_);
   180  	}
   181  	T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; }
   182  	const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; }
   183  	size_t size() const CYBOZU_NOEXCEPT { return size_; }
   184  	bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; }
   185  	T* begin() CYBOZU_NOEXCEPT { return p_; }
   186  	T* end() CYBOZU_NOEXCEPT { return p_ + size_; }
   187  	const T* begin() const CYBOZU_NOEXCEPT { return p_; }
   188  	const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; }
   189      T* data() CYBOZU_NOEXCEPT { return p_; }
   190      const T* data() const CYBOZU_NOEXCEPT { return p_; }
   191  #if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11)
   192  	const T* cbegin() const CYBOZU_NOEXCEPT { return p_; }
   193  	const T* cend() const CYBOZU_NOEXCEPT { return p_ + size_; }
   194  #endif
   195  };
   196  
   197  } // cybozu