Mercurial > projects > hoofbaby
view deps/Platinum/ThirdParty/Neptune/Source/Core/NptStreams.cpp @ 0:3425707ddbf6
Initial import (hopefully this mercurial stuff works...)
author | fraserofthenight |
---|---|
date | Mon, 06 Jul 2009 08:06:28 -0700 |
parents | |
children |
line wrap: on
line source
/***************************************************************** | | Neptune - Byte Streams | | Copyright (c) 2002-2008, Axiomatic Systems, LLC. | All rights reserved. | | Redistribution and use in source and binary forms, with or without | modification, are permitted provided that the following conditions are met: | * Redistributions of source code must retain the above copyright | notice, this list of conditions and the following disclaimer. | * Redistributions in binary form must reproduce the above copyright | notice, this list of conditions and the following disclaimer in the | documentation and/or other materials provided with the distribution. | * Neither the name of Axiomatic Systems nor the | names of its contributors may be used to endorse or promote products | derived from this software without specific prior written permission. | | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ****************************************************************/ /*---------------------------------------------------------------------- | includes +---------------------------------------------------------------------*/ #include "NptStreams.h" #include "NptUtils.h" #include "NptConstants.h" #include "NptStrings.h" #include "NptDebug.h" /*---------------------------------------------------------------------- | constants +---------------------------------------------------------------------*/ const NPT_Size NPT_INPUT_STREAM_LOAD_DEFAULT_READ_CHUNK = 4096; const NPT_LargeSize NPT_INPUT_STREAM_LOAD_MAX_SIZE = 0x100000; // 1GB /*---------------------------------------------------------------------- | NPT_InputStream::Load +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::Load(NPT_DataBuffer& buffer, NPT_Size max_read /* = 0 */) { NPT_Result result; NPT_LargeSize total_bytes_read; // reset the buffer buffer.SetDataSize(0); // check the limits if (max_read > NPT_INPUT_STREAM_LOAD_MAX_SIZE) { return NPT_ERROR_INVALID_PARAMETERS; } // try to get the stream size NPT_LargeSize size; if (NPT_SUCCEEDED(GetSize(size))) { // make sure we don't read more than max_read if (max_read && max_read < size) size = max_read; if (size > NPT_INPUT_STREAM_LOAD_MAX_SIZE) { return NPT_ERROR_OUT_OF_RANGE; } } else { size = max_read; } // pre-allocate the buffer if (size) NPT_CHECK(buffer.Reserve((NPT_Size)size)); // read the data from the file total_bytes_read = 0; do { NPT_LargeSize available = 0; NPT_LargeSize bytes_to_read; NPT_Size bytes_read; NPT_Byte* data; // check if we know how much data is available result = GetAvailable(available); if (NPT_SUCCEEDED(result) && available) { // we know how much is available bytes_to_read = available; } else { bytes_to_read = NPT_INPUT_STREAM_LOAD_DEFAULT_READ_CHUNK; } // make sure we don't read more than what was asked if (size != 0 && total_bytes_read+bytes_to_read>size) { bytes_to_read = size-total_bytes_read; } // stop if we've read everything if (bytes_to_read == 0) break; // ensure that the buffer has enough space if (total_bytes_read+bytes_to_read > NPT_INPUT_STREAM_LOAD_MAX_SIZE) { buffer.SetBufferSize(0); return NPT_ERROR_OUT_OF_RANGE; } NPT_CHECK(buffer.Reserve((NPT_Size)(total_bytes_read+bytes_to_read))); // read the data data = buffer.UseData()+total_bytes_read; result = Read((void*)data, (NPT_Size)bytes_to_read, &bytes_read); if (NPT_SUCCEEDED(result) && bytes_read != 0) { total_bytes_read += bytes_read; buffer.SetDataSize((NPT_Size)total_bytes_read); } } while(NPT_SUCCEEDED(result) && (size==0 || total_bytes_read < size)); if (result == NPT_ERROR_EOS) { return NPT_SUCCESS; } else { return result; } } /*---------------------------------------------------------------------- | NPT_InputStream::ReadFully +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::ReadFully(void* buffer, NPT_Size bytes_to_read) { // shortcut if (bytes_to_read == 0) return NPT_SUCCESS; // read until failure NPT_Size bytes_read; while (bytes_to_read) { NPT_Result result = Read(buffer, bytes_to_read, &bytes_read); if (NPT_FAILED(result)) return result; if (bytes_read == 0) return NPT_ERROR_INTERNAL; NPT_ASSERT(bytes_read <= bytes_to_read); bytes_to_read -= bytes_read; buffer = (void*)(((NPT_Byte*)buffer)+bytes_read); } return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_InputStream::ReadUI64 +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::ReadUI64(NPT_UInt64& value) { unsigned char buffer[8]; // read bytes from the stream NPT_Result result; result = ReadFully((void*)buffer, 8); if (NPT_FAILED(result)) { value = 0; return result; } // convert bytes to value value = NPT_BytesToInt64Be(buffer); return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_InputStream::ReadUI32 +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::ReadUI32(NPT_UInt32& value) { unsigned char buffer[4]; // read bytes from the stream NPT_Result result; result = ReadFully((void*)buffer, 4); if (NPT_FAILED(result)) { value = 0; return result; } // convert bytes to value value = NPT_BytesToInt32Be(buffer); return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_InputStream::ReadUI24 +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::ReadUI24(NPT_UInt32& value) { unsigned char buffer[3]; // read bytes from the stream NPT_Result result; result = ReadFully((void*)buffer, 3); if (NPT_FAILED(result)) { value = 0; return result; } // convert bytes to value value = NPT_BytesToInt24Be(buffer); return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_InputStream::ReadUI16 +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::ReadUI16(NPT_UInt16& value) { unsigned char buffer[2]; // read bytes from the stream NPT_Result result; result = ReadFully((void*)buffer, 2); if (NPT_FAILED(result)) { value = 0; return result; } // convert bytes to value value = NPT_BytesToInt16Be(buffer); return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_InputStream::ReadUI08 +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::ReadUI08(NPT_UInt8& value) { unsigned char buffer[1]; // read bytes from the stream NPT_Result result; result = ReadFully((void*)buffer, 1); if (NPT_FAILED(result)) { value = 0; return result; } // convert bytes to value value = buffer[0]; return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_InputStream::Skip +---------------------------------------------------------------------*/ NPT_Result NPT_InputStream::Skip(NPT_Size count) { // get the current location NPT_Position position; NPT_CHECK(Tell(position)); // seek ahead return Seek(position+count); } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteFully +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteFully(const void* buffer, NPT_Size bytes_to_write) { // shortcut if (bytes_to_write == 0) return NPT_SUCCESS; // write until failure NPT_Size bytes_written; while (bytes_to_write) { NPT_Result result = Write(buffer, bytes_to_write, &bytes_written); if (NPT_FAILED(result)) return result; if (bytes_written == 0) return NPT_ERROR_INTERNAL; NPT_ASSERT(bytes_written <= bytes_to_write); bytes_to_write -= bytes_written; buffer = (const void*)(((const NPT_Byte*)buffer)+bytes_written); } return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteString +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteString(const char* buffer) { // shortcut NPT_Size string_length; if (buffer == NULL || (string_length = NPT_StringLength(buffer)) == 0) { return NPT_SUCCESS; } // write the string return WriteFully((const void*)buffer, string_length); } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteLine +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteLine(const char* buffer) { NPT_CHECK(WriteString(buffer)); NPT_CHECK(WriteFully((const void*)"\r\n", 2)); return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteUI64 +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteUI64(NPT_UInt64 value) { unsigned char buffer[8]; // convert value to bytes NPT_BytesFromInt64Be(buffer, value); // write bytes to the stream return WriteFully((void*)buffer, 8); } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteUI32 +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteUI32(NPT_UInt32 value) { unsigned char buffer[4]; // convert value to bytes NPT_BytesFromInt32Be(buffer, value); // write bytes to the stream return WriteFully((void*)buffer, 4); } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteUI24 +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteUI24(NPT_UInt32 value) { unsigned char buffer[3]; // convert value to bytes NPT_BytesFromInt24Be(buffer, value); // write bytes to the stream return WriteFully((void*)buffer, 3); } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteUI16 +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteUI16(NPT_UInt16 value) { unsigned char buffer[2]; // convert value to bytes NPT_BytesFromInt16Be(buffer, value); // write bytes to the stream return WriteFully((void*)buffer, 2); } /*---------------------------------------------------------------------- | NPT_OutputStream::WriteUI08 +---------------------------------------------------------------------*/ NPT_Result NPT_OutputStream::WriteUI08(NPT_UInt8 value) { return WriteFully((void*)&value, 1); } /*---------------------------------------------------------------------- | NPT_MemoryStream::NPT_MemoryStream +---------------------------------------------------------------------*/ NPT_MemoryStream::NPT_MemoryStream(NPT_Size initial_capacity) : m_Buffer(initial_capacity), m_ReadOffset(0), m_WriteOffset(0) { } /*---------------------------------------------------------------------- | NPT_MemoryStream::NPT_MemoryStream +---------------------------------------------------------------------*/ NPT_MemoryStream::NPT_MemoryStream(const void* data, NPT_Size size) : m_Buffer(data, size), m_ReadOffset(0), m_WriteOffset(0) { } /*---------------------------------------------------------------------- | NPT_MemoryStream::Read +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::Read(void* buffer, NPT_Size bytes_to_read, NPT_Size* bytes_read) { // check for shortcut if (bytes_to_read == 0) { if (bytes_read) *bytes_read = 0; return NPT_SUCCESS; } // clip to what's available NPT_Size available = m_Buffer.GetDataSize(); if (m_ReadOffset+bytes_to_read > available) { bytes_to_read = available-m_ReadOffset; } // copy the data if (bytes_to_read) { NPT_CopyMemory(buffer, (void*)(((char*)m_Buffer.UseData())+m_ReadOffset), bytes_to_read); m_ReadOffset += bytes_to_read; } if (bytes_read) *bytes_read = bytes_to_read; return bytes_to_read?NPT_SUCCESS:NPT_ERROR_EOS; } /*---------------------------------------------------------------------- | NPT_MemoryStream::InputSeek +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::InputSeek(NPT_Position offset) { if (offset > m_Buffer.GetDataSize()) { return NPT_ERROR_OUT_OF_RANGE; } else { m_ReadOffset = (NPT_Size)offset; return NPT_SUCCESS; } } /*---------------------------------------------------------------------- | NPT_MemoryStream::Write +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::Write(const void* data, NPT_Size bytes_to_write, NPT_Size* bytes_written) { NPT_CHECK(m_Buffer.Reserve(m_WriteOffset+bytes_to_write)); NPT_CopyMemory(m_Buffer.UseData()+m_WriteOffset, data, bytes_to_write); m_WriteOffset += bytes_to_write; if (m_WriteOffset > m_Buffer.GetDataSize()) { m_Buffer.SetDataSize(m_WriteOffset); } if (bytes_written) *bytes_written = bytes_to_write; return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_MemoryStream::OutputSeek +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::OutputSeek(NPT_Position offset) { if (offset <= m_Buffer.GetDataSize()) { m_WriteOffset = (NPT_Size)offset; return NPT_SUCCESS; } else { return NPT_ERROR_OUT_OF_RANGE; } } /*---------------------------------------------------------------------- | NPT_MemoryStream::SetSize +---------------------------------------------------------------------*/ NPT_Result NPT_MemoryStream::SetSize(NPT_Size size) { // try to resize the data buffer NPT_CHECK(m_Buffer.SetDataSize(size)); // adjust the read and write offsets if (m_ReadOffset > size) m_ReadOffset = size; if (m_WriteOffset > size) m_WriteOffset = size; return NPT_SUCCESS; } /*---------------------------------------------------------------------- | NPT_StreamToStreamCopy +---------------------------------------------------------------------*/ const unsigned int NPT_STREAM_COPY_BUFFER_SIZE = 4096; // copy 4k at a time NPT_Result NPT_StreamToStreamCopy(NPT_InputStream& from, NPT_OutputStream& to, NPT_Position offset /* = 0 */, NPT_LargeSize size /* = 0, 0 means the entire stream */) { // seek into the input if required if (offset) { NPT_CHECK(from.Seek(offset)); } // allocate a buffer for the transfer NPT_LargeSize bytes_transfered = 0; NPT_Byte* buffer = new NPT_Byte[NPT_STREAM_COPY_BUFFER_SIZE]; NPT_Result result = NPT_SUCCESS; if (buffer == NULL) return NPT_ERROR_OUT_OF_MEMORY; // copy until an error occurs or the end of stream is reached for (;;) { // read some data NPT_Size bytes_to_read = NPT_STREAM_COPY_BUFFER_SIZE; NPT_Size bytes_read = 0; if (size) { // a max size was specified if (bytes_to_read > (NPT_Size)(size-bytes_transfered)) { bytes_to_read = (NPT_Size)(size-bytes_transfered); } } result = from.Read(buffer, bytes_to_read, &bytes_read); if (NPT_FAILED(result)) { if (result == NPT_ERROR_EOS) result = NPT_SUCCESS; break; } if (bytes_read == 0) continue; // write the data result = to.WriteFully(buffer, bytes_read); if (NPT_FAILED(result)) break; // update the counts if (size) { bytes_transfered += bytes_read; if (bytes_transfered >= size) break; } } // free the buffer and return delete[] buffer; return result; } /*---------------------------------------------------------------------- | NPT_StringOutputStream::NPT_StringOutputStream +---------------------------------------------------------------------*/ NPT_StringOutputStream::NPT_StringOutputStream(NPT_Size size) : m_String(new NPT_String), m_StringIsOwned(true) { m_String->Reserve(size); } /*---------------------------------------------------------------------- | NPT_StringOutputStream::NPT_StringOutputStream +---------------------------------------------------------------------*/ NPT_StringOutputStream::NPT_StringOutputStream(NPT_String* storage) : m_String(storage), m_StringIsOwned(false) { } /*---------------------------------------------------------------------- | NPT_StringOutputStream::~NPT_StringOutputStream +---------------------------------------------------------------------*/ NPT_StringOutputStream::~NPT_StringOutputStream() { if (m_StringIsOwned) delete m_String; } /*---------------------------------------------------------------------- | NPT_StringOutputStream::Write +---------------------------------------------------------------------*/ NPT_Result NPT_StringOutputStream::Write(const void* buffer, NPT_Size bytes_to_write, NPT_Size* bytes_written /* = NULL */) { m_String->Append((const char*)buffer, bytes_to_write); if (bytes_written) *bytes_written = bytes_to_write; return NPT_SUCCESS; }