55 unsigned int allocsize; |
57 unsigned int allocsize; |
56 |
58 |
57 // Written size of the buffer |
59 // Written size of the buffer |
58 unsigned int writesize; |
60 unsigned int writesize; |
59 |
61 |
|
62 // Marks and references |
|
63 ScriptMark* marks[MAX_MARKS]; |
|
64 ScriptMarkReference* refs[MAX_MARKS]; |
|
65 |
|
66 // ==================================================================== |
60 // METHODS |
67 // METHODS |
|
68 |
|
69 // ==================================================================== |
|
70 // Constructor |
61 DataBuffer (unsigned int size=128) { |
71 DataBuffer (unsigned int size=128) { |
62 writesize = 0; |
72 writesize = 0; |
63 |
73 |
64 buffer = new unsigned char[size]; |
74 buffer = new unsigned char[size]; |
65 allocsize = size; |
75 allocsize = size; |
66 } |
76 |
67 |
77 // Clear the marks table out |
|
78 for (unsigned int u = 0; u < MAX_MARKS; u++) { |
|
79 marks[u] = NULL; |
|
80 refs[u] = NULL; |
|
81 } |
|
82 } |
|
83 |
|
84 // ==================================================================== |
68 ~DataBuffer () { |
85 ~DataBuffer () { |
69 delete buffer; |
86 delete buffer; |
70 } |
87 |
71 |
88 // Delete any marks and references |
|
89 for (unsigned int u = 0; u < MAX_MARKS; u++) { |
|
90 if (marks[u]) |
|
91 delete marks[u]; |
|
92 |
|
93 if (refs[u]) |
|
94 delete refs[u]; |
|
95 } |
|
96 } |
|
97 |
|
98 // ==================================================================== |
|
99 // Write stuff to the buffer |
72 template<class T> void Write(T stuff) { |
100 template<class T> void Write(T stuff) { |
73 if (sizeof (char) != 1) { |
101 if (sizeof (char) != 1) { |
74 error ("DataBuffer: sizeof(char) must be 1!\n"); |
102 error ("DataBuffer: sizeof(char) must be 1!\n"); |
75 } |
103 } |
76 |
104 |
97 |
125 |
98 // Write the new stuff one byte at a time |
126 // Write the new stuff one byte at a time |
99 for (unsigned int x = 0; x < sizeof (T); x++) { |
127 for (unsigned int x = 0; x < sizeof (T); x++) { |
100 if (writesize >= allocsize) |
128 if (writesize >= allocsize) |
101 error ("DataBuffer: written size exceeds allocated size!\n"); |
129 error ("DataBuffer: written size exceeds allocated size!\n"); |
102 buffer[writesize] = CharByte<T> (stuff, x); |
130 buffer[writesize] = GetByteIndex<T> (stuff, x); |
103 writesize++; |
131 writesize++; |
104 } |
132 } |
105 } |
133 } |
106 |
134 |
|
135 // ==================================================================== |
107 // Merge another data buffer into this one. |
136 // Merge another data buffer into this one. |
108 void Merge (DataBuffer* other) { |
137 void Merge (DataBuffer* other) { |
109 if (!other) |
138 if (!other) |
110 return; |
139 return; |
111 |
140 |
112 for (unsigned int x = 0; x < other->writesize; x++) { |
141 for (unsigned int x = 0; x < other->writesize; x++) { |
113 unsigned char c = *(other->buffer+x); |
142 unsigned char c = *(other->buffer+x); |
114 Write<unsigned char> (c); |
143 Write<unsigned char> (c); |
115 } |
144 } |
116 |
145 |
|
146 // Merge its marks and references |
|
147 unsigned int u = 0; |
|
148 for (u = 0; u < MAX_MARKS; u++) { |
|
149 if (other->marks[u]) { |
|
150 // Add the mark and offset its position. |
|
151 unsigned int u = AddMark (other->marks[u]->type, other->marks[u]->name); |
|
152 marks[u]->pos += other->writesize; |
|
153 } |
|
154 |
|
155 if (other->refs[u]) { |
|
156 // Same for references |
|
157 unsigned int r = AddMarkReference (other->refs[u]->num); |
|
158 refs[r]->pos += other->writesize; |
|
159 } |
|
160 } |
|
161 |
117 delete other; |
162 delete other; |
118 } |
163 } |
119 |
164 |
120 private: |
165 // ==================================================================== |
121 template <class T> unsigned char CharByte (T a, unsigned int b) { |
166 // Adds a mark to the buffer. A mark is a reference to a particular |
122 if (b >= sizeof (T)) |
167 // position in the bytecode. The actual permanent position cannot |
123 error ("CharByte: tried to get byte %u out of a %u-byte %s\n", |
168 // be predicted in any way or form, thus these things will be used |
124 b, sizeof (T), typeid (T).name()); |
169 // to "mark" a position like that for future use. |
125 |
170 unsigned int AddMark (int type, str name) { |
126 unsigned long p1 = pow<unsigned long> (256, b); |
171 // Find a free slot for the mark |
127 unsigned long p2 = pow<unsigned long> (256, b+1); |
172 unsigned int u; |
128 unsigned long r = (a % p2) / p1; |
173 for (u = 0; u < MAX_MARKS; u++) |
129 |
174 if (!marks[u]) |
130 if (r > 256) |
175 break; |
131 error ("DataBuffer::CharByte: result %lu too big!", r); |
176 |
132 |
177 if (u >= MAX_MARKS) |
133 unsigned char ur = static_cast<unsigned char> (r); |
178 error ("mark quota exceeded, all labels, if-structs and loops add marks\n"); |
134 return ur; |
179 |
|
180 ScriptMark* m = new ScriptMark; |
|
181 m->name = name; |
|
182 m->type = type; |
|
183 m->pos = writesize; |
|
184 marks[u] = m; |
|
185 return u; |
|
186 } |
|
187 |
|
188 unsigned int AddMarkReference (unsigned int marknum) { |
|
189 unsigned int u; |
|
190 for (u = 0; u < MAX_MARKS; u++) |
|
191 if (!refs[u]) |
|
192 break; |
|
193 |
|
194 if (u == MAX_MARKS) |
|
195 error ("mark reference quota exceeded, all goto-statements, if-structs and loops add refs\n"); |
|
196 |
|
197 // NOTE: Do not check if the mark actually exists here since a |
|
198 // reference may come in the code earlier than the actual mark |
|
199 // and the new mark number can be predicted. |
|
200 ScriptMarkReference* r = new ScriptMarkReference; |
|
201 r->num = marknum; |
|
202 r->pos = writesize; |
|
203 refs[u] = r; |
|
204 |
|
205 return u; |
|
206 } |
|
207 |
|
208 // Delete a mark and all references to it. |
|
209 void DeleteMark (unsigned int marknum) { |
|
210 if (!marks[marknum]) |
|
211 return; |
|
212 |
|
213 // Delete the mark |
|
214 delete marks[marknum]; |
|
215 marks[marknum] = NULL; |
|
216 |
|
217 // Delete its references |
|
218 for (unsigned int u = 0; u < MAX_MARKS; u++) { |
|
219 if (refs[u]->num == marknum) { |
|
220 delete refs[u]; |
|
221 refs[u] = NULL; |
|
222 } |
|
223 } |
135 } |
224 } |
136 }; |
225 }; |
137 |
226 |
138 #endif // __DATABUFFER_H__ |
227 #endif // __DATABUFFER_H__ |