#ifndef MEMCACHE__H_
#define MEMCACHE__H_
#include <cstddef>
#include <cassert>
#include <cstring>
template<bool HOSTING>
class MemFileT{
public:
MemFileT():
m_ptr_(NULL),
m_max_(0),
m_cur_(0){}
~MemFileT(){
fclose();
}
void fclose()
{
if(m_ptr_){
if(!HOSTING)
free(m_ptr_);
m_ptr_ = NULL;
m_max_ = 0;
m_cur_ = 0;
}
}
void attach(char* ptr,size_t size)
{
if(HOSTING)
{
assert(ptr);
assert(size);
m_ptr_ = ptr;
m_max_ = size;
m_cur_ = 0;
}
}
bool fread(char*ptr,size_t size,size_t* readed)
{
assert(ptr);
assert(size);
size_t rest_ = m_max_ - m_cur_;
if(readed){
*readed = std::min(size,rest_);
if(*readed > 0){
memcpy(ptr,m_ptr_ + m_cur_,*readed);
m_cur_ += *readed;
}
}else{
if(rest_ < size)
return false;
if(size > 0){
memcpy(ptr,m_ptr_ + m_cur_,size);
m_cur_ += size;
}
}
return true;
}
bool fwrite(char*ptr,size_t size){
assert(ptr);
assert(size);
if(m_max_ - m_cur_ < size)
{
if(HOSTING)
return false;
resize(size + m_cur_);
}
memcpy(m_ptr_ + m_cur_ ,ptr,size);
m_cur_ += size;
return true;
}
bool fseek(long int offset, int origin )
{
switch(origin){
case SEEK_SET:
{
if(offset <= (long int)m_max_ && offset >= 0){
m_cur_ = offset;
return true;
}
break;
}
case SEEK_END:
{
offset = - offset;
if(offset <= (long int)m_max_ && offset >= 0)
{
m_cur_ = m_max_ - offset;
return true;
}
break;
}
case SEEK_CUR:
{
if(offset >= 0)
{
if(m_cur_ + (size_t)offset <= m_max_)
{
m_cur_ += (size_t)offset;
return true;
}
}else{
if(offset + (long int)m_cur_ >= 0)
{
m_cur_ += offset;
return true;
}
}
break;
}
};
return false;
}
size_t ftell() const{
return m_cur_;
}
private:
void resize(size_t size)
{
char* oldptr = m_ptr_;
char* newptr = static_cast<char*>(malloc(size));
assert(newptr);
if(oldptr){
if(m_cur_)
memcpy(newptr,oldptr,m_cur_);
free(oldptr);
}
m_ptr_ = newptr;
m_max_ = size;
}
private:
char* m_ptr_;
size_t m_max_;
size_t m_cur_;
};
typedef MemFileT<true> MemFileHandle;
typedef MemFileT<false> MemFile;
#endif