Mercurial > pub > dyncall > dyncall
comparison dyncall/dyncall_struct.c @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | ee2b6e54b074 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3e629dc19168 |
---|---|
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); | |
57 assert(s->pCurrentStruct->nextField <= (DCint)s->pCurrentStruct->fieldCount - 1); | |
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); | |
110 for (i = 0; i < s->fieldCount; i++) { | |
111 DCfield *f = s->pFields + i; | |
112 DCsize fieldAlignment; | |
113 if (f->type == DC_SIGCHAR_STRUCT) { | |
114 dcComputeStructSize(f->pSubStruct); | |
115 f->size = f->pSubStruct->size; | |
116 fieldAlignment = f->pSubStruct->alignment; | |
117 } else { | |
118 fieldAlignment = f->size; | |
119 } | |
120 if (!f->alignment) | |
121 f->alignment = fieldAlignment; | |
122 | |
123 if (f->alignment > s->alignment) | |
124 s->alignment = f->alignment; | |
125 | |
126 f->size *= f->arrayLength; | |
127 | |
128 /*printf("FIELD %d, size = %d, alignment = %d\n", (int)i, (int)f->size, (int)f->alignment);@@@*/ | |
129 } | |
130 for (i = 0; i < s->fieldCount; i++) { | |
131 DCfield *f = s->pFields + i; | |
132 dcAlign(&s->size, f->alignment); | |
133 s->size += f->size; | |
134 } | |
135 dcAlign(&s->size, s->alignment); | |
136 | |
137 /*printf("STRUCT size = %d, alignment = %d\n", (int)s->size, (int)s->alignment);@@@*/ | |
138 } | |
139 | |
140 | |
141 void dcCloseStruct(DCstruct* s) | |
142 { | |
143 assert(s); | |
144 assert(s->pCurrentStruct); | |
145 assert(s->pCurrentStruct->nextField == s->pCurrentStruct->fieldCount); | |
146 if (!s->pCurrentStruct->pLastStruct) { | |
147 dcComputeStructSize(s->pCurrentStruct); | |
148 } | |
149 s->pCurrentStruct = s->pCurrentStruct->pLastStruct; | |
150 } | |
151 | |
152 | |
153 void dcFreeStruct(DCstruct* s) | |
154 { | |
155 DCsize i; | |
156 assert(s); | |
157 for (i = 0; i < s->fieldCount; i++) { | |
158 DCfield *f = s->pFields + i; | |
159 if (f->type == DC_SIGCHAR_STRUCT) | |
160 dcFreeStruct(f->pSubStruct); | |
161 } | |
162 free(s->pFields); | |
163 free(s); | |
164 } | |
165 | |
166 | |
167 DCsize dcStructSize(DCstruct* s) | |
168 { | |
169 assert(!s->pCurrentStruct && "Struct was not closed"); | |
170 return s->size; | |
171 } | |
172 | |
173 DCsize dcStructAlignment(DCstruct* s) | |
174 { | |
175 assert(!s->pCurrentStruct && "Struct was not closed"); | |
176 return s->alignment; | |
177 } | |
178 | |
179 | |
180 void dcArgStructUnroll(DCCallVM* vm, DCstruct* s, DCpointer value) | |
181 { | |
182 DCsize i; | |
183 /*printf("UNROLLING STRUCT !\n");@@@*/ | |
184 assert(s && value); | |
185 for (i = 0; i < s->fieldCount; i++) { | |
186 DCfield *f = s->pFields + i; | |
187 DCpointer p = (char*)value + f->offset; | |
188 switch(f->type) { | |
189 case DC_SIGCHAR_STRUCT: | |
190 dcArgStruct(vm, f->pSubStruct, p); | |
191 break; | |
192 case DC_SIGCHAR_BOOL: | |
193 dcArgBool (vm, *(DCbool*)p); | |
194 break; | |
195 case DC_SIGCHAR_CHAR: | |
196 case DC_SIGCHAR_UCHAR: | |
197 dcArgChar (vm, *(DCchar*)p); | |
198 break; | |
199 case DC_SIGCHAR_SHORT: | |
200 case DC_SIGCHAR_USHORT: | |
201 dcArgShort (vm, *(DCshort*)p); | |
202 break; | |
203 case DC_SIGCHAR_INT: | |
204 case DC_SIGCHAR_UINT: | |
205 dcArgInt (vm, *(DCint*)p); | |
206 break; | |
207 case DC_SIGCHAR_LONG: | |
208 case DC_SIGCHAR_ULONG: | |
209 dcArgLong (vm, *(DCulong*)p); | |
210 break; | |
211 case DC_SIGCHAR_LONGLONG: | |
212 case DC_SIGCHAR_ULONGLONG: | |
213 dcArgLongLong (vm, *(DCulonglong*)p); | |
214 break; | |
215 case DC_SIGCHAR_FLOAT: | |
216 dcArgFloat (vm, *(DCfloat*)p); | |
217 break; | |
218 case DC_SIGCHAR_DOUBLE: | |
219 dcArgDouble (vm, *(DCdouble*)p); | |
220 break; | |
221 case DC_SIGCHAR_POINTER: | |
222 case DC_SIGCHAR_STRING: | |
223 dcArgPointer (vm, *(DCpointer**)p); | |
224 break; | |
225 default: | |
226 assert(0); | |
227 } | |
228 } | |
229 } | |
230 | |
231 | |
232 static DCint readInt(const char** ptr) | |
233 { | |
234 return strtol(*ptr, (char**)ptr, 10);/*@@@ enough*/ | |
235 } | |
236 | |
237 | |
238 DCstruct* dcDefineStruct(const char* signature) | |
239 { | |
240 DCstruct* s; | |
241 const char* ptr = signature; | |
242 DCint fieldCount = readInt(&ptr); | |
243 s = dcNewStruct(fieldCount, DEFAULT_ALIGNMENT); | |
244 | |
245 while (*ptr) { | |
246 char type = *(ptr++); | |
247 if (type == DC_SIGCHAR_STRUCT) { | |
248 /*dcSubStruct( @@@*/ | |
249 } else { | |
250 dcStructField(s, type, DEFAULT_ALIGNMENT, readInt(&ptr)); | |
251 } | |
252 } | |
253 dcCloseStruct(s); | |
254 return s; | |
255 } | |
256 |