aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/ChunkFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/ChunkFile.cpp')
-rw-r--r--SrcShared/ChunkFile.cpp830
1 files changed, 830 insertions, 0 deletions
diff --git a/SrcShared/ChunkFile.cpp b/SrcShared/ChunkFile.cpp
new file mode 100644
index 0000000..620d97d
--- /dev/null
+++ b/SrcShared/ChunkFile.cpp
@@ -0,0 +1,830 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 1999-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "ChunkFile.h"
+
+#include "Byteswapping.h" // Canonical
+#include "Platform.h" // ReallocMemory
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile constructor
+ *
+ * DESCRIPTION: Initialize the ChunkFile object. Sets the fStream data
+ * member to refer to the given EmStream (which must
+ * exist for the life of the ChunkFile).
+ *
+ * PARAMETERS: s - EmStream to utilize for read/write operations.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+ChunkFile::ChunkFile (EmStream& s) :
+ fStream (s)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile destructor
+ *
+ * DESCRIPTION: Releases ChunkFile resources. Currently does nothing.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+ChunkFile::~ChunkFile (void)
+{
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::FindChunk
+ *
+ * DESCRIPTION: Find the requested chunk. If successful, the file
+ * marker will be pointing to the chunk data which can
+ * then be read with ReadChunk.
+ *
+ * PARAMETERS: targetTag - the tag of the chunk to find.
+ *
+ * RETURNED: Size of the chunk, in bytes. If the chunk can't be
+ * found, kChunkNotFound is returned.
+ *
+ ***********************************************************************/
+
+long ChunkFile::FindChunk (Tag targetTag)
+{
+ long len = kChunkNotFound;
+ long fileOffset = 0;
+ long fileLength = fStream.GetLength ();
+
+ fStream.SetMarker (fileOffset, kStreamFromStart);
+
+ while (fileOffset < fileLength)
+ {
+ Tag chunkTag;
+ long chunkLen;
+
+ fStream.GetBytes (&chunkTag, sizeof (chunkTag));
+ fStream.GetBytes (&chunkLen, sizeof (chunkLen));
+
+ Canonical (chunkTag);
+ Canonical (chunkLen);
+
+ if (chunkTag == targetTag)
+ {
+ len = chunkLen;
+ break;
+ }
+
+ fStream.SetMarker (chunkLen, kStreamFromMarker);
+ fileOffset += sizeof (chunkTag) + sizeof (chunkLen) + chunkLen;
+ }
+
+ return len;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadChunk
+ *
+ * DESCRIPTION: Find the requested chunk. If successful, the file
+ * marker will be pointing to the chunk data which can
+ * then be read with ReadChunk.
+ *
+ * PARAMETERS: targetTag - the tag of the chunk to find.
+ *
+ * RETURNED: Size of the chunk, in bytes. If the chunk can't be
+ * found, kChunkNotFound is returned.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadChunk (int index, Tag& tag, Chunk& chunk)
+{
+ long fileOffset = 0;
+ long fileLength = fStream.GetLength ();
+
+ fStream.SetMarker (fileOffset, kStreamFromStart);
+
+ while (fileOffset < fileLength)
+ {
+ // Read the chunk's tag and length.
+
+ Tag chunkTag;
+ long chunkLen;
+
+ fStream.GetBytes (&chunkTag, sizeof (chunkTag));
+ fStream.GetBytes (&chunkLen, sizeof (chunkLen));
+
+ Canonical (chunkTag);
+ Canonical (chunkLen);
+
+ // If this is the chunk we're looking for, read it in.
+
+ if (index == 0)
+ {
+ tag = chunkTag;
+ chunk.SetLength (chunkLen);
+ this->ReadChunk (chunkLen, chunk.GetPointer ());
+
+ // Return that we found the chunk.
+
+ return true;
+ }
+
+ // Move to the next chunk.
+
+ fStream.SetMarker (chunkLen, kStreamFromMarker);
+ fileOffset += sizeof (chunkTag) + sizeof (chunkLen) + chunkLen;
+ --index;
+ }
+
+ // Return that we didn't find the chunk.
+
+ return false;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadChunk
+ *
+ * DESCRIPTION: Read a block of bytes into the given buffer.
+ *
+ * PARAMETERS: tag - marker identifying the data to read.
+ *
+ * chunk - object to contain the returned data.
+ *
+ * RETURNED: True if the data was found and read in.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadChunk (Tag tag, Chunk& chunk)
+{
+ long size = this->FindChunk (tag);
+
+ if (size == kChunkNotFound)
+ return false;
+
+ chunk.SetLength (size);
+ this->ReadChunk (size, chunk.GetPointer ());
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadInt
+ *
+ * DESCRIPTION: Read an integer (scalar) from the file.
+ *
+ * PARAMETERS: tag - marker of the value to be read.
+ *
+ * val - reference to variable to receive the integer.
+ *
+ * RETURNED: True if the value existed; false if the tag could not
+ * be found.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadInt (Tag tag, uint8& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, int8& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, uint16& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, int16& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, uint32& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+Bool ChunkFile::ReadInt (Tag tag, int32& val)
+{
+ if (ChunkFile::FindChunk (tag) == kChunkNotFound)
+ return false;
+
+ ChunkFile::ReadChunk (sizeof (val), &val);
+ Canonical (val);
+
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadString
+ *
+ * DESCRIPTION: Read a string from the file.
+ *
+ * PARAMETERS: tag - marker of the string to be read.
+ *
+ * s - reference to variable to receive the string.
+ *
+ * RETURNED: True if the string existed; false if the tag could not
+ * be found.
+ *
+ ***********************************************************************/
+
+Bool ChunkFile::ReadString (Tag tag, char* s)
+{
+ long len = ChunkFile::FindChunk (tag);
+ if (len == kChunkNotFound)
+ return false;
+
+ if (len > 0)
+ {
+ ChunkFile::ReadChunk (len, s);
+ }
+
+ s[len] = '\0'; // Null terminator
+
+ return true;
+}
+
+Bool ChunkFile::ReadString (Tag tag, string& s)
+{
+ long len = ChunkFile::FindChunk (tag);
+ if (len == kChunkNotFound)
+ return false;
+
+ s.resize (len);
+ if (len > 0)
+ {
+ ChunkFile::ReadChunk (len, &s[0]);
+ }
+
+ return true;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteChunk
+ *
+ * DESCRIPTION: Write the given data to the file. The data is marked
+ * with the given tag. No effort is made to find any
+ * existing chunks with the same tag and deleting them.
+ *
+ * PARAMETERS: tag - marker for the data being written.
+ *
+ * chunk - object containing the data to write.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteChunk (Tag tag, const Chunk& chunk)
+{
+ this->WriteChunk (tag, chunk.GetLength (), chunk.GetPointer ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteInt
+ *
+ * DESCRIPTION: Write the given value to disk, marking it with the
+ * given tag.
+ *
+ * PARAMETERS: tag - marker used to later retrieve the value.
+ *
+ * val - integer to write to disk. All integers are
+ * stored in Big Endian format, and are written in
+ * their native size (1, 2, or 4 bytes).
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteInt (Tag tag, uint8 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, int8 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, uint16 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, int16 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, uint32 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+void ChunkFile::WriteInt (Tag tag, int32 val)
+{
+ Canonical (val);
+ ChunkFile::WriteChunk (tag, sizeof (val), &val);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteString
+ *
+ * DESCRIPTION: Write the given string to disk, marking it with the
+ * given tag.
+ *
+ * PARAMETERS: tag - marker used to later retrieve the value.
+ *
+ * s - string to write to disk.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteString (Tag tag, const char* s)
+{
+ ChunkFile::WriteChunk (tag, strlen (s), s);
+}
+
+void ChunkFile::WriteString (Tag tag, const string& s)
+{
+ ChunkFile::WriteChunk (tag, s.size (), s.c_str ());
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::ReadChunk
+ *
+ * DESCRIPTION: Read a block of bytes into the given buffer
+ *
+ * PARAMETERS: size - number of bytes to read.
+ *
+ * data - buffer to write the bytes to.
+ *
+ * RETURNED: Nothing (exceptions can be thrown).
+ *
+ ***********************************************************************/
+
+void ChunkFile::ReadChunk (uint32 size, void* data)
+{
+ // Merely read the requested bytes starting at the current location.
+
+ fStream.GetBytes (data, size);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::WriteChunk
+ *
+ * DESCRIPTION: Write the given data to the file. The data is marked
+ * with the given tag. No effort is made to find any
+ * existing chunks with the same tag and deleting them.
+ *
+ * PARAMETERS: tag - marker for the data being written.
+ *
+ * size - number of bytes to write.
+ *
+ * data - pointer to buffer containing bytes to write.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void ChunkFile::WriteChunk (Tag tag, uint32 size, const void* data)
+{
+ // Write the 4-byte tag in Big Endian format.
+
+ Canonical (tag);
+ fStream.PutBytes (&tag, sizeof (tag));
+
+ // Write the chunk size in Big Endian format. Return the size
+ // back to host format when done so that it can be used to write
+ // the actual data.
+
+ Canonical (size);
+ fStream.PutBytes (&size, sizeof (size));
+ Canonical (size);
+
+ // Write the chunk data.
+
+ fStream.PutBytes (data, size);
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: ChunkFile::GetFile
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: Nothing.
+ *
+ ***********************************************************************/
+
+EmStream& ChunkFile::GetStream (void) const
+{
+ return fStream;
+}
+
+
+#pragma mark -
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::Chunk
+ *
+ * DESCRIPTION: Default constructor. Creates a "chunk" that initially
+ * has no memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+Chunk::Chunk (void) :
+ fPtr (NULL),
+ fUsedSize (0),
+ fAllocatedSize (0)
+{
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::Chunk
+ *
+ * DESCRIPTION: Parameterized constructor. Creates a "chunk" with a
+ * block of memory with the given length.
+ *
+ * PARAMETERS: inLength - number of bytes for the initial block of
+ * memory.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Chunk::Chunk (long inLength) :
+ fPtr (NULL),
+ fUsedSize (0),
+ fAllocatedSize (0)
+{
+ SetLength (inLength);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::Chunk
+ *
+ * DESCRIPTION: Copy constructor. Creates a "chunk" containing a copy
+ * of the given data.
+ *
+ * PARAMETERS: other - chunk containing the data to copy.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Chunk::Chunk (const Chunk& other) :
+ fPtr (NULL),
+ fUsedSize (0),
+ fAllocatedSize (0)
+{
+ this->SetLength (other.GetLength ());
+ memcpy (this->GetPointer (), other.GetPointer (), other.GetLength ());
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::~Chunk
+ *
+ * DESCRIPTION: Destructor. Disposes of the owned block of memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+Chunk::~Chunk (void)
+{
+ Platform::DisposeMemory (fPtr);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::operator=
+ *
+ * DESCRIPTION: Assignment operator. Makes the controlled chunk
+ * contain a copy of the data managed by the other chunk.
+ *
+ * PARAMETERS: other - chunk containing the data to copy.
+ *
+ * RETURNED: Referenced to the controlled object.
+ *
+ ***********************************************************************/
+
+Chunk& Chunk::operator= (const Chunk& other)
+{
+ if (this != &other)
+ {
+ this->SetLength (other.GetLength ());
+ memcpy (this->GetPointer (), other.GetPointer (), other.GetLength ());
+ }
+
+ return *this;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::GetPointer
+ *
+ * DESCRIPTION: Returns a pointer to the owned block of memory.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: A pointer to the owned block of memory.
+ *
+ ***********************************************************************/
+
+void* Chunk::GetPointer (void) const
+{
+ return fPtr;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::GetLength
+ *
+ * DESCRIPTION: Returns the number of useable bytes in the block of
+ * memory. The actual number of allocated bytes may be
+ * larger, but shouldn't be used.
+ *
+ * PARAMETERS: None
+ *
+ * RETURNED: The number of usable bytes in the chunk.
+ *
+ ***********************************************************************/
+
+long Chunk::GetLength (void) const
+{
+ return fUsedSize;
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: Chunk::SetLength
+ *
+ * DESCRIPTION: Set the number of useable bytes in the owned block of
+ * memory. The number of bytes actually allocated may
+ * be greater than passed in. After this call, any
+ * previous pointers returned by GetPointer may be
+ * invalid.
+ *
+ * PARAMETERS: inLength - the number of useable bytes to make available.
+ *
+ * RETURNED: Nothing
+ *
+ ***********************************************************************/
+
+void Chunk::SetLength (long inLength)
+{
+ if (inLength > fAllocatedSize)
+ {
+ const long kSlushFund = 100;
+ long newAllocatedLength = inLength + kSlushFund;
+ fPtr = Platform::ReallocMemory (fPtr, newAllocatedLength);
+ fAllocatedSize = newAllocatedLength;
+ }
+
+ // As a special case, allow the clean up of memory by setting the
+ // length to zero.
+
+ else if (inLength == 0)
+ {
+ Platform::DisposeMemory (fPtr);
+ fAllocatedSize = 0;
+ }
+
+ fUsedSize = inLength;
+}
+
+
+// ===========================================================================
+// EmStreamChunk.cpp
+// ===========================================================================
+//
+// A Stream whose bytes are in a Chunk
+
+
+// ---------------------------------------------------------------------------
+// ¥ EmStreamChunk(Handle) Parameterized Constructor [public]
+// ---------------------------------------------------------------------------
+// Construct from an existing Chunk
+
+EmStreamChunk::EmStreamChunk(Chunk* chunk) :
+ EmStream (),
+ fChunk (*chunk),
+ fOwnedChunk (chunk)
+{
+ EmStream::SetLength (fChunk.GetLength ());
+}
+
+
+EmStreamChunk::EmStreamChunk(Chunk& chunk) :
+ EmStream (),
+ fChunk (chunk),
+ fOwnedChunk (NULL)
+{
+ EmStream::SetLength (fChunk.GetLength ());
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ ~EmStreamChunk Destructor [public]
+// ---------------------------------------------------------------------------
+
+EmStreamChunk::~EmStreamChunk()
+{
+ delete fOwnedChunk;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ SetLength [public]
+// ---------------------------------------------------------------------------
+// Set the length, in bytes, of the EmStreamChunk
+
+void
+EmStreamChunk::SetLength(
+ int32 inLength)
+{
+ fChunk.SetLength (inLength);
+ EmStream::SetLength (inLength);
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ PutBytes
+// ---------------------------------------------------------------------------
+// Write bytes from a buffer to a EmStreamChunk
+//
+// Returns an error code and passes back the number of bytes actually
+// written, which may be less than the number requested if an error occurred.
+//
+// Grows data Chunk if necessary.
+
+ErrCode
+EmStreamChunk::PutBytes(
+ const void *inBuffer,
+ int32 ioByteCount)
+{
+ ErrCode err = errNone;
+ int32 endOfWrite = GetMarker () + ioByteCount;
+
+ if (endOfWrite > GetLength ()) // Need to grow Chunk
+ {
+ SetLength (endOfWrite);
+ }
+ // Copy bytes into Chunk
+ if (ioByteCount > 0)
+ {
+ memmove ((char*) fChunk.GetPointer () + GetMarker (), inBuffer, ioByteCount);
+ SetMarker (ioByteCount, kStreamFromMarker);
+ }
+
+ return err;
+}
+
+
+// ---------------------------------------------------------------------------
+// ¥ GetBytes
+// ---------------------------------------------------------------------------
+// Read bytes from a EmStreamChunk to a buffer
+//
+// Returns an error code and passes back the number of bytes actually
+// read, which may be less than the number requested if an error occurred.
+//
+// Errors:
+// readErr Attempt to read past the end of the EmStreamChunk
+
+ErrCode
+EmStreamChunk::GetBytes(
+ void *outBuffer,
+ int32 ioByteCount)
+{
+ ErrCode err = errNone;
+ // Upper bound is number of bytes from
+ // marker to end
+ if ((GetMarker () + ioByteCount) > GetLength ())
+ {
+ ioByteCount = GetLength () - GetMarker ();
+ err = 1;
+ }
+ // Copy bytes from Handle into buffer
+
+ memmove (outBuffer, (char*) fChunk.GetPointer () + GetMarker (), ioByteCount);
+ SetMarker (ioByteCount, kStreamFromMarker);
+
+ return err;
+}