xref: /haiku/src/libs/zydis/Zydis/FormatterBuffer.c (revision bc2428853ff331825f608f1b6cceb96bc006ebae)
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 {
41     if (!token || !type || !value)
42     {
43         return ZYAN_STATUS_INVALID_ARGUMENT;
44     }
45 
46     *type = token->type;
47     *value = (ZyanConstCharPointer)((ZyanU8*)token + sizeof(ZydisFormatterToken));
48 
49     return ZYAN_STATUS_SUCCESS;
50 }
51 
52 ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token)
53 {
54     if (!token || !*token)
55     {
56         return ZYAN_STATUS_INVALID_ARGUMENT;
57     }
58 
59     const ZyanU8 next = (*token)->next;
60     if (!next)
61     {
62         return ZYAN_STATUS_OUT_OF_RANGE;
63     }
64     *token = (ZydisFormatterTokenConst*)((ZyanU8*)*token + sizeof(ZydisFormatterToken) + next);
65 
66     return ZYAN_STATUS_SUCCESS;
67 }
68 
69 /* ---------------------------------------------------------------------------------------------- */
70 /* Buffer                                                                                         */
71 /* ---------------------------------------------------------------------------------------------- */
72 
73 ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer,
74     ZydisFormatterTokenConst** token)
75 {
76     if (!buffer || !token)
77     {
78         return ZYAN_STATUS_INVALID_ARGUMENT;
79     }
80 
81     *token = ((ZydisFormatterTokenConst*)buffer->string.vector.data - 1);
82     if ((*token)->type == ZYDIS_TOKEN_INVALID)
83     {
84         return ZYAN_STATUS_INVALID_OPERATION;
85     }
86 
87     return ZYAN_STATUS_SUCCESS;
88 }
89 
90 ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, ZyanString** string)
91 {
92     if (!buffer || !string)
93     {
94         return ZYAN_STATUS_INVALID_ARGUMENT;
95     }
96 
97     if (buffer->is_token_list &&
98         ((ZydisFormatterTokenConst*)buffer->string.vector.data - 1)->type == ZYDIS_TOKEN_INVALID)
99     {
100         return ZYAN_STATUS_INVALID_OPERATION;
101     }
102 
103     ZYAN_ASSERT(buffer->string.vector.data);
104     ZYAN_ASSERT(buffer->string.vector.size);
105 
106     *string = &buffer->string;
107 
108     return ZYAN_STATUS_SUCCESS;
109 }
110 
111 ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, ZydisTokenType type)
112 {
113     if (!buffer)
114     {
115         return ZYAN_STATUS_INVALID_ARGUMENT;
116     }
117 
118     if (!buffer->is_token_list)
119     {
120         return ZYAN_STATUS_SUCCESS;
121     }
122 
123     const ZyanUSize len = buffer->string.vector.size;
124     ZYAN_ASSERT((len > 0) && (len < 256));
125     if (buffer->capacity <= len + sizeof(ZydisFormatterToken))
126     {
127         return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
128     }
129 
130     ZydisFormatterToken* const last  = (ZydisFormatterToken*)buffer->string.vector.data - 1;
131     last->next = (ZyanU8)len;
132 
133     const ZyanUSize delta = len + sizeof(ZydisFormatterToken);
134     buffer->capacity -= delta;
135     buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta;
136     buffer->string.vector.size = 1;
137     buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
138     *(char*)buffer->string.vector.data = '\0';
139 
140     ZydisFormatterToken* const token = (ZydisFormatterToken*)buffer->string.vector.data - 1;
141     token->type = type;
142     token->next = 0;
143 
144     return ZYAN_STATUS_SUCCESS;
145 }
146 
147 ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, ZyanUPointer* state)
148 {
149     if (!buffer || !state)
150     {
151         return ZYAN_STATUS_INVALID_ARGUMENT;
152     }
153 
154     if (buffer->is_token_list)
155     {
156         *state = (ZyanUPointer)buffer->string.vector.data;
157     } else
158     {
159         *state = (ZyanUPointer)buffer->string.vector.size;
160     }
161 
162     return ZYAN_STATUS_SUCCESS;
163 }
164 
165 ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, ZyanUPointer state)
166 {
167     if (!buffer)
168     {
169         return ZYAN_STATUS_INVALID_ARGUMENT;
170     }
171 
172     if (buffer->is_token_list)
173     {
174         const ZyanUSize delta = (ZyanUPointer)buffer->string.vector.data - state;
175         buffer->capacity += delta;
176         buffer->string.vector.data = (void*)state;
177         buffer->string.vector.size = 1; // TODO: Restore size?
178         buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
179         *(char*)buffer->string.vector.data = '\0';
180     } else
181     {
182         buffer->string.vector.size = (ZyanUSize)state;
183         ZYDIS_STRING_NULLTERMINATE(&buffer->string);
184     }
185 
186     return ZYAN_STATUS_SUCCESS;
187 }
188 
189 /* ---------------------------------------------------------------------------------------------- */
190 
191 /* ============================================================================================== */
192