/src/zydis/src/FormatterBuffer.c
Line | Count | Source |
1 | | /*************************************************************************************************** |
2 | | |
3 | | Zyan Disassembler Library (Zydis) |
4 | | |
5 | | Original Author : Florian Bernd |
6 | | |
7 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
8 | | * of this software and associated documentation files (the "Software"), to deal |
9 | | * in the Software without restriction, including without limitation the rights |
10 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
11 | | * copies of the Software, and to permit persons to whom the Software is |
12 | | * furnished to do so, subject to the following conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be included in all |
15 | | * copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
20 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
22 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | | * SOFTWARE. |
24 | | |
25 | | ***************************************************************************************************/ |
26 | | |
27 | | #include <Zydis/Internal/String.h> |
28 | | #include <Zydis/FormatterBuffer.h> |
29 | | |
30 | | /* ============================================================================================== */ |
31 | | /* Exported functions */ |
32 | | /* ============================================================================================== */ |
33 | | |
34 | | /* ---------------------------------------------------------------------------------------------- */ |
35 | | /* Token */ |
36 | | /* ---------------------------------------------------------------------------------------------- */ |
37 | | |
38 | | ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token, |
39 | | ZydisTokenType* type, ZyanConstCharPointer* value) |
40 | 13.9k | { |
41 | 13.9k | if (!token || !type || !value) |
42 | 0 | { |
43 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
44 | 0 | } |
45 | | |
46 | 13.9k | *type = token->type; |
47 | 13.9k | *value = (ZyanConstCharPointer)((ZyanU8*)token + sizeof(ZydisFormatterToken)); |
48 | | |
49 | 13.9k | return ZYAN_STATUS_SUCCESS; |
50 | 13.9k | } |
51 | | |
52 | | ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token) |
53 | 13.9k | { |
54 | 13.9k | if (!token || !*token) |
55 | 0 | { |
56 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
57 | 0 | } |
58 | | |
59 | 13.9k | const ZyanU8 next = (*token)->next; |
60 | 13.9k | if (!next) |
61 | 1.72k | { |
62 | 1.72k | return ZYAN_STATUS_OUT_OF_RANGE; |
63 | 1.72k | } |
64 | 12.2k | *token = (ZydisFormatterTokenConst*)((ZyanU8*)*token + sizeof(ZydisFormatterToken) + next); |
65 | | |
66 | 12.2k | return ZYAN_STATUS_SUCCESS; |
67 | 13.9k | } |
68 | | |
69 | | /* ---------------------------------------------------------------------------------------------- */ |
70 | | /* Buffer */ |
71 | | /* ---------------------------------------------------------------------------------------------- */ |
72 | | |
73 | | ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer, |
74 | | ZydisFormatterTokenConst** token) |
75 | 0 | { |
76 | 0 | if (!buffer || !token) |
77 | 0 | { |
78 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
79 | 0 | } |
80 | | |
81 | 0 | if (!buffer->is_token_list) |
82 | 0 | { |
83 | 0 | return ZYAN_STATUS_INVALID_OPERATION; |
84 | 0 | } |
85 | | |
86 | 0 | *token = ((ZydisFormatterTokenConst*)buffer->string.vector.data - 1); |
87 | 0 | if ((*token)->type == ZYDIS_TOKEN_INVALID) |
88 | 0 | { |
89 | 0 | return ZYAN_STATUS_INVALID_OPERATION; |
90 | 0 | } |
91 | | |
92 | 0 | return ZYAN_STATUS_SUCCESS; |
93 | 0 | } |
94 | | |
95 | | ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, ZyanString** string) |
96 | 0 | { |
97 | 0 | if (!buffer || !string) |
98 | 0 | { |
99 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
100 | 0 | } |
101 | | |
102 | 0 | if (buffer->is_token_list && |
103 | 0 | ((ZydisFormatterTokenConst*)buffer->string.vector.data - 1)->type == ZYDIS_TOKEN_INVALID) |
104 | 0 | { |
105 | 0 | return ZYAN_STATUS_INVALID_OPERATION; |
106 | 0 | } |
107 | | |
108 | 0 | ZYAN_ASSERT(buffer->string.vector.data); |
109 | 0 | ZYAN_ASSERT(buffer->string.vector.size); |
110 | |
|
111 | 0 | *string = &buffer->string; |
112 | |
|
113 | 0 | return ZYAN_STATUS_SUCCESS; |
114 | 0 | } |
115 | | |
116 | | ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, ZydisTokenType type) |
117 | 9.14k | { |
118 | 9.14k | if (!buffer) |
119 | 0 | { |
120 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
121 | 0 | } |
122 | | |
123 | 9.14k | if (!buffer->is_token_list) |
124 | 0 | { |
125 | 0 | return ZYAN_STATUS_SUCCESS; |
126 | 0 | } |
127 | | |
128 | 9.14k | ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1; |
129 | 9.14k | if (last->type == type) |
130 | 290 | { |
131 | 290 | return ZYAN_STATUS_SUCCESS; |
132 | 290 | } |
133 | | |
134 | 8.85k | const ZyanUSize len = buffer->string.vector.size; |
135 | 8.85k | ZYAN_ASSERT((len > 0) && (len < 256)); |
136 | 8.85k | if (buffer->capacity <= len + sizeof(ZydisFormatterToken)) |
137 | 217 | { |
138 | 217 | return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; |
139 | 217 | } |
140 | | |
141 | 8.63k | last->next = (ZyanU8)len; |
142 | | |
143 | 8.63k | const ZyanUSize delta = len + sizeof(ZydisFormatterToken); |
144 | 8.63k | buffer->capacity -= delta; |
145 | 8.63k | buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta; |
146 | 8.63k | buffer->string.vector.size = 1; |
147 | 8.63k | buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255); |
148 | 8.63k | *(char*)buffer->string.vector.data = '\0'; |
149 | | |
150 | 8.63k | ZydisFormatterToken* const token = (ZydisFormatterToken*)buffer->string.vector.data - 1; |
151 | 8.63k | token->type = type; |
152 | 8.63k | token->next = 0; |
153 | | |
154 | 8.63k | return ZYAN_STATUS_SUCCESS; |
155 | 8.85k | } |
156 | | |
157 | | ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, ZyanUPointer* state) |
158 | 0 | { |
159 | 0 | if (!buffer || !state) |
160 | 0 | { |
161 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
162 | 0 | } |
163 | | |
164 | 0 | if (buffer->is_token_list) |
165 | 0 | { |
166 | 0 | *state = (ZyanUPointer)buffer->string.vector.data; |
167 | 0 | } else |
168 | 0 | { |
169 | 0 | *state = (ZyanUPointer)buffer->string.vector.size; |
170 | 0 | } |
171 | |
|
172 | 0 | return ZYAN_STATUS_SUCCESS; |
173 | 0 | } |
174 | | |
175 | | ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, ZyanUPointer state) |
176 | 0 | { |
177 | 0 | if (!buffer) |
178 | 0 | { |
179 | 0 | return ZYAN_STATUS_INVALID_ARGUMENT; |
180 | 0 | } |
181 | | |
182 | 0 | if (buffer->is_token_list) |
183 | 0 | { |
184 | 0 | const ZyanUSize delta = (ZyanUPointer)buffer->string.vector.data - state; |
185 | 0 | buffer->capacity += delta; |
186 | 0 | buffer->string.vector.data = (void*)state; |
187 | 0 | buffer->string.vector.size = 1; // TODO: Restore size? |
188 | 0 | buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255); |
189 | 0 | *(char*)buffer->string.vector.data = '\0'; |
190 | 0 | } else |
191 | 0 | { |
192 | 0 | buffer->string.vector.size = (ZyanUSize)state; |
193 | 0 | ZYDIS_STRING_NULLTERMINATE(&buffer->string); |
194 | 0 | } |
195 | |
|
196 | 0 | return ZYAN_STATUS_SUCCESS; |
197 | 0 | } |
198 | | |
199 | | /* ---------------------------------------------------------------------------------------------- */ |
200 | | |
201 | | /* ============================================================================================== */ |