Index: utils/objfw-new/NewClass.m ================================================================== --- utils/objfw-new/NewClass.m +++ utils/objfw-new/NewClass.m @@ -70,13 +70,39 @@ property.type, property.name]; if (properties.count > 0) [headerFile writeString: @"}\n\n"]; - for (Property *property in properties) - [headerFile writeFormat: @"@property %@%@;\n", + for (Property *property in properties) { + [headerFile writeString: @"@property "]; + + if (property.attributes.count > 0) { + bool first = true; + + if ([property.attributes containsObject: @"nullable"]) + [headerFile writeString: + @"OF_NULLABLE_PROPERTY "]; + + [headerFile writeString: @"("]; + + for (OFString *attribute in property.attributes) { + if ([attribute isEqual: @"nullable"]) + continue; + + if (!first) + [headerFile writeString: @", "]; + + [headerFile writeString: attribute]; + first = false; + } + + [headerFile writeString: @") "]; + } + + [headerFile writeFormat: @"%@_%@;\n", property.type, property.name]; + } [headerFile writeString: @"@end\n" @"\n" @"OF_ASSUME_NONNULL_END\n"]; Index: utils/objfw-new/Property.h ================================================================== --- utils/objfw-new/Property.h +++ utils/objfw-new/Property.h @@ -19,15 +19,17 @@ OF_ASSUME_NONNULL_BEGIN @interface Property: OFObject { OFString *_name, *_type; + OFArray OF_GENERIC(OFString *) *_attributes; } + (instancetype)propertyWithString: (OFString *)string; - (instancetype)initWithString: (OFString *)string; @property (readonly, nonatomic) OFString *name; @property (readonly, nonatomic) OFString *type; +@property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *attributes; @end OF_ASSUME_NONNULL_END Index: utils/objfw-new/Property.m ================================================================== --- utils/objfw-new/Property.m +++ utils/objfw-new/Property.m @@ -15,19 +15,22 @@ #include "config.h" #import "Property.h" +#import "OFArray.h" +#import "OFString.h" + #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" @interface Property () - (void)parseString: (OFString *)string; @end @implementation Property -@synthesize name = _name, type = _type; +@synthesize name = _name, type = _type, attributes = _attributes; + (instancetype)propertyWithString: (OFString *)string { return [[[self alloc] initWithString: string] autorelease]; } @@ -46,16 +49,57 @@ return self; } - (void)parseString: (OFString *)string { + void *pool = objc_autoreleasePoolPush(); const char *UTF8String = string.UTF8String; size_t length = string.UTF8StringLength, nameIdx = -1; + OFMutableArray *attributes = nil; if (length > SSIZE_MAX) @throw [OFOutOfRangeException exception]; + if (UTF8String[0] == '(') { + for (size_t i = 0, level = 0; i < length; i++) { + if (UTF8String[i] == '(') + level++; + else if (UTF8String[i] == ')') { + if (--level == 0) { + OFString *attributesString = [OFString + stringWithUTF8String: UTF8String + 1 + length: i - 1]; + attributes = [[[attributesString + componentsSeparatedByString: @","] + mutableCopy] autorelease]; + + UTF8String += i + 1; + length += i + 1; + + while (*UTF8String == ' ' || + *UTF8String == '\t') { + UTF8String++; + length--; + } + + break; + } + } + } + } + + for (size_t i = 0; i < attributes.count; i++) { + OFString *attribute = [[attributes objectAtIndex: i] + stringByDeletingEnclosingWhitespaces]; + + [attributes replaceObjectAtIndex: i + withObject: attribute]; + } + + [attributes makeImmutable]; + _attributes = [attributes copy]; + for (ssize_t i = (ssize_t)length - 1; i > 0; i--) { if (UTF8String[i] == '*' || UTF8String[i] == ' ' || UTF8String[i] == '\t') { nameIdx = i + 1; break; @@ -66,10 +110,12 @@ @throw [OFInvalidArgumentException exception]; _name = [[OFString alloc] initWithUTF8String: UTF8String + nameIdx]; _type = [[OFString alloc] initWithUTF8String: UTF8String length: (size_t)nameIdx]; + + objc_autoreleasePoolPop(pool); } - (void)dealloc { [_name release];