Преглед изворни кода

Add runtime utility method for enumerating the nested types in the encoding string for a struct.

We will use this to create a struct argument input view that is composed of input views for each of its nested types.
Ryan Olson пре 12 година
родитељ
комит
3e285573de
2 измењених фајлова са 32 додато и 0 уклоњено
  1. 1 0
      Classes/Utility/FLEXRuntimeUtility.h
  2. 31 0
      Classes/Utility/FLEXRuntimeUtility.m

+ 1 - 0
Classes/Utility/FLEXRuntimeUtility.h

@@ -37,5 +37,6 @@ extern const unsigned int kFLEXNumberOfImplicitArgs;
 + (NSString *)editableJSONStringForObject:(id)object;
 + (NSString *)editableJSONStringForObject:(id)object;
 + (id)objectValueFromEditableJSONString:(NSString *)string;
 + (id)objectValueFromEditableJSONString:(NSString *)string;
 + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString;
 + (NSValue *)valueForNumberWithObjCType:(const char *)typeEncoding fromInputString:(NSString *)inputString;
++ (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock;
 
 
 @end
 @end

+ 31 - 0
Classes/Utility/FLEXRuntimeUtility.m

@@ -437,6 +437,37 @@ const unsigned int kFLEXNumberOfImplicitArgs = 2;
     return value;
     return value;
 }
 }
 
 
++ (void)enumerateTypesInStructEncoding:(const char *)structEncoding usingBlock:(void (^)(NSString *structName, const char *fieldTypeEncoding, NSString *prettyTypeEncoding, NSUInteger fieldIndex, NSUInteger fieldOffset))typeBlock
+{
+    if (structEncoding && structEncoding[0] == '{') {
+        const char *equals = strchr(structEncoding, '=');
+        if (equals) {
+            const char *nameStart = structEncoding + 1;
+            NSString *structName = [@(structEncoding) substringWithRange:NSMakeRange(nameStart - structEncoding, equals - nameStart)];
+            
+            NSUInteger fieldAlignment = 0;
+            NSGetSizeAndAlignment(structEncoding, NULL, &fieldAlignment);
+            NSUInteger runningFieldIndex = 0;
+            NSUInteger runningFieldOffset = 0;
+            const char *typeStart = equals + 1;
+            while (*typeStart != '}') {
+                NSUInteger fieldSize = 0;
+                const char *nextTypeStart = NSGetSizeAndAlignment(typeStart, &fieldSize, NULL);
+                NSString *typeEncoding = [@(structEncoding) substringWithRange:NSMakeRange(typeStart - structEncoding, nextTypeStart - typeStart)];
+                typeBlock(structName, [typeEncoding UTF8String], [self readableTypeForEncoding:typeEncoding], runningFieldIndex, runningFieldOffset);
+                runningFieldOffset += fieldSize;
+                // Padding to keep propper alignment. __attribute((packed)) structs will break here.
+                // The type encoding is no different for packed structs, so it's not clear there's anything we can do for those.
+                if (runningFieldOffset % fieldAlignment != 0) {
+                    runningFieldOffset += fieldAlignment - runningFieldOffset % fieldAlignment;
+                }
+                runningFieldIndex++;
+                typeStart = nextTypeStart;
+            }
+        }
+    }
+}
+
 
 
 #pragma mark - Internal Helpers
 #pragma mark - Internal Helpers