32 #include <stdio.h> |
32 #include <stdio.h> |
33 #include <string.h> |
33 #include <string.h> |
34 #include "Main.h" |
34 #include "Main.h" |
35 #include "StringTable.h" |
35 #include "StringTable.h" |
36 |
36 |
37 // ============================================================================ |
37 /** |
38 // data_buffer: A dynamic data buffer. |
38 * @class DataBuffer |
39 // |
39 * @brief Stores a buffer of bytecode |
40 // Notes: |
40 * |
41 // |
41 * The DataBuffer class stores a section of bytecode. Buffers are allocated on |
42 // - A mark is a "pointer" to a particular position in the bytecode. The actual |
42 * the heap and written to using the @c write* functions. Buffers can be cut and |
43 // permanent position cannot be predicted in any way or form, thus these things |
43 * pasted together with @c mergeAndDestroy, note that this function destroys the |
44 // are used to "mark" a position like that for future use. |
44 * parameter buffer in the process |
45 // |
45 * |
46 // - A reference is another "mark" that references a mark. When the bytecode |
46 * A mark is a "pointer" to a particular position in the bytecode. The actual |
47 // is written to file, they are changed into their marks' current |
47 * permanent position cannot be predicted in any way or form, thus these things |
48 // positions. Marks themselves are never written to files, only refs are |
48 * are used to "bookmark" a position like that for future use. |
49 // |
49 * |
|
50 * A reference acts as a pointer to a mark. The reference is four bytes in the |
|
51 * bytecode which will be replaced with its mark's position when the bytecode |
|
52 * is written to the output file. |
|
53 * |
|
54 * This mark/reference system is used to know bytecode offset values when |
|
55 * compiling, even though actual final positions cannot be known. |
|
56 */ |
50 class DataBuffer |
57 class DataBuffer |
51 { |
58 { |
52 PROPERTY (private, char*, Buffer, SetBuffer, STOCK_WRITE) |
59 //! @ |
53 PROPERTY (private, int, AllocatedSize, SetAllocatedSize, STOCK_WRITE) |
60 PROPERTY (private, char*, buffer, setBuffer, STOCK_WRITE) |
54 PROPERTY (private, char*, Position, SetPosition, STOCK_WRITE) |
61 PROPERTY (private, int, allocatedSize, setAllocatedSize, STOCK_WRITE) |
55 PROPERTY (private, List<ByteMark*>, Marks, SetMarks, STOCK_WRITE) |
62 PROPERTY (private, char*, position, setPosition, STOCK_WRITE) |
56 PROPERTY (private, List<MarkReference*>, References, SetReferences, STOCK_WRITE) |
63 PROPERTY (private, List<ByteMark*>, marks, setMarks, STOCK_WRITE) |
|
64 PROPERTY (private, List<MarkReference*>, references, setReferences, STOCK_WRITE) |
57 |
65 |
58 public: |
66 public: |
|
67 //! Constructs a new databuffer with @c size bytes. |
59 DataBuffer (int size = 128); |
68 DataBuffer (int size = 128); |
|
69 |
|
70 //! Destructs the databuffer. |
60 ~DataBuffer(); |
71 ~DataBuffer(); |
61 |
72 |
62 // ==================================================================== |
73 //! Adds a new mark to the current position with the name @c name. |
63 // Merge another data buffer into this one. |
74 //! @param name the name of the new mark |
64 // Note: @other is destroyed in the process! |
75 //! @return a pointer to the new mark |
65 void MergeAndDestroy (DataBuffer* other); |
76 ByteMark* addMark (const String& name); |
66 |
77 |
67 ByteMark* AddMark (String name); |
78 //! Adds a new reference to @c mark at the current position. This |
68 MarkReference* AddReference (ByteMark* mark); |
79 //! function will write 4 bytes to the buffer whose value will |
69 void CheckSpace (int bytes); |
80 //! be determined at final output writing. |
70 DataBuffer* Clone(); |
81 //! @param mark the mark which the new reference will attach to |
71 void DeleteMark (int marknum); |
82 //! @return a pointer to the new reference |
72 void AdjustMark (ByteMark* mark); |
83 MarkReference* addReference (ByteMark* mark); |
73 void OffsetMark (ByteMark* mark, int offset); |
|
74 ByteMark* FindMarkByName (const String& target); |
|
75 void Dump(); |
|
76 void TransferMarks (DataBuffer* other); |
|
77 void WriteStringIndex (const String& a); |
|
78 void WriteString (const String& a); |
|
79 void WriteByte (int8_t data); |
|
80 void WriteWord (int16_t data); |
|
81 void WriteDWord (int32_t data); |
|
82 void CopyBuffer (const DataBuffer* buf); |
|
83 |
84 |
84 inline int WrittenSize() const |
85 //! Moves @c mark to the current bytecode position. |
|
86 //! @param mark the mark to adjust |
|
87 void adjustMark (ByteMark* mark); |
|
88 |
|
89 //! Ensures there's at least @c bytes left in the buffer. Will resize |
|
90 //! if necessary, no-op if not. On resize, 512 extra bytes are allocated |
|
91 //! to reduce the amount of resizes. |
|
92 //! @param bytes the amount of space in bytes to ensure allocated |
|
93 void checkSpace (int bytes); |
|
94 |
|
95 //! Creates a clone of this data buffer. |
|
96 //! @note All marks will be moved into the new databuffer as marks are |
|
97 //! @note never duplicated. |
|
98 //! @return The newly cloned databuffer. |
|
99 DataBuffer* clone(); |
|
100 |
|
101 //! Prints the buffer to stdout. Useful for debugging. |
|
102 void dump(); |
|
103 |
|
104 //! Finds the given mark by name. |
|
105 //! @param name the name of the mark to find |
|
106 ByteMark* findMarkByName (const String& name); |
|
107 |
|
108 //! Merge another data buffer into this one. |
|
109 //! Note: @c other is destroyed in the process. |
|
110 //! @param other the buffer to merge in |
|
111 void mergeAndDestroy (DataBuffer* other); |
|
112 |
|
113 //! Moves @c mark to the given bytecode position. |
|
114 //! @param mark the mark to adjust |
|
115 //! @param position where to adjust the mark |
|
116 void offsetMark (ByteMark* mark, int position); |
|
117 |
|
118 //! Transfers all marks of this buffer to @c other. |
|
119 //! @param other the data buffer to transfer marks to |
|
120 void transferMarksTo (DataBuffer* other); |
|
121 |
|
122 //! Writes the index of the given string to the databuffer. |
|
123 //! 4 bytes will be written to the bytecode. |
|
124 //! @param a the string whose index to write |
|
125 void writeStringIndex (const String& a); |
|
126 |
|
127 //! Writes the given string as-is into the databuffer. |
|
128 //! @c a.length + 4 bytes will be written to the buffer. |
|
129 //! @param a the string to write |
|
130 void writeString (const String& a); |
|
131 |
|
132 //! Writes the given byte to the buffer. 1 byte will be written. |
|
133 //! @c data the byte to write |
|
134 void writeByte (int8_t data); |
|
135 |
|
136 //! Writes the given word to the buffer. 2 byte will be written. |
|
137 //! @c data the word to write |
|
138 void writeWord (int16_t data); |
|
139 |
|
140 //! Writes the given double word to the buffer. 4 bytes will be written. |
|
141 //! @c data the double word to write |
|
142 void writeDWord (int32_t data); |
|
143 |
|
144 //! @return the amount of bytes written to this buffer. |
|
145 inline int writtenSize() const |
85 { |
146 { |
86 return Position() - Buffer(); |
147 return position() - buffer(); |
87 } |
148 } |
|
149 |
|
150 protected: |
|
151 //! Writes the buffer's contents from @c buf. |
|
152 //! @c buf.writtenSize() bytes will be written. |
|
153 //! @param buf the buffer to copy |
|
154 void copyBuffer (const DataBuffer* buf); |
88 }; |
155 }; |
89 |
156 |
90 #endif // BOTC_DATABUFFER_H |
157 #endif // BOTC_DATABUFFER_H |