#ifdef ___POOL___
#define ___POOL___
#include"type.hpp"
#include<vector>
#include<cstdlib>
/*
* 上限値を定めて値を取り出する
* 渡された値が上限値以上なら、上限値にまるめる。
*
* value 任意の値
* limit valueの上限値
*/
inline size_t ClipValue(size_t value,size_t limit)
{
return value<limit?value:limit;
}
/*
* 高速伸張配列
* 値を追加しても無駄にコピーを
* 行わず比較的高速に伸びる配列
*/
class BinalyPool
{
typedef Type::narrow Byte;
typedef std::vector<Byte> Cache;
Cache cache;
size_t
length, //この配列全体の長さ
pool_offset, //次に書込を開始する位置
signal; //状態値(bit Flag)
enum{Update=1}; //更新を示す(Bit Flag)
/*
*リスト型格納領域
*/
struct Buffer
{
enum{length=0x100};
Byte array[length];
Buffer *next;
};
Buffer top,*current;
/*
*書込領域を更新する。
*既存の領域があればそれを利用する
*/
void NextBuffer(size_t write_length)
{
if(Buffer::length>write_length)
{
pool_offset+=write_length;
if(Buffer::length>pool_offset) return;
}
if(!current->next)
{
current->next = new Buffer;
current->next->next=0;
}
current=current->next;
}
public:
typedef Byte *iterator;
typedef const Byte *const_iterator;
BinalyPool(void):
signal(0),
length(0),
pool_offset(0),
current(&top)
{
top.next=0;
}
virtual ~BinalyPool(void)
{
FullClear();
}
size_t size(void)const
{
return length;
}
/*
* 先頭から書き込めるようにする
* 見かけだけの解除だが書込速度が最速になるので
* 通常はこちらを使う。
*/
BinalyPool &Clear(void)
{
signal^=signal&Update;
length=0;
pool_offset=0;
current = ⊤
cache.resize(0);
return *this;
}
/*
* 完全に情報を領域ごと削除する。
* 格納領域を再度構築するため遅くなる。
* 容量的にまずい場合のみ使う
*/
BinalyPool &FullClear(void)
{
Buffer *i = top.next,*garbage;
Clear();
cache=Cache();
while(i)
{
garbage=i;
i=i->next;
delete garbage;
}
top.next = 0;
return *this;
}
/*
* 引数に指定した配列を追記する。
*
* value_array 配列
* length 配列長
*/
virtual BinalyPool &Append(const void *value_array,size_t length)
{
const Byte *array=static_cast<const Byte*>(value_array);
signal|=Update;
//直列バッファへ格納
if(size()<cache.capacity())
{
//空き容量と配列長のうち空き容量を上限に格納する
size_t
cache_blank=cache.capacity()-size(),
write_length=ClipValue(length,cache_blank);
for(size_t i=0;i<write_length;++i)
{
cache.push_back(array[i]);
}
length-=write_length;
array+=write_length;
this->length=cache.size();
}
//
this->length+=length;
if(0>=length)return *this;
//位置を調整してリストバッファに格納
if(0<pool_offset&&pool_offset<Buffer::length)
{
//空き容量と配列長のうち空き容量を上限に格納する
size_t capacity=ClipValue(length,Buffer::length-pool_offset);
//前回書き込んだ次の位置から配列を書き込む
std::memcpy
(
pool_offset+current->array,
array,
capacity
);
array+=capacity;
if(capacity<=length)length-=capacity;
NextBuffer(capacity);
}
//Buffer::length以上引数の配列要素がある場合はここで処理する
while(Buffer::length<=length)
{
std::memcpy
(
current->array,
array,
Buffer::length
);
array+=Buffer::length;
if(Buffer::length<=length)length-=Buffer::length;
NextBuffer(Buffer::length);
}
//Buffer::lengthで割りきれず最終的に残った配列要素をここで書き込む
if(0<length)
{
std::memcpy
(
current->array,
array,
length
);
pool_offset=length;
}
return *this;
}
/*
*
*
*/
iterator begin(void)
{
if(signal)
{
size_t length=size()-cache.size();
const Buffer *buffer=⊤
current = ⊤
cache.reserve(size());
while(Buffer::length<length)
{
for(size_t i=0;Buffer::length>i;++i)
{
cache.push_back(buffer->array[i]);
}
buffer=buffer->next;
length-=Buffer::length<length?Buffer::length:0;
}
for(size_t i=0;i<length&&buffer;++i)
{
cache.push_back(buffer->array[i]);
}
pool_offset=0;
signal^=signal&Update;
}
return &cache.front();
}
iterator end(void)
{
return begin()+size();
}
const_iterator begin(void)const
{
return begin();
}
const_iterator end(void)const
{
return end();
}
};
#endif