Index: src/OFINICategory+Private.h ================================================================== --- src/OFINICategory+Private.h +++ src/OFINICategory+Private.h @@ -24,12 +24,11 @@ @class OFStream; OF_DIRECT_MEMBERS @interface OFINICategory () -- (instancetype)of_initWithName: (nullable OFString *)name - OF_METHOD_FAMILY(init); +- (instancetype)of_initWithName: (OFString *)name OF_METHOD_FAMILY(init); - (void)of_parseLine: (OFString *)line; - (bool)of_writeToStream: (OFStream *)stream encoding: (OFStringEncoding)encoding first: (bool)first; @end Index: src/OFINICategory.m ================================================================== --- src/OFINICategory.m +++ src/OFINICategory.m @@ -157,13 +157,10 @@ if (![line hasPrefix: @";"]) { OFINICategoryPair *pair; OFString *key, *value; size_t pos; - if (_name == nil) - @throw [OFInvalidFormatException exception]; - pair = [[[OFINICategoryPair alloc] init] autorelease]; if ((pos = [line rangeOfString: @"="].location) == OFNotFound) @throw [OFInvalidFormatException exception]; @@ -481,11 +478,11 @@ first: (bool)first { if (_lines.count == 0) return false; - if (_name != nil) { + if (_name.length > 0) { if (first) [stream writeFormat: @"[%@]\r\n", _name]; else [stream writeFormat: @"\r\n[%@]\r\n", _name]; } Index: src/OFINIFile.h ================================================================== --- src/OFINIFile.h +++ src/OFINIFile.h @@ -32,11 +32,10 @@ * @brief A class for reading, creating and modifying INI files. */ OF_SUBCLASSING_RESTRICTED @interface OFINIFile: OFObject { - OFINICategory *_prologue; OFMutableArray OF_GENERIC(OFINICategory *) *_categories; } /** * @brief All categories in the INI file. Index: src/OFINIFile.m ================================================================== --- src/OFINIFile.m +++ src/OFINIFile.m @@ -77,12 +77,12 @@ - (instancetype)initWithIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { self = [super init]; @try { - _prologue = [[OFINICategory alloc] of_initWithName: nil]; - _categories = [[OFMutableArray alloc] init]; + _categories = [[OFMutableArray alloc] initWithObject: + [[[OFINICategory alloc] of_initWithName: @""] autorelease]]; [self of_parseIRI: IRI encoding: encoding]; } @catch (id e) { [self release]; @throw e; @@ -91,11 +91,10 @@ return self; } - (void)dealloc { - [_prologue release]; [_categories release]; [super dealloc]; } @@ -118,11 +117,11 @@ - (void)of_parseIRI: (OFIRI *)IRI encoding: (OFStringEncoding)encoding { void *pool = objc_autoreleasePoolPush(); OFStream *file; - OFINICategory *category = _prologue; + OFINICategory *category = nil; OFString *line; if (encoding == OFStringEncodingAutodetect) encoding = OFStringEncodingUTF8; @@ -146,15 +145,22 @@ if (![line hasSuffix: @"]"]) @throw [OFInvalidFormatException exception]; categoryName = [line substringWithRange: OFMakeRange(1, line.length - 2)]; + if (categoryName.length == 0) + @throw [OFInvalidFormatException exception]; + category = [[[OFINICategory alloc] of_initWithName: categoryName] autorelease]; [_categories addObject: category]; - } else + } else { + if (category == nil) + category = [self categoryForName: @""]; + [category of_parseLine: line]; + } } objc_autoreleasePoolPop(pool); } @@ -167,13 +173,10 @@ { void *pool = objc_autoreleasePoolPush(); OFStream *file = [OFIRIHandler openItemAtIRI: IRI mode: @"w"]; bool first = true; - if ([_prologue of_writeToStream: file encoding: encoding first: true]) - first = false; - for (OFINICategory *category in _categories) if ([category of_writeToStream: file encoding: encoding first: first]) first = false; Index: tests/OFINIFileTests.m ================================================================== --- tests/OFINIFileTests.m +++ tests/OFINIFileTests.m @@ -109,11 +109,12 @@ [OFArray array]); } - (void)testWriteToIRIEncoding { - OFString *expectedOutput = @"; Comment before categories\r\n" + OFString *expectedOutput = @"; Comment in global category\r\n" + @"global=yes\r\n" @"\r\n" @"[tests]\r\n" @"foo=baz\r\n" @"foobar=baz\r\n" @";comment\r\n" @@ -174,17 +175,6 @@ } #else (void)expectedOutput; #endif } - -- (void)testValuePairOutsideOfCategoryRejected -{ - OFIRI *IRI = [OFIRI IRIWithString: @"embedded:testfile_broken.ini"]; - - OFRegisterEmbeddedFile(@"testfile_broken.ini", - (const uint8_t *)"; comment\r\na=b", 14); - - OTAssertThrowsSpecific([OFINIFile fileWithIRI: IRI], - OFInvalidFormatException); -} @end Index: tests/testfile.ini ================================================================== --- tests/testfile.ini +++ tests/testfile.ini @@ -1,6 +1,7 @@ -; Comment before categories +; Comment in global category +global=yes [tests] foo = bar foobar=baz ;comment