Overview
Comment: | Add support for parsing XML property lists |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
db0bf9d5a71ff675a974490d6428b3b3 |
User & Date: | js on 2018-03-18 00:28:53 |
Other Links: | manifest | tags |
Context
2018-03-18
| ||
00:52 | Implement +[operatingSystemVersion] for macOS/iOS check-in: 01104c5e85 user: js tags: trunk | |
00:28 | Add support for parsing XML property lists check-in: db0bf9d5a7 user: js tags: trunk | |
2018-03-17
| ||
21:53 | Add +[OFSystemInfo operatingSystem{Name,Version}] check-in: c6ed29d881 user: js tags: trunk | |
Changes
Modified src/Makefile from [d9f762d49e] to [41173c04c6].
︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 83 84 85 86 87 | OFSortedList.m \ OFStdIOStream.m \ ${OFSTDIOSTREAM_WIN32CONSOLE_M} \ OFStream.m \ OFString.m \ OFString+CryptoHashing.m \ OFString+JSONValue.m \ OFString+Serialization.m \ OFString+URLEncoding.m \ OFString+XMLEscaping.m \ OFString+XMLUnescaping.m \ OFSystemInfo.m \ OFTarArchive.m \ OFTarArchiveEntry.m \ | > | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | OFSortedList.m \ OFStdIOStream.m \ ${OFSTDIOSTREAM_WIN32CONSOLE_M} \ OFStream.m \ OFString.m \ OFString+CryptoHashing.m \ OFString+JSONValue.m \ OFString+PropertyListValue.m \ OFString+Serialization.m \ OFString+URLEncoding.m \ OFString+XMLEscaping.m \ OFString+XMLUnescaping.m \ OFSystemInfo.m \ OFTarArchive.m \ OFTarArchiveEntry.m \ |
︙ | ︙ |
Added src/OFString+PropertyListValue.h version [aa7e273f95].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018 * Jonathan Schleifer <js@heap.zone> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * 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 "OFString.h" OF_ASSUME_NONNULL_BEGIN #ifdef __cplusplus extern "C" { #endif extern int _OFString_PropertyListValue_reference; #ifdef __cplusplus } #endif @interface OFString (PropertyListValue) /*! * @brief The string interpreted as a property list and parsed as an object. * * @note This only supports XML property lists! */ @property (readonly, nonatomic) id propertyListValue; @end OF_ASSUME_NONNULL_END |
Added src/OFString+PropertyListValue.m version [c15d2666c9].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 109 110 111 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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | /* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018 * Jonathan Schleifer <js@heap.zone> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * 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. */ #include "config.h" #import "OFString+PropertyListValue.h" #import "OFArray.h" #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" #import "OFNumber.h" #import "OFXMLElement.h" #import "OFInvalidFormatException.h" #import "OFUnsupportedVersionException.h" int _OFString_PropertyListValue_reference; static id parseElement(OFXMLElement *element); static OFArray * parseArrayElement(OFXMLElement *element) { OFMutableArray *ret = [OFMutableArray array]; void *pool = objc_autoreleasePoolPush(); for (OFXMLElement *child in [element elements]) [ret addObject: parseElement(child)]; [ret makeImmutable]; objc_autoreleasePoolPop(pool); return ret; } static OFDictionary * parseDictElement(OFXMLElement *element) { OFMutableDictionary *ret = [OFMutableDictionary dictionary]; void *pool = objc_autoreleasePoolPush(); OFArray OF_GENERIC(OFXMLElement *) *children = [element elements]; OFEnumerator OF_GENERIC(OFXMLElement *) *enumerator; OFXMLElement *key, *object; if ([children count] % 2 != 0) @throw [OFInvalidFormatException exception]; enumerator = [children objectEnumerator]; while ((key = [enumerator nextObject]) && (object = [enumerator nextObject])) { if ([key namespace] != nil || [[key attributes] count] != 0 || ![[key name] isEqual: @"key"]) @throw [OFInvalidFormatException exception]; [ret setObject: parseElement(object) forKey: [key stringValue]]; } [ret makeImmutable]; objc_autoreleasePoolPop(pool); return ret; } static OFString * parseStringElement(OFXMLElement *element) { return [element stringValue]; } static OFData * parseDataElement(OFXMLElement *element) { return [OFData dataWithBase64EncodedString: [element stringValue]]; } static OFDate * parseDateElement(OFXMLElement *element) { return [OFDate dateWithDateString: [element stringValue] format: @"%Y-%m-%dT%H:%M:%SZ"]; } static OFNumber * parseTrueElement(OFXMLElement *element) { if ([[element children] count] != 0) @throw [OFInvalidFormatException exception]; return [OFNumber numberWithBool: true]; } static OFNumber * parseFalseElement(OFXMLElement *element) { if ([[element children] count] != 0) @throw [OFInvalidFormatException exception]; return [OFNumber numberWithBool: false]; } static OFNumber * parseRealElement(OFXMLElement *element) { return [OFNumber numberWithDouble: [[element stringValue] doubleValue]]; } static OFNumber * parseIntegerElement(OFXMLElement *element) { return [OFNumber numberWithIntMax: [[element stringValue] decimalValue]]; } static id parseElement(OFXMLElement *element) { OFString *elementName; if ([element namespace] != nil || [[element attributes] count] != 0) @throw [OFInvalidFormatException exception]; elementName = [element name]; if ([elementName isEqual: @"array"]) return parseArrayElement(element); else if ([elementName isEqual: @"dict"]) return parseDictElement(element); else if ([elementName isEqual: @"string"]) return parseStringElement(element); else if ([elementName isEqual: @"data"]) return parseDataElement(element); else if ([elementName isEqual: @"date"]) return parseDateElement(element); else if ([elementName isEqual: @"true"]) return parseTrueElement(element); else if ([elementName isEqual: @"false"]) return parseFalseElement(element); else if ([elementName isEqual: @"real"]) return parseRealElement(element); else if ([elementName isEqual: @"integer"]) return parseIntegerElement(element); else @throw [OFInvalidFormatException exception]; } @implementation OFString (PropertyListValue) - (id)propertyListValue { void *pool = objc_autoreleasePoolPush(); OFXMLElement *rootElement = [OFXMLElement elementWithXMLString: self]; OFXMLAttribute *versionAttribute; OFArray OF_GENERIC(OFXMLElement *) *elements; id ret; if (![[rootElement name] isEqual: @"plist"] || [rootElement namespace] != nil) @throw [OFInvalidFormatException exception]; versionAttribute = [rootElement attributeForName: @"version"]; if (versionAttribute == nil) @throw [OFInvalidFormatException exception]; if (![[versionAttribute stringValue] isEqual: @"1.0"]) @throw [OFUnsupportedVersionException exceptionWithVersion: [versionAttribute stringValue]]; elements = [rootElement elements]; if ([elements count] != 1) @throw [OFInvalidFormatException exception]; ret = parseElement([elements firstObject]); [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @end |
Modified src/OFString.h from [47bba28c27] to [0b96a25a15].
︙ | ︙ | |||
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 | #import "OFConstantString.h" #import "OFMutableString.h" #import "OFString+CryptoHashing.h" #import "OFString+JSONValue.h" #ifdef OF_HAVE_FILES # import "OFString+PathAdditions.h" #endif #import "OFString+Serialization.h" #import "OFString+URLEncoding.h" #import "OFString+XMLEscaping.h" #import "OFString+XMLUnescaping.h" #if !defined(NSINTEGER_DEFINED) && !__has_feature(modules) /* | > | 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | #import "OFConstantString.h" #import "OFMutableString.h" #import "OFString+CryptoHashing.h" #import "OFString+JSONValue.h" #ifdef OF_HAVE_FILES # import "OFString+PathAdditions.h" #endif #import "OFString+PropertyListValue.h" #import "OFString+Serialization.h" #import "OFString+URLEncoding.h" #import "OFString+XMLEscaping.h" #import "OFString+XMLUnescaping.h" #if !defined(NSINTEGER_DEFINED) && !__has_feature(modules) /* |
︙ | ︙ |
Modified src/OFString.m from [1c64791f79] to [2a7e99dee8].
︙ | ︙ | |||
119 120 121 122 123 124 125 126 127 128 129 130 131 132 | _references_to_categories_of_OFString(void) { _OFString_CryptoHashing_reference = 1; _OFString_JSONValue_reference = 1; #ifdef OF_HAVE_FILES _OFString_PathAdditions_reference = 1; #endif _OFString_Serialization_reference = 1; _OFString_URLEncoding_reference = 1; _OFString_XMLEscaping_reference = 1; _OFString_XMLUnescaping_reference = 1; } void | > | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | _references_to_categories_of_OFString(void) { _OFString_CryptoHashing_reference = 1; _OFString_JSONValue_reference = 1; #ifdef OF_HAVE_FILES _OFString_PathAdditions_reference = 1; #endif _OFString_PropertyListValue_reference = 1; _OFString_Serialization_reference = 1; _OFString_URLEncoding_reference = 1; _OFString_XMLEscaping_reference = 1; _OFString_XMLUnescaping_reference = 1; } void |
︙ | ︙ |
Modified src/OFXMLParser.h from [8d5866753d] to [34f43298f1].
︙ | ︙ | |||
125 126 127 128 129 130 131 | * @class OFXMLParser OFXMLParser.h ObjFW/OFXMLParser.h * * @brief An event-based XML parser. * * OFXMLParser is an event-based XML parser which calls the delegate's callbacks * as soon as it finds something, thus suitable for streams as well. */ | | | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | * @class OFXMLParser OFXMLParser.h ObjFW/OFXMLParser.h * * @brief An event-based XML parser. * * OFXMLParser is an event-based XML parser which calls the delegate's callbacks * as soon as it finds something, thus suitable for streams as well. */ @interface OFXMLParser: OFObject { id <OFXMLParserDelegate> _Nullable _delegate; enum of_xml_parser_state { OF_XMLPARSER_IN_BYTE_ORDER_MARK, OF_XMLPARSER_OUTSIDE_TAG, OF_XMLPARSER_TAG_OPENED, OF_XMLPARSER_IN_PROCESSING_INSTRUCTIONS, |
︙ | ︙ |
Modified src/OFXMLParser.m from [9e54ac8837] to [b2f6d860ce].
︙ | ︙ | |||
37 38 39 40 41 42 43 | #import "OFOutOfRangeException.h" #import "OFUnboundPrefixException.h" typedef void (*state_function_t)(id, SEL); static SEL selectors[OF_XMLPARSER_NUM_STATES]; static state_function_t lookupTable[OF_XMLPARSER_NUM_STATES]; | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #import "OFOutOfRangeException.h" #import "OFUnboundPrefixException.h" typedef void (*state_function_t)(id, SEL); static SEL selectors[OF_XMLPARSER_NUM_STATES]; static state_function_t lookupTable[OF_XMLPARSER_NUM_STATES]; @interface OFXMLParser () <OFStringXMLUnescapingDelegate> - (void)of_inByteOrderMarkState; - (void)of_outsideTagState; - (void)of_tagOpenedState; - (void)of_inProcessingInstructionsState; - (void)of_inTagNameState; - (void)of_inCloseTagNameState; - (void)of_inTagState; |
︙ | ︙ |
Modified tests/Makefile from [8e0e6ff06b] to [c6bfc1c65e].
︙ | ︙ | |||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 | OFHTTPCookieManagerTests.m \ OFInvocationTests.m \ OFJSONTests.m \ OFListTests.m \ OFMethodSignatureTests.m \ OFNumberTests.m \ OFObjectTests.m \ OFSetTests.m \ OFStreamTests.m \ OFStringTests.m \ OFURLTests.m \ OFValueTests.m \ OFXMLElementBuilderTests.m \ OFXMLNodeTests.m \ | > | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | OFHTTPCookieManagerTests.m \ OFInvocationTests.m \ OFJSONTests.m \ OFListTests.m \ OFMethodSignatureTests.m \ OFNumberTests.m \ OFObjectTests.m \ OFPropertyListTests.m \ OFSetTests.m \ OFStreamTests.m \ OFStringTests.m \ OFURLTests.m \ OFValueTests.m \ OFXMLElementBuilderTests.m \ OFXMLNodeTests.m \ |
︙ | ︙ |
Added tests/OFPropertyListTests.m version [9ab61dab17].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | /* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, * 2018 * Jonathan Schleifer <js@heap.zone> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE.QPL included in * the packaging of this file. * * 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. */ #include "config.h" #import "OFString.h" #import "OFArray.h" #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" #import "OFNumber.h" #import "OFAutoreleasePool.h" #import "OFInvalidFormatException.h" #import "OFUnsupportedVersionException.h" #import "TestsAppDelegate.h" #define PLIST(x) \ @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \ @"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" " \ @"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" \ @"<plist version=\"1.0\">\n" \ x @"\n" \ @"</plist>" static OFString *module = @"OFPropertyList"; static OFString *PLIST1 = PLIST(@"<string>Hello</string>"); static OFString *PLIST2 = PLIST( @"<array>" @" <string>Hello</string>" @" <data>V29ybGQh</data>" @" <date>2018-03-14T12:34:56Z</date>" @" <true/>" @" <false/>" @" <real>12.25</real>" @" <integer>-10</integer>" @"</array>"); static OFString *PLIST3 = PLIST( @"<dict>" @" <key>array</key>" @" <array>" @" <string>Hello</string>" @" <data>V29ybGQh</data>" @" <date>2018-03-14T12:34:56Z</date>" @" <true/>" @" <false/>" @" <real>12.25</real>" @" <integer>-10</integer>" @" </array>" @" <key>foo</key>" @" <string>bar</string>" @"</dict>"); @implementation TestsAppDelegate (OFPLISTParser) - (void)propertyListTests { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFArray *array = [OFArray arrayWithObjects: @"Hello", [OFData dataWithItems: "World!" count: 6], [OFDate dateWithTimeIntervalSince1970: 1521030896], [OFNumber numberWithBool: true], [OFNumber numberWithBool: false], [OFNumber numberWithFloat: 12.25], [OFNumber numberWithInt: -10], nil]; TEST(@"-[propertyListValue:] #1", [[PLIST1 propertyListValue] isEqual: @"Hello"]) TEST(@"-[propertyListValue:] #2", [[PLIST2 propertyListValue] isEqual: array]) TEST(@"-[propertyListValue:] #3", [[PLIST3 propertyListValue] isEqual: [OFDictionary dictionaryWithKeysAndObjects: @"array", array, @"foo", @"bar", nil]]) EXPECT_EXCEPTION(@"-[propertyListValue] detecting unsupported version", OFUnsupportedVersionException, [[PLIST(@"<string/>") stringByReplacingOccurrencesOfString: @"1.0" withString: @"1.1"] propertyListValue]) EXPECT_EXCEPTION( @"-[propertyListValue] detecting invalid format #1", OFInvalidFormatException, [PLIST(@"<string x='b'/>") propertyListValue]) EXPECT_EXCEPTION( @"-[propertyListValue] detecting invalid format #2", OFInvalidFormatException, [PLIST(@"<string xmlns='foo'/>") propertyListValue]) EXPECT_EXCEPTION( @"-[propertyListValue] detecting invalid format #3", OFInvalidFormatException, [PLIST(@"<dict count='0'/>") propertyListValue]) EXPECT_EXCEPTION( @"-[propertyListValue] detecting invalid format #4", OFInvalidFormatException, [PLIST(@"<dict><key/><string/><key/></dict>") propertyListValue]) EXPECT_EXCEPTION( @"-[propertyListValue] detecting invalid format #5", OFInvalidFormatException, [PLIST(@"<dict><key x='x'/><string/></dict>") propertyListValue]) [pool drain]; } @end |
Modified tests/TestsAppDelegate.h from [1db9587198] to [0a503e50ce].
︙ | ︙ | |||
144 145 146 147 148 149 150 151 152 153 154 155 156 157 | @interface TestsAppDelegate (OFNumberTests) - (void)numberTests; @end @interface TestsAppDelegate (OFObjectTests) - (void)objectTests; @end @interface TestsAppDelegate (OFPluginTests) - (void)pluginTests; @end @interface TestsAppDelegate (RuntimeTests) - (void)runtimeTests; | > > > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | @interface TestsAppDelegate (OFNumberTests) - (void)numberTests; @end @interface TestsAppDelegate (OFObjectTests) - (void)objectTests; @end @interface TestsAppDelegate (OFPropertyListTests) - (void)propertyListTests; @end @interface TestsAppDelegate (OFPluginTests) - (void)pluginTests; @end @interface TestsAppDelegate (RuntimeTests) - (void)runtimeTests; |
︙ | ︙ |
Modified tests/TestsAppDelegate.m from [a633b7ccbe] to [119c280046].
︙ | ︙ | |||
433 434 435 436 437 438 439 440 441 442 443 444 445 446 | [self XMLParserTests]; [self XMLNodeTests]; [self XMLElementBuilderTests]; #ifdef OF_HAVE_FILES [self serializationTests]; #endif [self JSONTests]; #if defined(OF_HAVE_PLUGINS) [self pluginTests]; #endif #if defined(OF_IOS) [self outputString: [OFString stringWithFormat: @"%d tests failed!", _fails] | > | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | [self XMLParserTests]; [self XMLNodeTests]; [self XMLElementBuilderTests]; #ifdef OF_HAVE_FILES [self serializationTests]; #endif [self JSONTests]; [self propertyListTests]; #if defined(OF_HAVE_PLUGINS) [self pluginTests]; #endif #if defined(OF_IOS) [self outputString: [OFString stringWithFormat: @"%d tests failed!", _fails] |
︙ | ︙ |