]> git.saurik.com Git - cycript.git/commitdiff
Support Internal_getProperty with bitfield types.
authorJay Freeman (saurik) <saurik@saurik.com>
Tue, 7 Jan 2014 09:38:40 +0000 (01:38 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Tue, 7 Jan 2014 09:55:13 +0000 (01:55 -0800)
ObjectiveC/Library.mm

index 3fa5c705c784c74cda40f20dcf722a2aee6eb747..c72212eebfe32f5c6091f60437264881c1d7e1f7 100644 (file)
@@ -1977,9 +1977,32 @@ static JSValueRef Internal_getProperty(JSContextRef context, JSObjectRef object,
 #endif
 
     if (objc_ivar *ivar = object_getInstanceVariable(self, name, NULL)) {
-        Type_privateData type(pool, ivar_getTypeEncoding(ivar));
-        // XXX: if this fails and throws an exception the person we are throwing it to gets the wrong exception
-        return CYFromFFI(context, type.type_, type.GetFFI(), reinterpret_cast<uint8_t *>(self) + ivar_getOffset(ivar));
+        ptrdiff_t offset(ivar_getOffset(ivar));
+        void *data(reinterpret_cast<uint8_t *>(self) + offset);
+
+        const char *encoding(ivar_getTypeEncoding(ivar));
+        if (encoding[0] == 'b') {
+            unsigned length(CYCastDouble(encoding + 1));
+            unsigned shift(0);
+
+            unsigned int size;
+            objc_ivar **ivars(class_copyIvarList(object_getClass(self), &size));
+            for (size_t i(0); i != size; ++i)
+                if (ivars[i] == ivar)
+                    break;
+                else if (ivar_getOffset(ivars[i]) == offset) {
+                    const char *encoding(ivar_getTypeEncoding(ivars[i]));
+                    _assert(encoding[0] == 'b');
+                    shift += CYCastDouble(encoding + 1);
+                }
+            free(ivars);
+
+            _assert(shift + length <= sizeof(uintptr_t) * 8);
+            return CYCastJSValue(context, (*reinterpret_cast<uintptr_t *>(data) >> shift) & (1 << length) - 1);
+        } else {
+            Type_privateData type(pool, ivar_getTypeEncoding(ivar));
+            return CYFromFFI(context, type.type_, type.GetFFI(), data);
+        }
     }
 
     return NULL;