src/dataBuffer.cpp

changeset 119
bdf8d46c145f
child 125
85814c0918c5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dataBuffer.cpp	Sun Mar 30 21:51:23 2014 +0300
@@ -0,0 +1,242 @@
+/*
+	Copyright 2012-2014 Santeri Piippo
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions
+	are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. 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.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+*/
+
+#include "dataBuffer.h"
+
+// ============================================================================
+//
+DataBuffer::DataBuffer (int size)
+{
+	setBuffer (new char[size]);
+	setPosition (&buffer()[0]);
+	setAllocatedSize (size);
+}
+
+// ============================================================================
+//
+DataBuffer::~DataBuffer()
+{
+	assert (marks().isEmpty() && references().isEmpty());
+	delete buffer();
+}
+
+// ============================================================================
+//
+void DataBuffer::mergeAndDestroy (DataBuffer* other)
+{
+	if (other == null)
+		return;
+
+	// Note: We transfer the marks before the buffer is copied, so that the
+	// offset uses the proper value (which is the written size of @other, which
+	// we don't want our written size to be added to yet).
+	other->transferMarksTo (this);
+	copyBuffer (other);
+	delete other;
+}
+
+// ============================================================================
+//
+// Clones this databuffer to a new one and returns it. Note that the original
+// transfers its marks and references and loses them in the process.
+//
+DataBuffer* DataBuffer::clone()
+{
+	DataBuffer* other = new DataBuffer;
+	transferMarksTo (other);
+	other->copyBuffer (this);
+	return other;
+}
+
+// ============================================================================
+//
+void DataBuffer::copyBuffer (const DataBuffer* buf)
+{
+	checkSpace (buf->writtenSize());
+	memcpy (m_position, buf->buffer(), buf->writtenSize());
+	m_position += buf->writtenSize();
+}
+
+// ============================================================================
+//
+void DataBuffer::transferMarksTo (DataBuffer* dest)
+{
+	int offset = dest->writtenSize();
+
+	for (ByteMark* mark : marks())
+	{
+		mark->pos += offset;
+		dest->m_marks << mark;
+	}
+
+	for (MarkReference* ref : references())
+	{
+		ref->pos += offset;
+		dest->m_references << ref;
+	}
+
+	m_marks.clear();
+	m_references.clear();
+}
+
+// ============================================================================
+//
+ByteMark* DataBuffer::addMark (const String& name)
+{
+	ByteMark* mark = new ByteMark;
+	mark->name = name;
+	mark->pos = writtenSize();
+	m_marks << mark;
+	return mark;
+}
+
+// ============================================================================
+//
+MarkReference* DataBuffer::addReference (ByteMark* mark)
+{
+	MarkReference* ref = new MarkReference;
+	ref->target = mark;
+	ref->pos = writtenSize();
+	m_references << ref;
+
+	// Write a dummy placeholder for the reference
+	writeDWord (0xBEEFCAFE);
+
+	return ref;
+}
+
+// ============================================================================
+//
+void DataBuffer::adjustMark (ByteMark* mark)
+{
+	mark->pos = writtenSize();
+}
+
+// ============================================================================
+//
+void DataBuffer::offsetMark (ByteMark* mark, int position)
+{
+	mark->pos += position;
+}
+
+// ============================================================================
+//
+void DataBuffer::writeStringIndex (const String& a)
+{
+	writeDWord (DH_PushStringIndex);
+	writeDWord (getStringTableIndex (a));
+}
+
+// ============================================================================
+//
+void DataBuffer::dump()
+{
+	for (int i = 0; i < writtenSize(); ++i)
+		printf ("%d. [0x%X]\n", i, buffer()[i]);
+}
+
+// ============================================================================
+//
+void DataBuffer::checkSpace (int bytes)
+{
+	int writesize = writtenSize();
+
+	if (writesize + bytes < allocatedSize())
+		return;
+
+	// We don't have enough space in the buffer to write
+	// the stuff - thus resize. First, store the old
+	// buffer temporarily:
+	char* copy = new char[allocatedSize()];
+	memcpy (copy, buffer(), allocatedSize());
+
+	// Remake the buffer with the new size. Have enough space
+	// for the stuff we're going to write, as well as a bit
+	// of leeway so we don't have to resize immediately again.
+	int newsize = allocatedSize() + bytes + 512;
+
+	delete buffer();
+	setBuffer (new char[newsize]);
+	setAllocatedSize (newsize);
+
+	// Now, copy the stuff back.
+	memcpy (m_buffer, copy, allocatedSize());
+	setPosition (buffer() + writesize);
+	delete copy;
+}
+
+// =============================================================================
+//
+void DataBuffer::writeByte (int8_t data)
+{
+	checkSpace (1);
+	*m_position++ = data;
+}
+
+// =============================================================================
+//
+void DataBuffer::writeWord (int16_t data)
+{
+	checkSpace (2);
+
+	for (int i = 0; i < 2; ++i)
+		*m_position++ = (data >> (i * 8)) & 0xFF;
+}
+
+// =============================================================================
+//
+void DataBuffer::writeDWord (int32_t data)
+{
+	checkSpace (4);
+
+	for (int i = 0; i < 4; ++i)
+		*m_position++ = (data >> (i * 8)) & 0xFF;
+}
+
+// =============================================================================
+//
+void DataBuffer::writeString (const String& a)
+{
+	checkSpace (a.length() + 4);
+	writeDWord (a.length());
+
+	for (char c : a)
+		writeByte (c);
+}
+
+
+// =============================================================================
+//
+ByteMark* DataBuffer::findMarkByName (const String& name)
+{
+	for (ByteMark* mark : marks())
+		if (mark->name == name)
+			return mark;
+
+	return null;
+}

mercurial