databuffer.h

changeset 37
c349dca807f9
parent 36
a8838b5f1213
child 38
e4bbd540663b
equal deleted inserted replaced
36:a8838b5f1213 37:c349dca807f9
42 #define __DATABUFFER_H__ 42 #define __DATABUFFER_H__
43 #include <stdio.h> 43 #include <stdio.h>
44 #include <string.h> 44 #include <string.h>
45 #include "common.h" 45 #include "common.h"
46 46
47 #define MAX_MARKS 256
48
47 // ============================================================================ 49 // ============================================================================
48 // DataBuffer: A dynamic data buffer. 50 // DataBuffer: A dynamic data buffer.
49 class DataBuffer { 51 class DataBuffer {
50 public: 52 public:
51 // The actual buffer 53 // The actual buffer
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__

mercurial