src/data_buffer.cc

changeset 88
5def6ff8b466
parent 87
8f65914e7046
child 89
029a330a9bef
equal deleted inserted replaced
87:8f65914e7046 88:5def6ff8b466
1 /*
2 Copyright 2012-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
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. 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 3. The name of the author may not be used to endorse or promote products
15 derived from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "data_buffer.h"
30
31 // ============================================================================
32 //
33 data_buffer::data_buffer (int size)
34 {
35 set_writepos (get_buffer());
36 set_buffer (new byte[size]);
37 set_allocated_size (size);
38 }
39
40 // ============================================================================
41 //
42 data_buffer::~data_buffer()
43 {
44 assert (count_marks() == 0 && count_refs() == 0);
45 delete get_buffer();
46 }
47
48 // ============================================================================
49 //
50 void data_buffer::merge_and_destroy (data_buffer* other)
51 {
52 if (!other)
53 return;
54
55 int oldsize = get_write_size();
56 copy_buffer (other);
57
58 // Assimilate in its marks and references
59 for (byte_mark* mark : other->get_marks())
60 {
61 mark->pos += oldsize;
62 push_to_marks (mark);
63 }
64
65 for (mark_reference* ref : other->get_refs())
66 {
67 ref->pos += oldsize;
68 push_to_refs (ref);
69 }
70
71 clear_marks();
72 clear_refs();
73 delete other;
74 }
75
76 // ============================================================================
77 //
78 data_buffer* data_buffer::clone()
79 {
80 data_buffer* other = new data_buffer;
81 other->copy_buffer (this);
82 return other;
83 }
84
85 // ============================================================================
86 //
87 void data_buffer::copy_buffer (const data_buffer* buf)
88 {
89 check_space (buf->get_write_size());
90 memcpy (m_writepos, buf->get_buffer(), buf->get_write_size());
91 m_writepos += buf->get_write_size();
92 }
93
94 // ============================================================================
95 //
96 byte_mark* data_buffer::add_mark (string name)
97 {
98 byte_mark* mark = new byte_mark;
99 mark->name = name;
100 mark->pos = get_write_size();
101 push_to_marks (mark);
102 return mark;
103 }
104
105 // ============================================================================
106 //
107 mark_reference* data_buffer::add_reference (byte_mark* mark, bool write_placeholder)
108 {
109 mark_reference* ref = new mark_reference;
110 ref->target = mark;
111 ref->pos = get_write_size();
112 push_to_refs (ref);
113
114 // Write a dummy placeholder for the reference
115 if (write_placeholder)
116 write_dword (0xBEEFCAFE);
117
118 return ref;
119 }
120
121 // ============================================================================
122 //
123 void data_buffer::adjust_mark (byte_mark* mark)
124 {
125 mark->pos = get_write_size();
126 }
127
128 // ============================================================================
129 //
130 void data_buffer::offset_mark (byte_mark* mark, int offset)
131 {
132 mark->pos += offset;
133 }
134
135 // ============================================================================
136 //
137 void data_buffer::write_float (float a)
138 {
139 // TODO: Find a way to store the number without decimal loss.
140 write_dword (dh_push_number);
141 write_dword (abs (a));
142
143 if (a < 0)
144 write_dword (dh_unary_minus);
145 }
146
147 // ============================================================================
148 //
149 void data_buffer::write_string_index (const string& a)
150 {
151 write_dword (dh_push_string_index);
152 write_dword (get_string_table_index (a));
153 }
154
155 // ============================================================================
156 //
157 void data_buffer::dump()
158 {
159 for (int i = 0; i < get_write_size(); ++i)
160 printf ("%d. [%d]\n", i, get_buffer()[i]);
161 }
162
163 // ============================================================================
164 //
165 void data_buffer::check_space (int bytes)
166 {
167 int writesize = get_write_size();
168
169 if (writesize + bytes < get_allocated_size())
170 return;
171
172 // We don't have enough space in the buffer to write
173 // the stuff - thus resize. First, store the old
174 // buffer temporarily:
175 char* copy = new char[get_allocated_size()];
176 memcpy (copy, get_buffer(), get_allocated_size());
177
178 // Remake the buffer with the new size. Have enough space
179 // for the stuff we're going to write, as well as a bit
180 // of leeway so we don't have to resize immediately again.
181 size_t newsize = get_allocated_size() + bytes + 512;
182
183 delete get_buffer();
184 set_buffer (new byte[newsize]);
185 set_allocated_size (newsize);
186
187 // Now, copy the stuff back.
188 memcpy (m_buffer, copy, get_allocated_size());
189 set_writepos (get_buffer() + writesize);
190 delete copy;
191 }
192
193 // =============================================================================
194 //
195 void data_buffer::write_byte (int8_t data)
196 {
197 check_space (1);
198 *m_writepos++ = data;
199 }
200
201 // =============================================================================
202 //
203 void data_buffer::write_word (int16_t data)
204 {
205 check_space (2);
206
207 for (int i = 0; i < 2; ++i)
208 *m_writepos++ = (data >> (i * 8)) & 0xFF;
209 }
210
211 // =============================================================================
212 //
213 void data_buffer::write_dword (int32_t data)
214 {
215 check_space (4);
216
217 for (int i = 0; i < 4; ++i)
218 *m_writepos++ = (data >> (i * 8)) & 0xFF;
219 }
220
221 // =============================================================================
222 //
223 void data_buffer::write_string (const string& a)
224 {
225 check_space (a.length() + 1);
226
227 for (char c : a)
228 write_byte (c);
229
230 write_byte ('\0');
231 }
232
233
234 // =============================================================================
235 //
236 byte_mark* data_buffer::find_mark_by_name (const string& target)
237 {
238 for (byte_mark* mark : get_marks())
239 if (mark->name == target)
240 return mark;
241
242 return null;
243 }

mercurial