|         | 
     1 /* | 
|         | 
     2 	Copyright (c) 2013-2014, Santeri Piippo | 
|         | 
     3 	All rights reserved. | 
|         | 
     4  | 
|         | 
     5 	Redistribution and use in source and binary forms, with or without | 
|         | 
     6 	modification, are permitted provided that the following conditions are met: | 
|         | 
     7  | 
|         | 
     8 		* Redistributions of source code must retain the above copyright | 
|         | 
     9 		  notice, this list of conditions and the following disclaimer. | 
|         | 
    10  | 
|         | 
    11 		* Redistributions in binary form must reproduce the above copyright | 
|         | 
    12 		  notice, this list of conditions and the following disclaimer in the | 
|         | 
    13 		  documentation and/or other materials provided with the distribution. | 
|         | 
    14  | 
|         | 
    15 		* Neither the name of the <organization> nor the | 
|         | 
    16 		  names of its contributors may be used to endorse or promote products | 
|         | 
    17 		  derived from this software without specific prior written permission. | 
|         | 
    18  | 
|         | 
    19 	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | 
|         | 
    20 	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
|         | 
    21 	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
|         | 
    22 	DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY | 
|         | 
    23 	DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
|         | 
    24 	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
|         | 
    25 	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
|         | 
    26 	ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|         | 
    27 	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|         | 
    28 	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|         | 
    29 */ | 
|         | 
    30  | 
|         | 
    31 #include "data_buffer.h" | 
|         | 
    32  | 
|         | 
    33 // ============================================================================ | 
|         | 
    34 // | 
|         | 
    35 void data_buffer::merge (data_buffer* other) | 
|         | 
    36 { | 
|         | 
    37 	if (!other) | 
|         | 
    38 		return; | 
|         | 
    39  | 
|         | 
    40 	int oldsize = writesize; | 
|         | 
    41  | 
|         | 
    42 	for (int x = 0; x < other->writesize; x++) | 
|         | 
    43 		write (* (other->buffer + x)); | 
|         | 
    44  | 
|         | 
    45 	// Merge its marks and references | 
|         | 
    46 	int u = 0; | 
|         | 
    47  | 
|         | 
    48 	for (u = 0; u < MAX_MARKS; u++) | 
|         | 
    49 	{ | 
|         | 
    50 		if (other->marks[u]) | 
|         | 
    51 		{ | 
|         | 
    52 			// Merge the mark and offset its position. | 
|         | 
    53 			if (marks[u]) | 
|         | 
    54 				error ("DataBuffer: duplicate mark %d!\n"); | 
|         | 
    55  | 
|         | 
    56 			marks[u] = other->marks[u]; | 
|         | 
    57 			marks[u]->pos += oldsize; | 
|         | 
    58  | 
|         | 
    59 			// The original mark becomes null so that the deconstructor | 
|         | 
    60 			// will not delete it prematurely. (should it delete any | 
|         | 
    61 			// marks in the first place since there is no such thing | 
|         | 
    62 			// as at temporary mark?) | 
|         | 
    63 			other->marks[u] = null; | 
|         | 
    64 		} | 
|         | 
    65  | 
|         | 
    66 		if (other->refs[u]) | 
|         | 
    67 		{ | 
|         | 
    68 			// Same for references | 
|         | 
    69 			// TODO: add a g_NextRef system like here, akin to marks! | 
|         | 
    70 			int r = AddMarkReference (other->refs[u]->num, false); | 
|         | 
    71 			refs[r]->pos = other->refs[u]->pos + oldsize; | 
|         | 
    72 		} | 
|         | 
    73 	} | 
|         | 
    74  | 
|         | 
    75 	delete other; | 
|         | 
    76 } | 
|         | 
    77  | 
|         | 
    78 // ============================================================================ | 
|         | 
    79 // | 
|         | 
    80 data_buffer* data_buffer::clone() | 
