xenia/third_party/crunch/crnlib/crn_dynamic_stream.h

207 lines
4.7 KiB
C++

// File: crn_dynamic_stream.h
// See Copyright Notice and license at the end of inc/crnlib.h
#pragma once
#include "crn_data_stream.h"
namespace crnlib
{
class dynamic_stream : public data_stream
{
public:
dynamic_stream(uint initial_size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) :
data_stream(pName, attribs),
m_ofs(0)
{
open(initial_size, pName, attribs);
}
dynamic_stream(const void* pBuf, uint size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable) :
data_stream(pName, attribs),
m_ofs(0)
{
open(pBuf, size, pName, attribs);
}
dynamic_stream() :
data_stream(),
m_ofs(0)
{
open();
}
virtual ~dynamic_stream()
{
}
bool open(uint initial_size = 0, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable)
{
close();
m_opened = true;
m_buf.clear();
m_buf.resize(initial_size);
m_ofs = 0;
m_name.set(pName ? pName : "dynamic_stream");
m_attribs = static_cast<attribs_t>(attribs);
return true;
}
bool reopen(const char* pName, uint attribs)
{
if (!m_opened)
{
return open(0, pName, attribs);
}
m_name.set(pName ? pName : "dynamic_stream");
m_attribs = static_cast<attribs_t>(attribs);
return true;
}
bool open(const void* pBuf, uint size, const char* pName = "dynamic_stream", uint attribs = cDataStreamSeekable | cDataStreamWritable | cDataStreamReadable)
{
if (!m_opened)
{
m_opened = true;
m_buf.resize(size);
if (size)
{
CRNLIB_ASSERT(pBuf);
memcpy(&m_buf[0], pBuf, size);
}
m_ofs = 0;
m_name.set(pName ? pName : "dynamic_stream");
m_attribs = static_cast<attribs_t>(attribs);
return true;
}
return false;
}
virtual bool close()
{
if (m_opened)
{
m_opened = false;
m_buf.clear();
m_ofs = 0;
return true;
}
return false;
}
const crnlib::vector<uint8>& get_buf() const { return m_buf; }
crnlib::vector<uint8>& get_buf() { return m_buf; }
void reserve(uint size)
{
if (m_opened)
{
m_buf.reserve(size);
}
}
virtual const void* get_ptr() const { return m_buf.empty() ? NULL : &m_buf[0]; }
virtual uint read(void* pBuf, uint len)
{
CRNLIB_ASSERT(pBuf && (len <= 0x7FFFFFFF));
if ((!m_opened) || (!is_readable()) || (!len))
return 0;
CRNLIB_ASSERT(m_ofs <= m_buf.size());
uint bytes_left = m_buf.size() - m_ofs;
len = math::minimum<uint>(len, bytes_left);
if (len)
memcpy(pBuf, &m_buf[m_ofs], len);
m_ofs += len;
return len;
}
virtual uint write(const void* pBuf, uint len)
{
CRNLIB_ASSERT(pBuf && (len <= 0x7FFFFFFF));
if ((!m_opened) || (!is_writable()) || (!len))
return 0;
CRNLIB_ASSERT(m_ofs <= m_buf.size());
uint new_ofs = m_ofs + len;
if (new_ofs > m_buf.size())
m_buf.resize(new_ofs);
memcpy(&m_buf[m_ofs], pBuf, len);
m_ofs = new_ofs;
return len;
}
virtual bool flush()
{
if (!m_opened)
return false;
return true;
}
virtual uint64 get_size()
{
if (!m_opened)
return 0;
return m_buf.size();
}
virtual uint64 get_remaining()
{
if (!m_opened)
return 0;
CRNLIB_ASSERT(m_ofs <= m_buf.size());
return m_buf.size() - m_ofs;
}
virtual uint64 get_ofs()
{
if (!m_opened)
return 0;
return m_ofs;
}
virtual bool seek(int64 ofs, bool relative)
{
if ((!m_opened) || (!is_seekable()))
return false;
int64 new_ofs = relative ? (m_ofs + ofs) : ofs;
if (new_ofs < 0)
return false;
else if (new_ofs > m_buf.size())
return false;
m_ofs = static_cast<uint>(new_ofs);
post_seek();
return true;
}
private:
crnlib::vector<uint8> m_buf;
uint m_ofs;
};
} // namespace crnlib