34 #include "main.h" |
34 #include "main.h" |
35 #include "stringtable.h" |
35 #include "stringtable.h" |
36 |
36 |
37 #define MAX_MARKS 512 |
37 #define MAX_MARKS 512 |
38 |
38 |
39 extern int g_NextMark; |
|
40 |
|
41 // ============================================================================ |
39 // ============================================================================ |
42 // DataBuffer: A dynamic data buffer. |
40 // data_buffer: A dynamic data buffer. |
|
41 // |
|
42 // Notes: |
|
43 // |
|
44 // - A mark is a "pointer" to a particular position in the bytecode. The actual |
|
45 // permanent position cannot be predicted in any way or form, thus these things |
|
46 // are used to "mark" a position like that for future use. |
|
47 // |
|
48 // - A reference is another "mark" that references a mark. When the bytecode |
|
49 // is written to file, they are changed into their marks' current |
|
50 // positions. Marks themselves are never written to files, only refs are |
|
51 // |
43 class data_buffer |
52 class data_buffer |
44 { |
53 { |
45 public: |
54 PROPERTY (private, byte*, buffer, NO_OPS, STOCK_WRITE) |
46 // The actual buffer |
55 PROPERTY (private, int, allocated_size, NUM_OPS, STOCK_WRITE) |
47 byte* buffer; |
56 PROPERTY (private, byte*, writepos, NO_OPS, STOCK_WRITE) |
|
57 PROPERTY (private, list<byte_mark*>, marks, LIST_OPS, STOCK_WRITE) |
|
58 PROPERTY (private, list<mark_reference*>, refs, LIST_OPS, STOCK_WRITE) |
48 |
59 |
49 // Allocated size of the buffer |
60 public: |
50 int allocsize; |
61 data_buffer (int size = 128); |
|
62 ~data_buffer(); |
51 |
63 |
52 // Written size of the buffer |
64 // ==================================================================== |
53 int writesize; |
65 // Merge another data buffer into this one. |
|
66 // Note: @other is destroyed in the process! |
|
67 void merge_and_destroy (data_buffer* other); |
54 |
68 |
55 // Marks and references |
69 // Clones this databuffer to a new one and returns it. |
56 ScriptMark* marks[MAX_MARKS]; |
70 data_buffer* clone (); |
57 ScriptMarkReference* refs[MAX_MARKS]; |
|
58 |
71 |
59 data_buffer (int size = 128); |
72 byte_mark* add_mark (string name); |
60 ~data_buffer (); |
|
61 |
73 |
62 // ==================================================================== |
74 mark_reference* add_reference (byte_mark* mark, bool write_placeholder = true); |
63 // Write stuff to the buffer |
75 void check_space (int bytes); |
64 // TODO: un-template and remove the union, move to source file |
76 void delete_mark (int marknum); |
65 template<class T> void write (T stuff) |
77 void adjust_mark(byte_mark* mark); |
66 { |
78 void offset_mark (byte_mark* mark, int offset); |
67 if (writesize + sizeof (T) >= allocsize) |
79 byte_mark* find_mark_by_name (const string& target); |
|
80 void dump(); |
|
81 void write_float (float a); |
|
82 void write_string_index (const string& a); |
|
83 void write_string (const string& a); |
|
84 void write_byte (int8_t data); |
|
85 void write_word (int16_t data); |
|
86 void write_dword (int32_t data); |
|
87 void copy_buffer (const data_buffer* buf); |
|
88 |
|
89 inline int get_write_size() const |
68 { |
90 { |
69 // We don't have enough space in the buffer to write |
91 return m_writepos - get_buffer(); |
70 // the stuff - thus resize. First, store the old |
|
71 // buffer temporarily: |
|
72 char* copy = new char[allocsize]; |
|
73 memcpy (copy, buffer, allocsize); |
|
74 |
|
75 // Remake the buffer with the new size. Have enough space |
|
76 // for the stuff we're going to write, as well as a bit |
|
77 // of leeway so we don't have to resize immediately again. |
|
78 size_t newsize = allocsize + sizeof (T) + 128; |
|
79 |
|
80 delete buffer; |
|
81 buffer = new unsigned char[newsize]; |
|
82 allocsize = newsize; |
|
83 |
|
84 // Now, copy the stuff back. |
|
85 memcpy (buffer, copy, allocsize); |
|
86 delete copy; |
|
87 } |
92 } |
88 |
|
89 // Buffer is now guaranteed to have enough space. |
|
90 // Write the stuff one byte at a time. |
|
91 generic_union<T> uni; |
|
92 uni.as_t = stuff; |
|
93 |
|
94 for (int x = 0; x < sizeof (T); x++) |
|
95 { |
|
96 if (writesize >= allocsize) // should NEVER happen because resizing is done above |
|
97 error ("DataBuffer: written size exceeds allocated size!\n"); |
|
98 |
|
99 buffer[writesize] = uni.as_bytes[x]; |
|
100 writesize++; |
|
101 } |
|
102 } |
|
103 |
|
104 // ==================================================================== |
|
105 // Merge another data buffer into this one. |
|
106 void merge (data_buffer* other); |
|
107 |
|
108 // Clones this databuffer to a new one and returns it. |
|
109 data_buffer* clone (); |
|
110 |
|
111 // ==================================================================== |
|
112 // Adds a mark to the buffer. A mark is a "pointer" to a particular |
|
113 // position in the bytecode. The actual permanent position cannot |
|
114 // be predicted in any way or form, thus these things will be used |
|
115 // to "mark" a position like that for future use. |
|
116 int add_mark (string name); |
|
117 |
|
118 // ==================================================================== |
|
119 // A ref is another "mark" that references a mark. When the bytecode |
|
120 // is written to file, they are changed into their marks' current |
|
121 // positions. Marks themselves are never written to files, only refs are |
|
122 int add_reference (int marknum, bool placeholder = true); |
|
123 |
|
124 // Delete a mark and all references to it. |
|
125 void delete_mark (int marknum); |
|
126 |
|
127 // Adjusts a mark to the current position |
|
128 void move_mark(int i); |
|
129 |
|
130 void offset_mark (int mark, int offset); |
|
131 |
|
132 // Dump the buffer (for debugging purposes) |
|
133 void dump(); |
|
134 |
|
135 // Count the amount of marks |
|
136 int count_marks (); |
|
137 |
|
138 // Count the amount of refs |
|
139 int count_references (); |
|
140 |
|
141 // Write a float into the buffer |
|
142 void write_float (string floatstring); |
|
143 |
|
144 void write_string (string a); |
|
145 }; |
93 }; |
146 |
94 |
147 #endif // BOTC_DATABUFFER_H |
95 #endif // BOTC_DATABUFFER_H |