Overview
Comment: | OFINIFile: Add support for quoted keys / values
This is a much more logical way to handle leading and trailing Additionally, this imports OFINICategory.h in OFINIFile.h so that |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
12c5b7ee912a9e4ba335e0c97b62a55f |
User & Date: | js on 2014-06-12 13:43:41 |
Other Links: | manifest | tags |
Context
2014-06-13
| ||
16:41 | Clean up OFINIFileTests.m check-in: 34cf1fb8c2 user: js tags: trunk | |
2014-06-12
| ||
13:43 | OFINIFile: Add support for quoted keys / values check-in: 12c5b7ee91 user: js tags: trunk | |
2014-05-31
| ||
17:57 | OFStream: Add -[hasDataInReadBuffer]. check-in: acc999a75e user: js tags: trunk | |
Changes
Modified src/OFINICategory.m from [900a1099e7] to [8e99773efd].
︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | @interface OFINICategory_Comment: OFObject { @public OFString *_comment; } @end @implementation OFINICategory_Pair - (void)dealloc { [_key release]; [_value release]; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | @interface OFINICategory_Comment: OFObject { @public OFString *_comment; } @end static OFString* escapeString(OFString *string) { OFMutableString *mutableString; /* FIXME: Optimize */ if (![string hasPrefix: @" "] && ![string hasPrefix: @"\t"] && ![string hasPrefix: @"\f"] && ![string hasSuffix: @" "] && ![string hasSuffix: @"\t"] && ![string hasSuffix: @"\f"] && ![string containsString: @"\""]) return string; mutableString = [[string mutableCopy] autorelease]; [mutableString replaceOccurrencesOfString: @"\\" withString: @"\\\\"]; [mutableString replaceOccurrencesOfString: @"\f" withString: @"\\f"]; [mutableString replaceOccurrencesOfString: @"\r" withString: @"\\r"]; [mutableString replaceOccurrencesOfString: @"\n" withString: @"\\n"]; [mutableString replaceOccurrencesOfString: @"\"" withString: @"\\\""]; [mutableString prependString: @"\""]; [mutableString appendString: @"\""]; [mutableString makeImmutable]; return mutableString; } static OFString* unescapeString(OFString *string) { OFMutableString *mutableString; if (![string hasPrefix: @"\""] || ![string hasSuffix: @"\""]) return string; string = [string substringWithRange: of_range(1, [string length] - 2)]; mutableString = [[string mutableCopy] autorelease]; [mutableString replaceOccurrencesOfString: @"\\f" withString: @"\f"]; [mutableString replaceOccurrencesOfString: @"\\r" withString: @"\r"]; [mutableString replaceOccurrencesOfString: @"\\n" withString: @"\n"]; [mutableString replaceOccurrencesOfString: @"\\\"" withString: @"\""]; [mutableString replaceOccurrencesOfString: @"\\\\" withString: @"\\"]; [mutableString makeImmutable]; return mutableString; } @implementation OFINICategory_Pair - (void)dealloc { [_key release]; [_value release]; |
︙ | ︙ | |||
108 109 110 111 112 113 114 | if ((pos = [line rangeOfString: @"="].location) == OF_NOT_FOUND) @throw [OFInvalidFormatException exception]; key = [line substringWithRange: of_range(0, pos)]; value = [line substringWithRange: of_range(pos + 1, [line length] - pos - 1)]; | < | | | > > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | if ((pos = [line rangeOfString: @"="].location) == OF_NOT_FOUND) @throw [OFInvalidFormatException exception]; key = [line substringWithRange: of_range(0, pos)]; value = [line substringWithRange: of_range(pos + 1, [line length] - pos - 1)]; key = [key stringByDeletingEnclosingWhitespaces]; value = [value stringByDeletingEnclosingWhitespaces]; key = unescapeString(key); value = unescapeString(value); pair->_key = [key copy]; pair->_value = [value copy]; [_lines addObject: pair]; } else { OFINICategory_Comment *comment = |
︙ | ︙ | |||
289 290 291 292 293 294 295 | objc_autoreleasePoolPop(pool); } - (void)setBool: (bool)bool_ forKey: (OFString*)key { | < | | < < < | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | objc_autoreleasePoolPop(pool); } - (void)setBool: (bool)bool_ forKey: (OFString*)key { [self setString: (bool_ ? @"true" : @"false") forKey: key]; } - (void)setFloat: (float)float_ forKey: (OFString*)key { void *pool = objc_autoreleasePoolPush(); |
︙ | ︙ | |||
369 370 371 372 373 374 375 | enumerator = [_lines objectEnumerator]; while ((line = [enumerator nextObject]) != nil) { if ([line isKindOfClass: [OFINICategory_Comment class]]) { OFINICategory_Comment *comment = line; [stream writeLine: comment->_comment]; } else if ([line isKindOfClass: [OFINICategory_Pair class]]) { OFINICategory_Pair *pair = line; | > > > | < | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | enumerator = [_lines objectEnumerator]; while ((line = [enumerator nextObject]) != nil) { if ([line isKindOfClass: [OFINICategory_Comment class]]) { OFINICategory_Comment *comment = line; [stream writeLine: comment->_comment]; } else if ([line isKindOfClass: [OFINICategory_Pair class]]) { OFINICategory_Pair *pair = line; OFString *key = escapeString(pair->_key); OFString *value = escapeString(pair->_value); [stream writeFormat: @"%@=%@\n", key, value]; } else @throw [OFInvalidArgumentException exception]; } return true; } @end |
Modified src/OFINIFile.h from [48c881a928] to [d3236d0058].
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 | * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" @class OFMutableArray; @class OFString; | > < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" #import "OFINICategory.h" @class OFMutableArray; @class OFString; /*! * @class OFINIFile OFINIFile.h ObjFW/OFINIFile.h * * @brief A class for reading, creating and modifying INI files. */ @interface OFINIFile: OFObject |
︙ | ︙ |
Modified src/OFINIFile.m from [68683c719e] to [38c671870e].
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #import "OFArray.h" #import "OFString.h" #import "OFFile.h" #import "OFINICategory.h" #import "OFINICategory+Private.h" #import "OFInvalidFormatException.h" #import "autorelease.h" #import "macros.h" @interface OFINIFile (OF_PRIVATE_CATEGORY) - (void)OF_parseFile: (OFString*)path; @end | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #import "OFArray.h" #import "OFString.h" #import "OFFile.h" #import "OFINICategory.h" #import "OFINICategory+Private.h" #import "OFInvalidFormatException.h" #import "OFOpenFileFailedException.h" #import "autorelease.h" #import "macros.h" @interface OFINIFile (OF_PRIVATE_CATEGORY) - (void)OF_parseFile: (OFString*)path; @end |
︙ | ︙ | |||
111 112 113 114 115 116 117 | return [category autorelease]; } - (void)OF_parseFile: (OFString*)path { void *pool = objc_autoreleasePoolPush(); | | < > > > > > > > > > > > | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | return [category autorelease]; } - (void)OF_parseFile: (OFString*)path { void *pool = objc_autoreleasePoolPush(); OFFile *file; OFINICategory *category = nil; OFString *line; @try { file = [OFFile fileWithPath: path mode: @"r"]; } @catch (OFOpenFileFailedException *e) { /* Handle missing file like an empty file */ if ([e errNo] == ENOENT) return; @throw e; } while ((line = [file readLine]) != nil) { if (isWhitespaceLine(line)) continue; if ([line hasPrefix: @"["]) { OFString *categoryName; |
︙ | ︙ |
Modified src/ObjFW.h from [9b2458d655] to [8316d27014].
︙ | ︙ | |||
46 47 48 49 50 51 52 | #import "OFStream.h" #import "OFStdIOStream.h" #import "OFDeflateStream.h" #ifdef OF_HAVE_FILES # import "OFFile.h" # import "OFINIFile.h" | < | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #import "OFStream.h" #import "OFStdIOStream.h" #import "OFDeflateStream.h" #ifdef OF_HAVE_FILES # import "OFFile.h" # import "OFINIFile.h" # import "OFZIPArchive.h" # import "OFZIPArchiveEntry.h" #endif #ifdef OF_HAVE_SOCKETS # import "OFStreamSocket.h" # import "OFTCPSocket.h" # import "OFUDPSocket.h" |
︙ | ︙ |
Modified tests/OFINIFileTests.m from [7ea6705870] to [556f5814fc].
︙ | ︙ | |||
40 41 42 43 44 45 46 | @"foo=baz" NL @"foobar=baz" NL @";comment" NL @"new=new" NL NL @"[foobar]" NL @";foobarcomment" NL | | > > | > > > > | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | @"foo=baz" NL @"foobar=baz" NL @";comment" NL @"new=new" NL NL @"[foobar]" NL @";foobarcomment" NL @"qux=\" asd\"" NL @"quxquxqux=\"hello\\\"world\"" NL @"qux2=\"\\f\"" NL NL @"[types]" NL @"integer=16" NL @"bool=false" NL @"float=0.25" NL @"double=0.75" NL; OFINIFile *file; OFINICategory *category; TEST(@"+[fileWithPath:]", (file = [OFINIFile fileWithPath: @"testfile.ini"])) TEST(@"-[categoryForName:]", (category = [file categoryForName: @"tests"])) module = @"OFINICategory"; TEST(@"-[stringForKey:]", [[category stringForKey: @"foo"] isEqual: @"bar"] && (category = [file categoryForName: @"foobar"]) && [[category stringForKey: @"quxquxqux"] isEqual: @"hello\"world"]) category = [file categoryForName: @"tests"]; TEST(@"-[setString:forKey:]", R([category setString: @"baz" forKey: @"foo"]) && R([category setString: @"new" forKey: @"new"])) |
︙ | ︙ | |||
100 101 102 103 104 105 106 | TEST(@"-[setDouble:forKey:]", R([category setDouble: 0.75 forKey: @"double"])) category = [file categoryForName: @"foobar"]; TEST(@"-[removeValueForKey:]", | | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | TEST(@"-[setDouble:forKey:]", R([category setDouble: 0.75 forKey: @"double"])) category = [file categoryForName: @"foobar"]; TEST(@"-[removeValueForKey:]", R([category removeValueForKey: @"quxqux "])) module = @"OFINIFile"; /* FIXME: Find a way to write files on Nintendo DS */ #ifndef OF_NINTENDO_DS TEST(@"-[writeToFile:]", R([file writeToFile: @"tmpfile.ini"]) && [[OFString stringWithContentsOfFile: @"tmpfile.ini"] |
︙ | ︙ |
Modified tests/testfile.ini from [89e5125eda] to [cf73f59c64].
1 2 3 4 5 6 7 | [tests] foo = bar foobar=baz ;comment [foobar] ;foobarcomment | | | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [tests] foo = bar foobar=baz ;comment [foobar] ;foobarcomment qux=" asd" "quxqux " = asd quxquxqux="hello\"world" qux2="\f" [types] integer = 0x20 bool = true float = 0.5 double = 0.25 |