diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dyncall/dyncall_struct.c	Thu Mar 19 22:24:28 2015 +0100
@@ -0,0 +1,256 @@
+/*
+
+ Package: dyncall
+ Library: dyncall
+ File: dyncall/dyncall_struct.c
+ Description: C interface to compute struct size
+ License:
+
+   Copyright (c) 2010-2015 Olivier Chafik <olivier.chafik@centraliens.net>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+
+
+#include "dyncall.h"
+#include "dyncall_signature.h"
+#include "dyncall_struct.h"
+#include "dyncall_alloc.h"
+#include <stdio.h>
+#include <assert.h>
+
+
+DCstruct* dcNewStruct(DCsize fieldCount, DCint alignment)
+{
+	DCstruct* s = (DCstruct*)dcAllocMem(sizeof(DCstruct));
+	s->pCurrentStruct = s;
+	s->pLastStruct = NULL;
+	s->nextField = 0;
+	s->fieldCount = fieldCount;
+	s->alignment = alignment;
+	s->size = 0;
+	s->pFields = (DCfield*)dcAllocMem(fieldCount * sizeof(DCfield));
+	return s;
+}
+
+
+void dcStructField(DCstruct* s, DCint type, DCint alignment, DCsize arrayLength)
+{
+	DCfield *f;
+	if (type == DC_SIGCHAR_STRING) {
+		assert(!"Use dcSubStruct instead !!!");
+		return;
+	}
+	assert(s && s->pCurrentStruct);
+	assert(s->pCurrentStruct->nextField <= (DCint)s->pCurrentStruct->fieldCount - 1);
+	f = s->pCurrentStruct->pFields + (s->pCurrentStruct->nextField++);
+	f->type = type;
+	f->alignment = alignment;
+	f->arrayLength = arrayLength;
+	f->pSubStruct = NULL;
+	switch (type) {
+    	case DC_SIGCHAR_BOOL:       f->size = sizeof(DCbool);     break;
+    	case DC_SIGCHAR_CHAR:       
+    	case DC_SIGCHAR_UCHAR:      f->size = sizeof(DCchar);     break;
+    	case DC_SIGCHAR_SHORT:      
+    	case DC_SIGCHAR_USHORT:     f->size = sizeof(DCshort);    break;
+    	case DC_SIGCHAR_INT:        
+    	case DC_SIGCHAR_UINT:       f->size = sizeof(DCint);      break;
+    	case DC_SIGCHAR_LONG:       
+    	case DC_SIGCHAR_ULONG:      f->size = sizeof(DClong);     break;
+    	case DC_SIGCHAR_LONGLONG:   
+    	case DC_SIGCHAR_ULONGLONG:  f->size = sizeof(DClonglong); break;
+    	case DC_SIGCHAR_FLOAT:      f->size = sizeof(DCfloat);    break;
+    	case DC_SIGCHAR_DOUBLE:     f->size = sizeof(DCdouble);   break;
+    	case DC_SIGCHAR_POINTER:
+		case DC_SIGCHAR_STRING:     f->size = sizeof(DCpointer);  break;
+		default:                    assert(0);
+	}
+}
+
+
+void dcSubStruct(DCstruct* s, DCsize fieldCount, DCint alignment, DCsize arrayLength)
+{
+	DCfield *f = s->pCurrentStruct->pFields + (s->pCurrentStruct->nextField++);
+	f->type = DC_SIGCHAR_STRUCT;
+	f->arrayLength = arrayLength;
+	f->alignment = alignment;
+	f->pSubStruct = dcNewStruct(fieldCount, alignment);
+	f->pSubStruct->pLastStruct = s->pCurrentStruct;
+	s->pCurrentStruct = f->pSubStruct;
+}  	
+
+
+static void dcAlign(DCsize *size, DCsize alignment)
+{
+	DCsize mod = (*size) % alignment;
+	if (mod) {
+		DCsize rest = alignment - mod;
+		(*size) += rest;
+	}
+}
+
+
+static void dcComputeStructSize(DCstruct* s)
+{
+	DCsize i;
+	assert(s);
+	for (i = 0; i < s->fieldCount; i++) {
+		DCfield *f = s->pFields + i;
+		DCsize fieldAlignment;
+		if (f->type == DC_SIGCHAR_STRUCT) {
+			dcComputeStructSize(f->pSubStruct);
+			f->size = f->pSubStruct->size;
+			fieldAlignment = f->pSubStruct->alignment;
+		} else {
+			fieldAlignment = f->size;
+		}
+		if (!f->alignment)
+			f->alignment = fieldAlignment;
+		
+		if (f->alignment > s->alignment)
+			s->alignment = f->alignment;
+		
+		f->size *= f->arrayLength;
+		
+		/*printf("FIELD %d, size = %d, alignment = %d\n", (int)i, (int)f->size, (int)f->alignment);@@@*/
+	}
+	for (i = 0; i < s->fieldCount; i++) {
+		DCfield *f = s->pFields + i;
+		dcAlign(&s->size, f->alignment);
+		s->size += f->size;
+	}
+	dcAlign(&s->size, s->alignment);
+	
+	/*printf("STRUCT size = %d, alignment = %d\n", (int)s->size, (int)s->alignment);@@@*/
+}
+
+
+void dcCloseStruct(DCstruct* s)
+{
+	assert(s);
+	assert(s->pCurrentStruct);
+	assert(s->pCurrentStruct->nextField == s->pCurrentStruct->fieldCount);
+	if (!s->pCurrentStruct->pLastStruct) {
+		dcComputeStructSize(s->pCurrentStruct);
+	}
+	s->pCurrentStruct = s->pCurrentStruct->pLastStruct;
+}
+
+
+void dcFreeStruct(DCstruct* s)
+{
+	DCsize i;
+	assert(s);
+	for (i = 0; i < s->fieldCount; i++) {
+		DCfield *f = s->pFields + i;
+		if (f->type == DC_SIGCHAR_STRUCT)
+			dcFreeStruct(f->pSubStruct);
+	}
+	free(s->pFields);
+	free(s);
+}
+
+
+DCsize dcStructSize(DCstruct* s)
+{
+	assert(!s->pCurrentStruct && "Struct was not closed");
+	return s->size;
+}
+
+DCsize dcStructAlignment(DCstruct* s)
+{
+	assert(!s->pCurrentStruct && "Struct was not closed");
+	return s->alignment;
+}
+
+
+void dcArgStructUnroll(DCCallVM* vm, DCstruct* s, DCpointer  value)
+{
+	DCsize i;
+	/*printf("UNROLLING STRUCT !\n");@@@*/
+	assert(s && value);
+	for (i = 0; i < s->fieldCount; i++) {
+		DCfield *f = s->pFields + i;
+		DCpointer p = (char*)value + f->offset;
+		switch(f->type) {
+		  case DC_SIGCHAR_STRUCT:
+		  	dcArgStruct(vm, f->pSubStruct, p);
+		  	break;
+		  case DC_SIGCHAR_BOOL: 
+			dcArgBool      (vm, *(DCbool*)p); 
+			break;
+		  case DC_SIGCHAR_CHAR:
+		  case DC_SIGCHAR_UCHAR:
+			dcArgChar      (vm, *(DCchar*)p);
+			break;
+		  case DC_SIGCHAR_SHORT:
+		  case DC_SIGCHAR_USHORT:
+			dcArgShort     (vm, *(DCshort*)p);
+			break;
+		  case DC_SIGCHAR_INT:
+		  case DC_SIGCHAR_UINT:
+			dcArgInt       (vm, *(DCint*)p);
+			break;
+		  case DC_SIGCHAR_LONG:
+		  case DC_SIGCHAR_ULONG:
+			dcArgLong      (vm, *(DCulong*)p);
+			break;
+		  case DC_SIGCHAR_LONGLONG:
+		  case DC_SIGCHAR_ULONGLONG:
+			dcArgLongLong  (vm, *(DCulonglong*)p);
+			break;
+		  case DC_SIGCHAR_FLOAT:
+			dcArgFloat     (vm, *(DCfloat*)p);
+			break;
+		  case DC_SIGCHAR_DOUBLE:
+			dcArgDouble    (vm, *(DCdouble*)p);
+			break;
+		  case DC_SIGCHAR_POINTER:
+		  case DC_SIGCHAR_STRING:
+			dcArgPointer   (vm, *(DCpointer**)p);
+			break;
+	       default:
+	       	assert(0);
+		}	
+	}
+}
+
+
+static DCint readInt(const char** ptr)
+{
+	return strtol(*ptr, (char**)ptr, 10);/*@@@ enough*/
+}
+
+
+DCstruct* dcDefineStruct(const char* signature)
+{
+	DCstruct* s;
+	const char* ptr = signature;
+	DCint fieldCount = readInt(&ptr);
+	s = dcNewStruct(fieldCount, DEFAULT_ALIGNMENT);
+	
+	while (*ptr) {
+		char type = *(ptr++);
+		if (type == DC_SIGCHAR_STRUCT) {
+			/*dcSubStruct(	@@@*/
+		} else {
+			dcStructField(s, type, DEFAULT_ALIGNMENT, readInt(&ptr));
+		}
+	}
+	dcCloseStruct(s);
+	return s;
+}
+