src/dataBuffer.cpp

changeset 119
bdf8d46c145f
child 125
85814c0918c5
equal deleted inserted replaced
118:e3361cf7cbf4 119:bdf8d46c145f
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 char[size]);
36 setPosition (&buffer()[0]);
37 setAllocatedSize (size);
38 }
39
40 // ============================================================================
41 //
42 DataBuffer::~DataBuffer()
43 {
44 assert (marks().isEmpty() && references().isEmpty());
45 delete buffer();
46 }
47
48 // ============================================================================
49 //
50 void DataBuffer::mergeAndDestroy (DataBuffer* other)
51 {
52 if (other == null)
53 return;
54
55 // Note: We transfer the marks before the buffer is copied, so that the
56 // offset uses the proper value (which is the written size of @other, which
57 // we don't want our written size to be added to yet).
58 other->transferMarksTo (this);
59 copyBuffer (other);
60 delete other;
61 }
62
63 // ============================================================================
64 //
65 // Clones this databuffer to a new one and returns it. Note that the original
66 // transfers its marks and references and loses them in the process.
67 //
68 DataBuffer* DataBuffer::clone()
69 {
70 DataBuffer* other = new DataBuffer;
71 transferMarksTo (other);
72 other->copyBuffer (this);
73 return other;
74 }
75
76 // ============================================================================
77 //
78 void DataBuffer::copyBuffer (const DataBuffer* buf)
79 {
80 checkSpace (buf->writtenSize());
81 memcpy (m_position, buf->buffer(), buf->writtenSize());
82 m_position += buf->writtenSize();
83 }
84
85 // ============================================================================
86 //
87 void DataBuffer::transferMarksTo (DataBuffer* dest)
88 {
89 int offset = dest->writtenSize();
90
91 for (ByteMark* mark : marks())
92 {
93 mark->pos += offset;
94 dest->m_marks << mark;
95 }
96
97 for (MarkReference* ref : references())
98 {
99 ref->pos += offset;
100 dest->m_references << ref;
101 }
102
103 m_marks.clear();
104 m_references.clear();
105 }
106
107 // ============================================================================
108 //
109 ByteMark* DataBuffer::addMark (const String& name)
110 {
111 ByteMark* mark = new ByteMark;
112 mark->name = name;
113 mark->pos = writtenSize();
114 m_marks << mark;
115 return mark;
116 }
117
118 // ============================================================================
119 //
120 MarkReference* DataBuffer::addReference (ByteMark* mark)
121 {
122 MarkReference* ref = new MarkReference;
123 ref->target = mark;
124 ref->pos = writtenSize();
125 m_references << ref;
126
127 // Write a dummy placeholder for the reference
128 writeDWord (0xBEEFCAFE);
129
130 return ref;
131 }
132
133 // ============================================================================
134 //
135 void DataBuffer::adjustMark (ByteMark* mark)
136 {
137 mark->pos = writtenSize();
138 }
139
140 // ============================================================================
141 //
142 void DataBuffer::offsetMark (ByteMark* mark, int position)
143 {
144 mark->pos += position;
145 }
146
147 // ============================================================================
148 //
149 void DataBuffer::writeStringIndex (const String& a)
150 {
151 writeDWord (DH_PushStringIndex);
152 writeDWord (getStringTableIndex (a));
153 }
154
155 // ============================================================================
156 //
157 void DataBuffer::dump()
158 {
159 for (int i = 0; i < writtenSize(); ++i)
160 printf ("%d. [0x%X]\n", i, buffer()[i]);
161 }
162
163 // ============================================================================
164 //
165 void DataBuffer::checkSpace (int bytes)
166 {
167 int writesize = writtenSize();
168
169 if (writesize + bytes < allocatedSize())
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[allocatedSize()];
176 memcpy (copy, buffer(), allocatedSize());
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 = allocatedSize() + bytes + 512;
182
183 delete buffer();
184 setBuffer (new char[newsize]);
185 setAllocatedSize (newsize);
186
187 // Now, copy the stuff back.
188 memcpy (m_buffer, copy, allocatedSize());
189 setPosition (buffer() + writesize);
190 delete copy;
191 }
192
193 // =============================================================================
194 //
195 void DataBuffer::writeByte (int8_t data)
196 {
197 checkSpace (1);
198 *m_position++ = 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 *m_position++ = (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 *m_position++ = (data >> (i * 8)) & 0xFF;
219 }
220
221 // =============================================================================
222 //
223 void DataBuffer::writeString (const String& a)
224 {
225 checkSpace (a.length() + 4);
226 writeDWord (a.length());
227
228 for (char c : a)
229 writeByte (c);
230 }
231
232
233 // =============================================================================
234 //
235 ByteMark* DataBuffer::findMarkByName (const String& name)
236 {
237 for (ByteMark* mark : marks())
238 if (mark->name == name)
239 return mark;
240
241 return null;
242 }

mercurial