// 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); 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); 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); 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& get_buf() const { return m_buf; } crnlib::vector& 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(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(new_ofs); post_seek(); return true; } private: crnlib::vector m_buf; uint m_ofs; }; } // namespace crnlib