src/DataBuffer.cc

changeset 88
5def6ff8b466
child 90
90ab2f2b3dc0
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 "DataBuffer.h"
30
31 // ============================================================================
32 //
33 DataBuffer::DataBuffer (int size)
34 {
35 SetBuffer (new byte[size]);
36 SetPosition (&GetBuffer()[0]);
37 SetAllocatedSize (size);
38 }
39
40 // ============================================================================
41 //
42 DataBuffer::~DataBuffer()
43 {
44 assert (CountMarks() == 0 && CountReferences() == 0);
45 delete GetBuffer();
46 }
47
48 // ============================================================================
49 //
50 void DataBuffer::MergeAndDestroy (DataBuffer* other)
51 {
52 if (!other)
53 return;
54
55 int oldsize = GetWrittenSize();
56 CopyBuffer (other);
57
58 // Assimilate in its marks and references
59 for (ByteMark* mark : other->GetMarks())
60 {
61 mark->pos += oldsize;
62 PushToMarks (mark);
63 }
64
65 for (MarkReference* ref : other->GetReferences())
66 {
67 ref->pos += oldsize;
68 PushToReferences (ref);
69 }
70
71 ClearMarks();
72 ClearReferences();
73 delete other;
74 }
75
76 // ============================================================================
77 //
78 DataBuffer* DataBuffer::Clone()
79 {
80 DataBuffer* other = new DataBuffer;
81 other->CopyBuffer (this);
82 return other;
83 }
84
85 // ============================================================================
86 //
87 void DataBuffer::CopyBuffer (const DataBuffer* buf)
88 {
89 CheckSpace (buf->GetWrittenSize());
90 memcpy (mPosition, buf->GetBuffer(), buf->GetWrittenSize());
91 mPosition += buf->GetWrittenSize();
92 }
93
94 // ============================================================================
95 //
96 ByteMark* DataBuffer::AddMark (String name)
97 {
98 ByteMark* mark = new ByteMark;
99 mark->name = name;
100 mark->pos = GetWrittenSize();
101 PushToMarks (mark);
102 return mark;
103 }
104
105 // ============================================================================
106 //
107 MarkReference* DataBuffer::AddReference (ByteMark* mark, bool writePlaceholder)
108 {
109 MarkReference* ref = new MarkReference;
110 ref->target = mark;
111 ref->pos = GetWrittenSize();
112 PushToReferences (ref);
113
114 // Write a dummy placeholder for the reference
115 if (writePlaceholder)
116 WriteDWord (0xBEEFCAFE);
117
118 return ref;
119 }
120
121 // ============================================================================
122 //
123 void DataBuffer::AdjustMark (ByteMark* mark)
124 {
125 mark->pos = GetWrittenSize();
126 }
127
128 // ============================================================================
129 //
130 void DataBuffer::OffsetMark (ByteMark* mark, int offset)
131 {
132 mark->pos += offset;
133 }
134
135 // ============================================================================
136 //
137 void DataBuffer::WriteFloat (float a)
138 {
139 // TODO: Find a way to store the number without decimal loss.
140 WriteDWord (dhPushNumber);
141 WriteDWord (abs (a));
142
143 if (a < 0)
144 WriteDWord (dhUnaryMinus);
145 }
146
147 // ============================================================================
148 //
149 void DataBuffer::WriteStringIndex (const String& a)
150 {
151 WriteDWord (dhPushStringIndex);
152 WriteDWord (GetStringTableIndex (a));
153 }
154
155 // ============================================================================
156 //
157 void DataBuffer::Dump()
158 {
159 for (int i = 0; i < GetWrittenSize(); ++i)
160 printf ("%d. [0x%X]\n", i, GetBuffer()[i]);
161 }
162
163 // ============================================================================
164 //
165 void DataBuffer::CheckSpace (int bytes)
166 {
167 int writesize = GetWrittenSize();
168
169 if (writesize + bytes < GetAllocatedSize())
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[GetAllocatedSize()];
176 memcpy (copy, GetBuffer(), GetAllocatedSize());
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 int newsize = GetAllocatedSize() + bytes + 512;
182
183 delete GetBuffer();
184 SetBuffer (new byte[newsize]);
185 SetAllocatedSize (newsize);
186
187 // Now, copy the stuff back.
188 memcpy (mBuffer, copy, GetAllocatedSize());
189 SetPosition (GetBuffer() + writesize);
190 delete copy;
191 }
192
193 // =============================================================================
194 //
195 void DataBuffer::WriteByte (int8_t data)
196 {
197 CheckSpace (1);
198 *mPosition++ = data;
199 }
200
201 // =============================================================================
202 //
203 void DataBuffer::WriteWord (int16_t data)
204 {
205 CheckSpace (2);
206
207 for (int i = 0; i < 2; ++i)
208 *mPosition++ = (data >> (i * 8)) & 0xFF;
209 }
210
211 // =============================================================================
212 //
213 void DataBuffer::WriteDWord (int32_t data)
214 {
215 CheckSpace (4);
216
217 for (int i = 0; i < 4; ++i)
218 *mPosition++ = (data >> (i * 8)) & 0xFF;
219 }
220
221 // =============================================================================
222 //
223 void DataBuffer::WriteString (const String& a)
224 {
225 CheckSpace (a.Length() + 1);
226
227 for (char c : a)
228 WriteByte (c);
229
230 WriteByte ('\0');
231 }
232
233
234 // =============================================================================
235 //
236 ByteMark* DataBuffer::FindMarkByName (const String& target)
237 {
238 for (ByteMark* mark : GetMarks())
239 if (mark->name == target)
240 return mark;
241
242 return null;
243 }

mercurial