databuffer.h

changeset 42
5cd91fd1526c
parent 41
47e686c96d8f
child 43
1b35c9985989
equal deleted inserted replaced
41:47e686c96d8f 42:5cd91fd1526c
95 } 95 }
96 } 96 }
97 97
98 // ==================================================================== 98 // ====================================================================
99 // Write stuff to the buffer 99 // Write stuff to the buffer
100 template<class T> void Write(T stuff) { 100 template<class T> void Write (T stuff) {
101 if (sizeof (char) != 1) { 101 if (writesize + sizeof (T) >= allocsize) {
102 error ("DataBuffer: sizeof(char) must be 1!\n"); 102 // We don't have enough space in the buffer to write
103 } 103 // the stuff - thus resize. First, store the old
104 104 // buffer temporarily:
105 // Out of space, must resize
106 if (writesize + sizeof(T) >= allocsize) {
107 // First, store the old buffer temporarily
108 char* copy = new char[allocsize]; 105 char* copy = new char[allocsize];
109 memcpy (copy, buffer, allocsize); 106 memcpy (copy, buffer, allocsize);
110 107
111 // Remake the buffer with the new size. 108 // Remake the buffer with the new size. Have enough space
112 // Have a bit of leeway so we don't have to 109 // for the stuff we're going to write, as well as a bit
113 // resize immediately again. 110 // of leeway so we don't have to resize immediately again.
114 size_t newsize = allocsize + sizeof (T) + 128; 111 size_t newsize = allocsize + sizeof (T) + 128;
115 delete buffer; 112 delete buffer;
116 buffer = new unsigned char[newsize]; 113 buffer = new unsigned char[newsize];
117 allocsize = newsize; 114 allocsize = newsize;
118 115
119 // Now, copy the new stuff over. 116 // Now, copy the stuff back.
120 memcpy (buffer, copy, allocsize); 117 memcpy (buffer, copy, allocsize);
121
122 // Nuke the copy now as it's no longer needed
123 delete copy; 118 delete copy;
124 } 119 }
125 120
126 // Write the new stuff one byte at a time 121 // Buffer is now guaranteed to have enough space.
122 // Write the stuff one byte at a time.
123 union_t<T> uni;
124 uni.val = stuff;
127 for (unsigned int x = 0; x < sizeof (T); x++) { 125 for (unsigned int x = 0; x < sizeof (T); x++) {
128 if (writesize >= allocsize) 126 if (writesize >= allocsize) // should NEVER happen because resizing is done above
129 error ("DataBuffer: written size exceeds allocated size!\n"); 127 error ("DataBuffer: written size exceeds allocated size!\n");
130 buffer[writesize] = GetByteIndex<T> (stuff, x); 128
129 buffer[writesize] = uni.b[x];
131 writesize++; 130 writesize++;
132 } 131 }
133 } 132 }
134 133
135 // ==================================================================== 134 // ====================================================================
167 other->Write<unsigned char> (*(buffer+x)); 166 other->Write<unsigned char> (*(buffer+x));
168 return other; 167 return other;
169 } 168 }
170 169
171 // ==================================================================== 170 // ====================================================================
172 // Adds a mark to the buffer. A mark is a reference to a particular 171 // Adds a mark to the buffer. A mark is a "pointer" to a particular
173 // position in the bytecode. The actual permanent position cannot 172 // position in the bytecode. The actual permanent position cannot
174 // be predicted in any way or form, thus these things will be used 173 // be predicted in any way or form, thus these things will be used
175 // to "mark" a position like that for future use. 174 // to "mark" a position like that for future use.
176 unsigned int AddMark (int type, str name) { 175 unsigned int AddMark (int type, str name) {
177 // Find a free slot for the mark 176 // Find a free slot for the mark
186 ScriptMark* m = new ScriptMark; 185 ScriptMark* m = new ScriptMark;
187 m->name = name; 186 m->name = name;
188 m->type = type; 187 m->type = type;
189 m->pos = writesize; 188 m->pos = writesize;
190 marks[u] = m; 189 marks[u] = m;
191 printf ("add mark %u at %d\n", u, m->pos);
192 return u; 190 return u;
193 } 191 }
194 192
193 // ====================================================================
194 // A ref is another "mark" that references a mark. When the bytecode
195 // is written to file, they are changed into their marks' current
196 // positions. Marks themselves are never written to files, only refs are
195 unsigned int AddMarkReference (unsigned int marknum) { 197 unsigned int AddMarkReference (unsigned int marknum) {
196 unsigned int u; 198 unsigned int u;
197 for (u = 0; u < MAX_MARKS; u++) 199 for (u = 0; u < MAX_MARKS; u++)
198 if (!refs[u]) 200 if (!refs[u])
199 break; 201 break;
202 error ("mark reference quota exceeded, all goto-statements, if-structs and loops add refs\n"); 204 error ("mark reference quota exceeded, all goto-statements, if-structs and loops add refs\n");
203 205
204 // NOTE: Do not check if the mark actually exists here since a 206 // NOTE: Do not check if the mark actually exists here since a
205 // reference may come in the code earlier than the actual mark 207 // reference may come in the code earlier than the actual mark
206 // and the new mark number can be predicted. 208 // and the new mark number can be predicted.
209 // 11/8/12: eh? The mark is always created first.
207 ScriptMarkReference* r = new ScriptMarkReference; 210 ScriptMarkReference* r = new ScriptMarkReference;
208 r->num = marknum; 211 r->num = marknum;
209 r->pos = writesize; 212 r->pos = writesize;
210 refs[u] = r; 213 refs[u] = r;
214
215 // Write a dummy placeholder for the reference
216 Write<word> (1234);
211 217
212 return u; 218 return u;
213 } 219 }
214 220
215 // Delete a mark and all references to it. 221 // Delete a mark and all references to it.
229 } 235 }
230 } 236 }
231 } 237 }
232 238
233 // Adjusts a mark to the current position 239 // Adjusts a mark to the current position
234 void MoveMark (unsigned int mark) { 240 void MoveMark (unsigned int mark, int offset = -1) {
235 if (!marks[mark]) 241 if (!marks[mark])
236 return; 242 return;
237 printf ("move mark %u from %d to %d\n", mark, marks[mark]->pos, writesize);
238 marks[mark]->pos = writesize; 243 marks[mark]->pos = writesize;
239 } 244 }
240 245
241 // Adjusts a mark to the current position
242 void OffsetMark (unsigned int mark, size_t offset) { 246 void OffsetMark (unsigned int mark, size_t offset) {
243 if (!marks[mark]) 247 if (!marks[mark])
244 return; 248 return;
245 printf ("move mark %u from %d to %d\n", mark, marks[mark]->pos, marks[mark]->pos+offset);
246 marks[mark]->pos += offset; 249 marks[mark]->pos += offset;
247 } 250 }
248 251
249 // Dump the buffer (for debugging purposes) 252 // Dump the buffer (for debugging purposes)
250 void Dump() { 253 void Dump() {

mercurial