|         | 
    81 { | 
|         | 
    82 	data_buffer* other = new data_buffer; | 
|         | 
    83  | 
|         | 
    84 	for (int x = 0; x < writesize; x++) | 
|         | 
    85 		other->write (* (buffer + x)); | 
|         | 
    86  | 
|         | 
    87 	return other; | 
|         | 
    88 } | 
|         | 
    89  | 
|         | 
    90 // ============================================================================ | 
|         | 
    91 // | 
|         | 
    92 int data_buffer::add_mark (string name) | 
|         | 
    93 { | 
|         | 
    94 	// Find a free slot for the mark | 
|         | 
    95 	int u = g_NextMark++; | 
|         | 
    96  | 
|         | 
    97 	if (marks[u]) | 
|         | 
    98 		error ("DataBuffer: attempted to re-create mark %u!\n", u); | 
|         | 
    99  | 
|         | 
   100 	if (u >= MAX_MARKS) | 
|         | 
   101 		error ("mark quota exceeded, all labels, if-structs and loops add marks\n"); | 
|         | 
   102  | 
|         | 
   103 	ScriptMark* m = new ScriptMark; | 
|         | 
   104 	m->name = name; | 
|         | 
   105 	m->pos = writesize; | 
|         | 
   106 	marks[u] = m; | 
|         | 
   107 	return u; | 
|         | 
   108 } | 
|         | 
   109  | 
|         | 
   110 // ============================================================================ | 
|         | 
   111 // | 
|         | 
   112 int data_buffer::AddMarkReference (int marknum, bool placeholder) | 
|         | 
   113 { | 
|         | 
   114 	int u; | 
|         | 
   115  | 
|         | 
   116 	for (u = 0; u < MAX_MARKS; u++) | 
|         | 
   117 		if (!refs[u]) | 
|         | 
   118 			break; | 
|         | 
   119  | 
|         | 
   120 	if (u == MAX_MARKS) | 
|         | 
   121 		error ("mark reference quota exceeded, all goto-statements, if-structs and loops add refs\n"); | 
|         | 
   122  | 
|         | 
   123 	ScriptMarkReference* r = new ScriptMarkReference; | 
|         | 
   124 	r->num = marknum; | 
|         | 
   125 	r->pos = writesize; | 
|         | 
   126 	refs[u] = r; | 
|         | 
   127  | 
|         | 
   128 	// Write a dummy placeholder for the reference | 
|         | 
   129 	if (placeholder) | 
|         | 
   130 		write (1234); | 
|         | 
   131  | 
|         | 
   132 	return u; | 
|         | 
   133 } | 
|         | 
   134  | 
|         | 
   135 // ============================================================================ | 
|         | 
   136 // | 
|         | 
   137 void data_buffer::delete_mark (int marknum) | 
|         | 
   138 { | 
|         | 
   139 	if (!marks[marknum]) | 
|         | 
   140 		return; | 
|         | 
   141  | 
|         | 
   142 	// Delete the mark | 
|         | 
   143 	delete marks[marknum]; | 
|         | 
   144 	marks[marknum] = null; | 
|         | 
   145  | 
|         | 
   146 	// Delete its references | 
|         | 
   147 	for (int u = 0; u < MAX_MARKS; u++) | 
|         | 
   148 	{ | 
|         | 
   149 		if (refs[u]->num == marknum) | 
|         | 
   150 		{ | 
|         | 
   151 			delete refs[u]; | 
|         | 
   152 			refs[u] = null; | 
|         | 
   153 		} | 
|         | 
   154 	} | 
|         | 
   155 } | 
|         | 
   156  | 
|         | 
   157 // ============================================================================ | 
|         | 
   158 // | 
|         | 
   159 void data_buffer::move_mark (int i) | 
|         | 
   160 { | 
|         | 
   161 	if (!marks[i]) | 
|         | 
   162 		return; | 
|         | 
   163  | 
|         | 
   164 	marks[i]->pos = writesize; | 
|         | 
   165 } | 
|         | 
   166  | 
|         | 
   167 // ============================================================================ | 
|         | 
   168 // | 
|         | 
   169 void data_buffer::offset_mark (int mark, int offset) | 
