summaryrefslogtreecommitdiff
path: root/Objective-C/PyObjC/objc_support.m
diff options
context:
space:
mode:
authorMatthias Benkard <code@mail.matthias.benkard.de>2008-01-28 19:17:00 +0100
committerMatthias Benkard <code@mail.matthias.benkard.de>2008-01-28 19:17:00 +0100
commit7cea2578637b823e93798e308ab0811c7fd7b7a4 (patch)
tree0db0eb3e9065528052ef618059ec7da91a44418a /Objective-C/PyObjC/objc_support.m
parentb44ee368288b98ed5125ccb214e6d665c134be1f (diff)
Directory layout: Put code imported from PyObjC into its own directory.
darcs-hash:e3dd1138105e4eece0fbcbc13365eb3a25ffb808
Diffstat (limited to 'Objective-C/PyObjC/objc_support.m')
-rw-r--r--Objective-C/PyObjC/objc_support.m505
1 files changed, 505 insertions, 0 deletions
diff --git a/Objective-C/PyObjC/objc_support.m b/Objective-C/PyObjC/objc_support.m
new file mode 100644
index 0000000..862879c
--- /dev/null
+++ b/Objective-C/PyObjC/objc_support.m
@@ -0,0 +1,505 @@
+/* Copyright (c) 1996,97,98 by Lele Gaifax. All Rights Reserved
+ * Copyright (c) 2002, 2003 Ronald Oussoren
+ *
+ * This software may be used and distributed freely for any purpose
+ * provided that this notice is included unchanged on any and all
+ * copies. The author does not warrant or guarantee this software in
+ * any way.
+ *
+ * This file is part of the PyObjC package.
+ *
+ * RCSfile: objc_support.m,v
+ * Revision: 1.24
+ * Date: 1998/08/18 15:35:58
+ *
+ * Created Tue Sep 10 14:16:02 1996.
+ */
+
+#include "objc_support.h"
+#include "pyobjc.h"
+
+#include <objc/Protocol.h>
+
+#include <unistd.h>
+
+#ifdef MACOSX
+/* OSX 10.1 doesn't define LLONG_MIN, LLONG_MAX and ULLONG_MAX */
+#ifndef LLONG_MIN
+#error "Mac OS X 10.1 not supported"
+#endif
+#endif
+
+#import <Foundation/NSInvocation.h>
+#import <Foundation/NSData.h>
+#import <Foundation/NSValue.h>
+#import <Foundation/NSDecimalNumber.h>
+
+#ifdef MACOSX
+#include <CoreFoundation/CFNumber.h>
+#endif /* MACOSX */
+
+
+/* Define in order to throw exceptions when a typespec cannot be parsed. */
+#undef STRICT_TYPE_PARSING
+
+
+#ifndef MAX
+static inline ssize_t
+MAX(ssize_t x, ssize_t y)
+{
+ return x > y ? x : y;
+}
+#endif
+
+static inline ssize_t
+ROUND(ssize_t v, ssize_t a)
+{
+ if (v % a == 0) {
+ return v;
+ } else {
+ return v + a - (v % a);
+ }
+}
+
+
+const char*
+PyObjCRT_SkipTypeQualifiers (const char* type)
+{
+ while (
+ *type == _C_CONST ||
+ *type == _C_IN ||
+ *type == _C_INOUT ||
+ *type == _C_OUT ||
+ *type == _C_BYCOPY ||
+ *type == _C_ONEWAY) {
+ type++;
+ }
+ while (*type && isdigit(*type)) type++;
+ return type;
+}
+
+
+const char *
+PyObjCRT_SkipTypeSpec (const char *type)
+{
+ type = PyObjCRT_SkipTypeQualifiers (type);
+
+ switch (*type) {
+ /* The following are one character type codes */
+ case _C_UNDEF:
+ case _C_CLASS:
+ case _C_SEL:
+ case _C_CHR:
+ case _C_UCHR:
+ case _C_CHARPTR:
+#ifdef _C_ATOM
+ case _C_ATOM:
+#endif
+#ifdef _C_BOOL
+ case _C_BOOL:
+#endif
+ case _C_SHT:
+ case _C_USHT:
+ case _C_INT:
+ case _C_UINT:
+ case _C_LNG:
+ case _C_ULNG:
+ case _C_FLT:
+ case _C_DBL:
+ case _C_VOID:
+ case _C_LNGLNG:
+ case _C_ULNGLNG:
+ case _C_BFLD: /* Not really 1 character, but close enough */
+ ++type;
+ break;
+
+ case _C_ID:
+ ++type;
+#ifdef MACOSX
+ if (*type == '"') {
+ /* embedded field name in an ivar_type */
+ type=strchr(type+1, '"');
+ if (type != NULL) {
+ type++;
+ }
+ }
+#endif
+ break;
+
+ case _C_ARY_B:
+ /* skip digits, typespec and closing ']' */
+
+ while (isdigit (*++type));
+ type = PyObjCRT_SkipTypeSpec (type);
+ assert (type == NULL || *type == _C_ARY_E);
+ if (type) type++;
+ break;
+
+ case _C_STRUCT_B:
+ /* skip name, and elements until closing '}' */
+ while (*type != _C_STRUCT_E && *type++ != '=');
+ while (type && *type != _C_STRUCT_E) {
+ if (*type == '"') {
+ /* embedded field names */
+ type = strchr(type+1, '"');
+ if (type != NULL) {
+ type++;
+ } else {
+ return NULL;
+ }
+ }
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ if (type) type++;
+ break;
+
+ case _C_UNION_B:
+ /* skip name, and elements until closing ')' */
+ while (*type != _C_UNION_E && *type++ != '=');
+ while (type && *type != _C_UNION_E) {
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ if (type) type++;
+ break;
+
+ case _C_PTR:
+ case _C_CONST:
+ case _C_IN:
+ case _C_INOUT:
+ case _C_OUT:
+ case _C_BYCOPY:
+ case _C_ONEWAY:
+
+ /* Just skip the following typespec */
+ type = PyObjCRT_SkipTypeSpec (type+1);
+ break;
+
+
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec"
+ reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type);
+#endif
+ return NULL;
+ }
+
+ /* The compiler inserts a number after the actual signature,
+ * this number may or may not be usefull depending on the compiler
+ * version. We never use it.
+ */
+ while (type && *type && isdigit(*type)) type++;
+ return type;
+}
+
+/*
+Return the alignment of an object specified by type
+*/
+
+/*
+* On MacOS X, the elements of a struct are aligned differently inside the
+* struct than outside. That is, the maximum alignment of any struct field
+* (except the first) is 4, doubles outside of a struct have an alignment of
+* 8.
+*
+* Other platform don't seem to have this inconsistency.
+*
+* XXX: sizeof_struct, alignof_struct and {de,}pythonify_c_struct should
+* probably be moved to platform dependend files. As long as this is the
+* only platform dependent code this isn't worth the effort.
+*/
+#ifdef MACOSX
+
+static inline ssize_t
+PyObjC_EmbeddedAlignOfType (const char* type)
+{
+ ssize_t align = PyObjCRT_AlignOfType(type);
+
+#ifdef __i386__
+ return align;
+
+#else
+ if (align < 4 || align == 16) {
+ return align;
+ } else {
+ return 4;
+ }
+#endif
+}
+
+#else
+
+static inline int
+PyObjC_EmbeddedAlignOfType (const char* type)
+{
+ ssize_t align = PyObjCRT_AlignOfType(type);
+
+ /* GNUstep/ix86 seems to behave like this: */
+ if (align < 4) {
+ return align;
+ } else {
+ return 4;
+ }
+}
+
+#endif
+
+ssize_t
+PyObjCRT_AlignOfType (const char *type)
+{
+ switch (*type) {
+ case _C_ID: return __alignof__ (id);
+ case _C_CLASS: return __alignof__ (Class);
+ case _C_SEL: return __alignof__ (SEL);
+ case _C_CHR: return __alignof__ (char);
+ case _C_UCHR: return __alignof__ (unsigned char);
+ case _C_SHT: return __alignof__ (short);
+ case _C_USHT: return __alignof__ (unsigned short);
+#ifdef _C_BOOL
+ case _C_BOOL: return __alignof__ (bool);
+#endif
+ case _C_INT: return __alignof__ (int);
+ case _C_UINT: return __alignof__ (unsigned int);
+ case _C_LNG: return __alignof__ (long);
+ case _C_ULNG: return __alignof__ (unsigned long);
+ case _C_FLT: return __alignof__ (float);
+ case _C_DBL:
+#if defined(__APPLE__) && defined(__i386__)
+ /* The ABI says natural alignment is 4 bytes, but
+ * GCC's __alignof__ says 8. The latter is wrong.
+ */
+ return 4;
+#else
+ return __alignof__ (double);
+#endif
+
+ case _C_CHARPTR: return __alignof__ (char *);
+#ifdef _C_ATOM
+ case _C_ATOM: return __alignof__ (char *);
+#endif
+ case _C_PTR: return __alignof__ (void *);
+#if defined(__APPLE__) && defined(__i386__)
+ /* The ABI says natural alignment is 4 bytes, but
+ * GCC's __alignof__ says 8. The latter is wrong.
+ */
+ case _C_LNGLNG: return 4;
+ case _C_ULNGLNG: return 4;
+#else
+ case _C_LNGLNG: return __alignof__(long long);
+ case _C_ULNGLNG: return __alignof__(unsigned long long);
+#endif
+
+ case _C_ARY_B:
+ while (isdigit(*++type)) /* do nothing */;
+ return PyObjCRT_AlignOfType (type);
+
+ case _C_STRUCT_B:
+ {
+ struct { int x; double y; } fooalign;
+ while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
+ if (*type != _C_STRUCT_E) {
+ int have_align = 0;
+ ssize_t align = 0;
+
+ while (type != NULL && *type != _C_STRUCT_E) {
+ if (*type == '"') {
+ type = strchr(type+1, '"');
+ if (type) type++;
+ }
+ if (have_align) {
+ align = MAX(align,
+ PyObjC_EmbeddedAlignOfType(type));
+ } else {
+ align = PyObjCRT_AlignOfType(type);
+ have_align = 1;
+ }
+ type = PyObjCRT_SkipTypeSpec(type);
+ }
+ if (type == NULL) return -1;
+ return align;
+ } else {
+ return __alignof__ (fooalign);
+ }
+ }
+
+ case _C_UNION_B:
+ {
+ int maxalign = 0;
+ type++;
+ while (*type != _C_UNION_E)
+ {
+ int item_align = PyObjCRT_AlignOfType(type);
+ if (item_align == -1) return -1;
+ maxalign = MAX (maxalign, item_align);
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ return maxalign;
+ }
+
+ case _C_CONST:
+ case _C_IN:
+ case _C_INOUT:
+ case _C_OUT:
+ case _C_BYCOPY:
+ case _C_ONEWAY:
+ return PyObjCRT_AlignOfType(type+1);
+
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec"
+ reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type);
+#endif
+ return -1;
+ }
+}
+
+/*
+The aligned size if the size rounded up to the nearest alignment.
+*/
+
+static ssize_t
+PyObjCRT_AlignedSize (const char *type)
+{
+ ssize_t size = PyObjCRT_SizeOfType (type);
+ ssize_t align = PyObjCRT_AlignOfType (type);
+
+ if (size == -1 || align == -1) return -1;
+ return ROUND(size, align);
+}
+
+/*
+return the size of an object specified by type
+*/
+
+ssize_t
+PyObjCRT_SizeOfType (const char *type)
+{
+ ssize_t itemSize;
+ switch (*type) {
+ case _C_VOID: return 0;
+ case _C_ID: return sizeof(id);
+ case _C_CLASS: return sizeof(Class);
+ case _C_SEL: return sizeof(SEL);
+ case _C_CHR: return sizeof(char);
+ case _C_UCHR: return sizeof(unsigned char);
+ case _C_SHT: return sizeof(short);
+ case _C_USHT: return sizeof(unsigned short);
+#ifdef _C_BOOL
+ case _C_BOOL: return sizeof(bool);
+#endif
+ case _C_INT: return sizeof(int);
+ case _C_UINT: return sizeof(unsigned int);
+ case _C_LNG: return sizeof(long);
+ case _C_ULNG: return sizeof(unsigned long);
+ case _C_FLT: return sizeof(float);
+ case _C_DBL: return sizeof(double);
+ case _C_LNGLNG: return sizeof(long long);
+ case _C_ULNGLNG: return sizeof(unsigned long long);
+
+ case _C_PTR:
+ case _C_CHARPTR:
+#ifdef _C_ATOM
+ case _C_ATOM:
+#endif
+ return sizeof(char*);
+
+ case _C_ARY_B:
+ {
+ ssize_t len = atoi(type+1);
+ ssize_t item_align;
+ while (isdigit(*++type))
+ ;
+ item_align = PyObjCRT_AlignedSize(type);
+ if (item_align == -1) return -1;
+ return len*item_align;
+ }
+ break;
+
+ case _C_STRUCT_B:
+ {
+ ssize_t acc_size = 0;
+ int have_align = 0;
+ ssize_t align;
+ ssize_t max_align = 0;
+
+ while (*type != _C_STRUCT_E && *type++ != '=')
+ ; /* skip "<name>=" */
+ while (*type != _C_STRUCT_E) {
+ if (*type == '"') {
+ type = strchr(type+1, '"');
+ if (type) type++;
+ }
+ if (have_align) {
+ align = PyObjC_EmbeddedAlignOfType(type);
+ if (align == -1) return -1;
+ } else {
+ align = PyObjCRT_AlignOfType(type);
+ if (align == -1) return -1;
+ have_align = 1;
+ }
+ max_align = MAX(align, max_align);
+ acc_size = ROUND (acc_size, align);
+
+ itemSize = PyObjCRT_SizeOfType (type);
+ if (itemSize == -1) return -1;
+ acc_size += itemSize;
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ if (max_align) {
+ acc_size = ROUND(acc_size, max_align);
+ }
+ return acc_size;
+ }
+
+ case _C_UNION_B:
+ {
+ ssize_t max_size = 0;
+ type++;
+ while (*type != _C_UNION_E) {
+ itemSize = PyObjCRT_SizeOfType (type);
+ if (itemSize == -1) return -1;
+ max_size = MAX (max_size, itemSize);
+ type = PyObjCRT_SkipTypeSpec (type);
+ }
+ return max_size;
+ }
+
+ case _C_CONST:
+ case _C_IN:
+ case _C_INOUT:
+ case _C_OUT:
+ case _C_BYCOPY:
+ case _C_ONEWAY:
+ return PyObjCRT_SizeOfType(type+1);
+
+ default:
+#ifdef STRICT_TYPE_PARSING
+ [[NSException exceptionWithName: @"PyObjCRT_SkipTypeSpec"
+ reason: [NSString stringWithFormat: @"Unhandled type: '%c'", *type]
+ userInfo: NULL] raise];
+#else
+ NSLog (@"PyObjCRT_SkipTypeSpec: Unhandled type: '%c'", *type);
+#endif
+ return -1;
+ }
+}
+
+
+ssize_t
+PyObjCRT_SizeOfReturnType(const char* type)
+{
+ switch(*type) {
+ case _C_CHR:
+ case _C_UCHR:
+ case _C_SHT:
+ case _C_USHT:
+ return sizeof(int);
+ default:
+ return PyObjCRT_SizeOfType(type);
+ }
+}