src/data_buffer.h

changeset 86
43fe4be38a58
parent 85
264a61e9eba0
equal deleted inserted replaced
85:264a61e9eba0 86:43fe4be38a58
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

mercurial