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