--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/data_buffer.h Sat Jan 11 22:36:31 2014 +0200 @@ -0,0 +1,149 @@ +/* + Copyright (c) 2013-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: + + * 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 the <organization> 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 <COPYRIGHT HOLDER> 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. +*/ + +#ifndef BOTC_DATABUFFER_H +#define BOTC_DATABUFFER_H + +#include <stdio.h> +#include <string.h> +#include "main.h" +#include "stringtable.h" + +#define MAX_MARKS 512 + +extern int g_NextMark; + +// ============================================================================ +// DataBuffer: A dynamic data buffer. +class data_buffer +{ +public: + // The actual buffer + byte* buffer; + + // Allocated size of the buffer + int allocsize; + + // Written size of the buffer + int writesize; + + // Marks and references + ScriptMark* marks[MAX_MARKS]; + ScriptMarkReference* refs[MAX_MARKS]; + + data_buffer (int size = 128); + ~data_buffer (); + + // ==================================================================== + // Write stuff to the buffer + // TODO: un-template and remove the union, move to source file + template<class T> void write (T stuff) + { + if (writesize + sizeof (T) >= allocsize) + { + // 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[allocsize]; + memcpy (copy, buffer, allocsize); + + // 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. + size_t newsize = allocsize + sizeof (T) + 128; + + delete buffer; + buffer = new unsigned char[newsize]; + allocsize = newsize; + + // Now, copy the stuff back. + memcpy (buffer, copy, allocsize); + delete copy; + } + + // Buffer is now guaranteed to have enough space. + // Write the stuff one byte at a time. + generic_union<T> uni; + uni.as_t = stuff; + + for (int x = 0; x < sizeof (T); x++) + { + if (writesize >= allocsize) // should NEVER happen because resizing is done above + error ("DataBuffer: written size exceeds allocated size!\n"); + + buffer[writesize] = uni.b[x]; + writesize++; + } + } + + // ==================================================================== + // Merge another data buffer into this one. + void merge (data_buffer* other); + + // Clones this databuffer to a new one and returns it. + data_buffer* clone (); + + // ==================================================================== + // Adds a mark to the buffer. A mark is a "pointer" to a particular + // position in the bytecode. The actual permanent position cannot + // be predicted in any way or form, thus these things will be used + // to "mark" a position like that for future use. + int add_mark (string name); + + // ==================================================================== + // A ref is another "mark" that references a mark. When the bytecode + // is written to file, they are changed into their marks' current + // positions. Marks themselves are never written to files, only refs are + int add_reference (int marknum, bool placeholder = true); + + // Delete a mark and all references to it. + void delete_mark (int marknum); + + // Adjusts a mark to the current position + void move_mark(int i); + + void offset_mark (int mark, int offset); + + // Dump the buffer (for debugging purposes) + void dump(); + + // Count the amount of marks + int count_marks (); + + // Count the amount of refs + int count_references (); + + // Write a float into the buffer + void write_float (string floatstring); + + void write_string (string a); +}; + +#endif // BOTC_DATABUFFER_H