You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
4.3 KiB
197 lines
4.3 KiB
#pragma once
|
|
|
|
/**
|
|
@file
|
|
@brief scoped array and aligned array
|
|
|
|
@author MITSUNARI Shigeo(@herumi)
|
|
*/
|
|
#include <new>
|
|
#include <utility>
|
|
#ifdef _WIN32
|
|
#include <malloc.h>
|
|
#else
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include <cybozu/inttype.hpp>
|
|
|
|
namespace cybozu {
|
|
|
|
inline void *AlignedMalloc(size_t size, size_t alignment)
|
|
{
|
|
#ifdef _WIN32
|
|
return _aligned_malloc(size, alignment);
|
|
#else
|
|
void *p;
|
|
int ret = posix_memalign(&p, alignment, size);
|
|
return (ret == 0) ? p : 0;
|
|
#endif
|
|
}
|
|
|
|
inline void AlignedFree(void *p)
|
|
{
|
|
#ifdef _WIN32
|
|
if (p == 0) return;
|
|
_aligned_free(p);
|
|
#else
|
|
free(p);
|
|
#endif
|
|
}
|
|
|
|
template<class T>
|
|
class ScopedArray {
|
|
T *p_;
|
|
size_t size_;
|
|
ScopedArray(const ScopedArray&);
|
|
void operator=(const ScopedArray&);
|
|
public:
|
|
explicit ScopedArray(size_t size)
|
|
: p_(new T[size])
|
|
, size_(size)
|
|
{
|
|
}
|
|
~ScopedArray()
|
|
{
|
|
delete[] p_;
|
|
}
|
|
T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; }
|
|
const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; }
|
|
size_t size() const CYBOZU_NOEXCEPT { return size_; }
|
|
bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; }
|
|
T* begin() CYBOZU_NOEXCEPT { return p_; }
|
|
T* end() CYBOZU_NOEXCEPT { return p_ + size_; }
|
|
const T* begin() const CYBOZU_NOEXCEPT { return p_; }
|
|
const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; }
|
|
T* data() CYBOZU_NOEXCEPT { return p_; }
|
|
const T* data() const CYBOZU_NOEXCEPT { return p_; }
|
|
};
|
|
|
|
/**
|
|
T must be POD type
|
|
16byte aligment array
|
|
*/
|
|
template<class T, size_t N = 16, bool defaultDoClear = true>
|
|
class AlignedArray {
|
|
T *p_;
|
|
size_t size_;
|
|
size_t allocSize_;
|
|
T *alloc(size_t size) const
|
|
{
|
|
T *p = static_cast<T*>(AlignedMalloc(size * sizeof(T), N));
|
|
if (p == 0) throw std::bad_alloc();
|
|
return p;
|
|
}
|
|
void copy(T *dst, const T *src, size_t n) const
|
|
{
|
|
for (size_t i = 0; i < n; i++) dst[i] = src[i];
|
|
}
|
|
void setZero(T *p, size_t n) const
|
|
{
|
|
for (size_t i = 0; i < n; i++) p[i] = 0;
|
|
}
|
|
/*
|
|
alloc allocN and copy [p, p + copyN) to new p_
|
|
don't modify size_
|
|
*/
|
|
void allocCopy(size_t allocN, const T *p, size_t copyN)
|
|
{
|
|
T *q = alloc(allocN);
|
|
copy(q, p, copyN);
|
|
AlignedFree(p_);
|
|
p_ = q;
|
|
allocSize_ = allocN;
|
|
}
|
|
public:
|
|
/*
|
|
don't clear buffer with zero if doClear is false
|
|
*/
|
|
explicit AlignedArray(size_t size = 0, bool doClear = defaultDoClear)
|
|
: p_(0)
|
|
, size_(0)
|
|
, allocSize_(0)
|
|
{
|
|
resize(size, doClear);
|
|
}
|
|
AlignedArray(const AlignedArray& rhs)
|
|
: p_(0)
|
|
, size_(0)
|
|
, allocSize_(0)
|
|
{
|
|
*this = rhs;
|
|
}
|
|
AlignedArray& operator=(const AlignedArray& rhs)
|
|
{
|
|
if (allocSize_ < rhs.size_) {
|
|
allocCopy(rhs.size_, rhs.p_, rhs.size_);
|
|
} else {
|
|
copy(p_, rhs.p_, rhs.size_);
|
|
}
|
|
size_ = rhs.size_;
|
|
return *this;
|
|
}
|
|
#if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11)
|
|
AlignedArray(AlignedArray&& rhs) CYBOZU_NOEXCEPT
|
|
: p_(rhs.p_)
|
|
, size_(rhs.size_)
|
|
, allocSize_(rhs.allocSize_)
|
|
{
|
|
rhs.p_ = 0;
|
|
rhs.size_ = 0;
|
|
rhs.allocSize_ = 0;
|
|
}
|
|
AlignedArray& operator=(AlignedArray&& rhs) CYBOZU_NOEXCEPT
|
|
{
|
|
swap(rhs);
|
|
rhs.clear();
|
|
return *this;
|
|
}
|
|
#endif
|
|
/*
|
|
don't clear buffer with zero if doClear is false
|
|
@note don't free if shrinked
|
|
*/
|
|
void resize(size_t size, bool doClear = defaultDoClear)
|
|
{
|
|
// shrink
|
|
if (size <= size_) {
|
|
size_ = size;
|
|
return;
|
|
}
|
|
// realloc if necessary
|
|
if (size > allocSize_) {
|
|
allocCopy(size, p_, size_);
|
|
}
|
|
if (doClear) setZero(p_ + size_, size - size_);
|
|
size_ = size;
|
|
}
|
|
void clear() // not free
|
|
{
|
|
size_ = 0;
|
|
}
|
|
~AlignedArray()
|
|
{
|
|
AlignedFree(p_);
|
|
}
|
|
void swap(AlignedArray& rhs) CYBOZU_NOEXCEPT
|
|
{
|
|
std::swap(p_, rhs.p_);
|
|
std::swap(size_, rhs.size_);
|
|
std::swap(allocSize_, rhs.allocSize_);
|
|
}
|
|
T& operator[](size_t idx) CYBOZU_NOEXCEPT { return p_[idx]; }
|
|
const T& operator[](size_t idx) const CYBOZU_NOEXCEPT { return p_[idx]; }
|
|
size_t size() const CYBOZU_NOEXCEPT { return size_; }
|
|
bool empty() const CYBOZU_NOEXCEPT { return size_ == 0; }
|
|
T* begin() CYBOZU_NOEXCEPT { return p_; }
|
|
T* end() CYBOZU_NOEXCEPT { return p_ + size_; }
|
|
const T* begin() const CYBOZU_NOEXCEPT { return p_; }
|
|
const T* end() const CYBOZU_NOEXCEPT { return p_ + size_; }
|
|
T* data() CYBOZU_NOEXCEPT { return p_; }
|
|
const T* data() const CYBOZU_NOEXCEPT { return p_; }
|
|
#if (CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11)
|
|
const T* cbegin() const CYBOZU_NOEXCEPT { return p_; }
|
|
const T* cend() const CYBOZU_NOEXCEPT { return p_ + size_; }
|
|
#endif
|
|
};
|
|
|
|
} // cybozu
|
|
|