|         | 
   170 { | 
|         | 
   171 	if (!marks[mark]) | 
|         | 
   172 		return; | 
|         | 
   173  | 
|         | 
   174 	marks[mark]->pos += offset; | 
|         | 
   175 } | 
|         | 
   176  | 
|         | 
   177 // ============================================================================ | 
|         | 
   178 // | 
|         | 
   179 int data_buffer::count_marks() | 
|         | 
   180 { | 
|         | 
   181 	int count = 0; | 
|         | 
   182  | 
|         | 
   183 	for (int u = 0; u < MAX_MARKS; u++) | 
|         | 
   184 		count += !!marks[u]; | 
|         | 
   185  | 
|         | 
   186 	return count; | 
|         | 
   187 } | 
|         | 
   188  | 
|         | 
   189 // ============================================================================ | 
|         | 
   190 // | 
|         | 
   191 int data_buffer::count_references() | 
|         | 
   192 { | 
|         | 
   193 	int count = 0; | 
|         | 
   194  | 
|         | 
   195 	for (int u = 0; u < MAX_MARKS; u++) | 
|         | 
   196 		count += !!refs[u]; | 
|         | 
   197  | 
|         | 
   198 	return count; | 
|         | 
   199 } | 
|         | 
   200  | 
|         | 
   201 // ============================================================================ | 
|         | 
   202 // | 
|         | 
   203 void data_buffer::write_float (string floatstring) | 
|         | 
   204 { | 
|         | 
   205 	// TODO: Casting float to word causes the decimal to be lost. | 
|         | 
   206 	// Find a way to store the number without such loss. | 
|         | 
   207 	float val = atof (floatstring); | 
|         | 
   208 	write (DH_PUSHNUMBER); | 
|         | 
   209 	write (static_cast<word> ((val > 0) ? val : -val)); | 
|         | 
   210  | 
|         | 
   211 	if (val < 0) | 
|         | 
   212 		write (DH_UNARYMINUS); | 
|         | 
   213 } | 
|         | 
   214  | 
|         | 
   215 // ============================================================================ | 
|         | 
   216 // | 
|         | 
   217 void data_buffer::write_string (string a) | 
|         | 
   218 { | 
|         | 
   219 	write (DH_PUSHSTRINGINDEX); | 
|         | 
   220 	write (get_string_table_index (a)); | 
|         | 
   221 } | 
|         | 
   222  | 
|         | 
   223 // ============================================================================ | 
|         | 
   224 // | 
|         | 
   225 void data_buffer::dump() | 
|         | 
   226 { | 
|         | 
   227 	for (int x = 0; x < writesize; x++) | 
|         | 
   228 		printf ("%d. [%d]\n", x, * (buffer + x)); | 
|         | 
   229 } | 
|         | 
   230  | 
|         | 
   231 // ============================================================================ | 
|         | 
   232 // | 
|         | 
   233 data_buffer::~data_buffer() | 
|         | 
   234 { | 
|         | 
   235 	delete buffer; | 
|         | 
   236  | 
|         | 
   237 	// Delete any marks and references | 
|         | 
   238 	for (int i = 0; i < MAX_MARKS; i++) | 
|         | 
   239 	{ | 
|         | 
   240 		delete marks[i]; | 
|         | 
   241 		delete refs[i]; | 
|         | 
   242 	} | 
|         | 
   243 } | 
|         | 
   244  | 
|         | 
   245 // ============================================================================ | 
|         | 
   246 // | 
|         | 
   247 data_buffer::data_buffer (int size) | 
|         | 
   248 { | 
|         | 
   249 	writesize = 0; | 
|         | 
   250  | 
|         | 
   251 	buffer = new unsigned char[size]; | 
|         | 
   252 	allocsize = size; | 
|         | 
   253  | 
|         | 
   254 	// Clear the marks table out | 
|         | 
   255 	for (int u = 0; u < MAX_MARKS; u++) | 
|         | 
   256 	{ | 
|         | 
   257 		marks[u] = null; | 
|         | 
   258 		refs[u] = null; | 
|         | 
   259 	} | 
|         | 
   260 } |