0
|
1 /*
|
|
2
|
|
3 Package: dyncall
|
|
4 Library: dyncall
|
|
5 File: dyncall/dyncall_struct.c
|
|
6 Description: C interface to compute struct size
|
|
7 License:
|
|
8
|
|
9 Copyright (c) 2010-2015 Olivier Chafik <olivier.chafik@centraliens.net>
|
|
10
|
|
11 Permission to use, copy, modify, and distribute this software for any
|
|
12 purpose with or without fee is hereby granted, provided that the above
|
|
13 copyright notice and this permission notice appear in all copies.
|
|
14
|
|
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
22
|
|
23 */
|
|
24
|
|
25
|
|
26
|
|
27 #include "dyncall.h"
|
|
28 #include "dyncall_signature.h"
|
|
29 #include "dyncall_struct.h"
|
|
30 #include "dyncall_alloc.h"
|
|
31 #include <stdio.h>
|
|
32 #include <assert.h>
|
|
33
|
|
34
|
|
35 DCstruct* dcNewStruct(DCsize fieldCount, DCint alignment)
|
|
36 {
|
|
37 DCstruct* s = (DCstruct*)dcAllocMem(sizeof(DCstruct));
|
|
38 s->pCurrentStruct = s;
|
|
39 s->pLastStruct = NULL;
|
|
40 s->nextField = 0;
|
|
41 s->fieldCount = fieldCount;
|
|
42 s->alignment = alignment;
|
|
43 s->size = 0;
|
|
44 s->pFields = (DCfield*)dcAllocMem(fieldCount * sizeof(DCfield));
|
|
45 return s;
|
|
46 }
|
|
47
|
|
48
|
|
49 void dcStructField(DCstruct* s, DCint type, DCint alignment, DCsize arrayLength)
|
|
50 {
|
|
51 DCfield *f;
|
|
52 if (type == DC_SIGCHAR_STRING) {
|
|
53 assert(!"Use dcSubStruct instead !!!");
|
|
54 return;
|
|
55 }
|
|
56 assert(s && s->pCurrentStruct);
|
338
|
57 assert(s->pCurrentStruct->nextField < (DCint)s->pCurrentStruct->fieldCount);
|
0
|
58 f = s->pCurrentStruct->pFields + (s->pCurrentStruct->nextField++);
|
|
59 f->type = type;
|
|
60 f->alignment = alignment;
|
|
61 f->arrayLength = arrayLength;
|
|
62 f->pSubStruct = NULL;
|
|
63 switch (type) {
|
|
64 case DC_SIGCHAR_BOOL: f->size = sizeof(DCbool); break;
|
|
65 case DC_SIGCHAR_CHAR:
|
|
66 case DC_SIGCHAR_UCHAR: f->size = sizeof(DCchar); break;
|
|
67 case DC_SIGCHAR_SHORT:
|
|
68 case DC_SIGCHAR_USHORT: f->size = sizeof(DCshort); break;
|
|
69 case DC_SIGCHAR_INT:
|
|
70 case DC_SIGCHAR_UINT: f->size = sizeof(DCint); break;
|
|
71 case DC_SIGCHAR_LONG:
|
|
72 case DC_SIGCHAR_ULONG: f->size = sizeof(DClong); break;
|
|
73 case DC_SIGCHAR_LONGLONG:
|
|
74 case DC_SIGCHAR_ULONGLONG: f->size = sizeof(DClonglong); break;
|
|
75 case DC_SIGCHAR_FLOAT: f->size = sizeof(DCfloat); break;
|
|
76 case DC_SIGCHAR_DOUBLE: f->size = sizeof(DCdouble); break;
|
|
77 case DC_SIGCHAR_POINTER:
|
|
78 case DC_SIGCHAR_STRING: f->size = sizeof(DCpointer); break;
|
|
79 default: assert(0);
|
|
80 }
|
|
81 }
|
|
82
|
|
83
|
|
84 void dcSubStruct(DCstruct* s, DCsize fieldCount, DCint alignment, DCsize arrayLength)
|
|
85 {
|
|
86 DCfield *f = s->pCurrentStruct->pFields + (s->pCurrentStruct->nextField++);
|
|
87 f->type = DC_SIGCHAR_STRUCT;
|
|
88 f->arrayLength = arrayLength;
|
|
89 f->alignment = alignment;
|
|
90 f->pSubStruct = dcNewStruct(fieldCount, alignment);
|
|
91 f->pSubStruct->pLastStruct = s->pCurrentStruct;
|
|
92 s->pCurrentStruct = f->pSubStruct;
|
|
93 }
|
|
94
|
|
95
|
|
96 static void dcAlign(DCsize *size, DCsize alignment)
|
|
97 {
|
|
98 DCsize mod = (*size) % alignment;
|
|
99 if (mod) {
|
|
100 DCsize rest = alignment - mod;
|
|
101 (*size) += rest;
|
|
102 }
|
|
103 }
|
|
104
|
|
105
|
|
106 static void dcComputeStructSize(DCstruct* s)
|
|
107 {
|
|
108 DCsize i;
|
|
109 assert(s);
|
338
|
110
|
|
111 /* compute field sizes and alignments, recurse if needed */
|
0
|
112 for (i = 0; i < s->fieldCount; i++) {
|
|
113 DCfield *f = s->pFields + i;
|
|
114 DCsize fieldAlignment;
|
|
115 if (f->type == DC_SIGCHAR_STRUCT) {
|
|
116 dcComputeStructSize(f->pSubStruct);
|
|
117 f->size = f->pSubStruct->size;
|
|
118 fieldAlignment = f->pSubStruct->alignment;
|
338
|
119 } else
|
0
|
120 fieldAlignment = f->size;
|
338
|
121
|
0
|
122 if (!f->alignment)
|
|
123 f->alignment = fieldAlignment;
|
338
|
124
|
|
125 /* if field alignment > struct alignment, choose former */
|
0
|
126 if (f->alignment > s->alignment)
|
|
127 s->alignment = f->alignment;
|
338
|
128
|
|
129 /* if array, it's x times the size */
|
0
|
130 f->size *= f->arrayLength;
|
338
|
131
|
0
|
132 /*printf("FIELD %d, size = %d, alignment = %d\n", (int)i, (int)f->size, (int)f->alignment);@@@*/
|
|
133 }
|
338
|
134
|
|
135 /* compute overall struct size */
|
0
|
136 for (i = 0; i < s->fieldCount; i++) {
|
|
137 DCfield *f = s->pFields + i;
|
|
138 dcAlign(&s->size, f->alignment);
|
|
139 s->size += f->size;
|
|
140 }
|
|
141 dcAlign(&s->size, s->alignment);
|
|
142
|
|
143 /*printf("STRUCT size = %d, alignment = %d\n", (int)s->size, (int)s->alignment);@@@*/
|
|
144 }
|
|
145
|
|
146
|
|
147 void dcCloseStruct(DCstruct* s)
|
|
148 {
|
|
149 assert(s);
|
|
150 assert(s->pCurrentStruct);
|
|
151 assert(s->pCurrentStruct->nextField == s->pCurrentStruct->fieldCount);
|
|
152 if (!s->pCurrentStruct->pLastStruct) {
|
|
153 dcComputeStructSize(s->pCurrentStruct);
|
|
154 }
|
|
155 s->pCurrentStruct = s->pCurrentStruct->pLastStruct;
|
|
156 }
|
|
157
|
|
158
|
|
159 void dcFreeStruct(DCstruct* s)
|
|
160 {
|
|
161 DCsize i;
|
|
162 assert(s);
|
|
163 for (i = 0; i < s->fieldCount; i++) {
|
|
164 DCfield *f = s->pFields + i;
|
|
165 if (f->type == DC_SIGCHAR_STRUCT)
|
|
166 dcFreeStruct(f->pSubStruct);
|
|
167 }
|
|
168 free(s->pFields);
|
|
169 free(s);
|
|
170 }
|
|
171
|
|
172
|
|
173 DCsize dcStructSize(DCstruct* s)
|
|
174 {
|
|
175 assert(!s->pCurrentStruct && "Struct was not closed");
|
|
176 return s->size;
|
|
177 }
|
|
178
|
|
179 DCsize dcStructAlignment(DCstruct* s)
|
|
180 {
|
|
181 assert(!s->pCurrentStruct && "Struct was not closed");
|
|
182 return s->alignment;
|
|
183 }
|
|
184
|
|
185
|
|
186 void dcArgStructUnroll(DCCallVM* vm, DCstruct* s, DCpointer value)
|
|
187 {
|
|
188 DCsize i;
|
|
189 /*printf("UNROLLING STRUCT !\n");@@@*/
|
|
190 assert(s && value);
|
|
191 for (i = 0; i < s->fieldCount; i++) {
|
|
192 DCfield *f = s->pFields + i;
|
|
193 DCpointer p = (char*)value + f->offset;
|
|
194 switch(f->type) {
|
|
195 case DC_SIGCHAR_STRUCT:
|
|
196 dcArgStruct(vm, f->pSubStruct, p);
|
|
197 break;
|
|
198 case DC_SIGCHAR_BOOL:
|
|
199 dcArgBool (vm, *(DCbool*)p);
|
|
200 break;
|
|
201 case DC_SIGCHAR_CHAR:
|
|
202 case DC_SIGCHAR_UCHAR:
|
|
203 dcArgChar (vm, *(DCchar*)p);
|
|
204 break;
|
|
205 case DC_SIGCHAR_SHORT:
|
|
206 case DC_SIGCHAR_USHORT:
|
|
207 dcArgShort (vm, *(DCshort*)p);
|
|
208 break;
|
|
209 case DC_SIGCHAR_INT:
|
|
210 case DC_SIGCHAR_UINT:
|
|
211 dcArgInt (vm, *(DCint*)p);
|
|
212 break;
|
|
213 case DC_SIGCHAR_LONG:
|
|
214 case DC_SIGCHAR_ULONG:
|
|
215 dcArgLong (vm, *(DCulong*)p);
|
|
216 break;
|
|
217 case DC_SIGCHAR_LONGLONG:
|
|
218 case DC_SIGCHAR_ULONGLONG:
|
|
219 dcArgLongLong (vm, *(DCulonglong*)p);
|
|
220 break;
|
|
221 case DC_SIGCHAR_FLOAT:
|
|
222 dcArgFloat (vm, *(DCfloat*)p);
|
|
223 break;
|
|
224 case DC_SIGCHAR_DOUBLE:
|
|
225 dcArgDouble (vm, *(DCdouble*)p);
|
|
226 break;
|
|
227 case DC_SIGCHAR_POINTER:
|
|
228 case DC_SIGCHAR_STRING:
|
|
229 dcArgPointer (vm, *(DCpointer**)p);
|
|
230 break;
|
|
231 default:
|
|
232 assert(0);
|
|
233 }
|
|
234 }
|
|
235 }
|
|
236
|
|
237
|
|
238 static DCint readInt(const char** ptr)
|
|
239 {
|
|
240 return strtol(*ptr, (char**)ptr, 10);/*@@@ enough*/
|
|
241 }
|
|
242
|
|
243
|
|
244 DCstruct* dcDefineStruct(const char* signature)
|
|
245 {
|
|
246 DCstruct* s;
|
|
247 const char* ptr = signature;
|
|
248 DCint fieldCount = readInt(&ptr);
|
|
249 s = dcNewStruct(fieldCount, DEFAULT_ALIGNMENT);
|
|
250
|
|
251 while (*ptr) {
|
|
252 char type = *(ptr++);
|
|
253 if (type == DC_SIGCHAR_STRUCT) {
|
|
254 /*dcSubStruct( @@@*/
|
|
255 } else {
|
|
256 dcStructField(s, type, DEFAULT_ALIGNMENT, readInt(&ptr));
|
|
257 }
|
|
258 }
|
|
259 dcCloseStruct(s);
|
|
260 return s;
|
|
261 }
|
|
262
|