Index: new_tests/OFJSONTests.m ================================================================== --- new_tests/OFJSONTests.m +++ new_tests/OFJSONTests.m @@ -30,11 +30,11 @@ @implementation OFJSONTests - (void)setUp { [super setUp]; - _dictionary = [[OFDictionary alloc] initWithKeysAndObjects: + _dictionary = [[OTOrderedDictionary alloc] initWithKeysAndObjects: @"foo", @"b\na\r", @"x", [OFArray arrayWithObjects: [OFNumber numberWithFloat: .5f], [OFNumber numberWithInt: 0xF], [OFNull null], @@ -56,43 +56,27 @@ OTAssertEqualObjects(string.objectByParsingJSON, _dictionary); } - (void)testJSONRepresentation { - OFString *representation = _dictionary.JSONRepresentation; - - OTAssert( - [representation isEqual: - @"{\"x\":[0.5,15,null,\"foo\",false],\"foo\":\"b\\na\\r\"}"] || - [representation isEqual: - @"{\"foo\":\"b\\na\\r\",\"x\":[0.5,15,null,\"foo\",false]}"]); + OTAssert(_dictionary.JSONRepresentation, + @"{\"foo\":\"b\\na\\r\",\"x\":[0.5,15,null,\"foo\",false]}"); } - (void)testPrettyJSONRepresentation { - OFString *representation = [_dictionary JSONRepresentationWithOptions: - OFJSONRepresentationOptionPretty]; - - OTAssert( - [representation isEqual: - @"{\n\t\"x\": [\n\t\t0.5,\n\t\t15,\n\t\tnull,\n\t\t" - @"\"foo\",\n\t\tfalse\n\t],\n\t\"foo\": \"b\\na\\r\"\n}"] || - [representation isEqual: + OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions: + OFJSONRepresentationOptionPretty], @"{\n\t\"foo\": \"b\\na\\r\",\n\t\"x\": [\n\t\t0.5,\n\t\t15," - @"\n\t\tnull,\n\t\t\"foo\",\n\t\tfalse\n\t]\n}"]); + @"\n\t\tnull,\n\t\t\"foo\",\n\t\tfalse\n\t]\n}"); } - (void)testJSON5Representation { - OFString *representation = [_dictionary JSONRepresentationWithOptions: - OFJSONRepresentationOptionJSON5]; - - OTAssert( - [representation isEqual: - @"{x:[0.5,15,null,\"foo\",false],foo:\"b\\\na\\r\"}"] || - [representation isEqual: - @"{foo:\"b\\\na\\r\",x:[0.5,15,null,\"foo\",false]}"]); + OTAssertEqualObjects([_dictionary JSONRepresentationWithOptions: + OFJSONRepresentationOptionJSON5], + @"{foo:\"b\\\na\\r\",x:[0.5,15,null,\"foo\",false]}"); } - (void)testObjectByParsingJSONFailsWithInvalidJSON { OTAssertThrowsSpecific([@"{" objectByParsingJSON], Index: src/test/Makefile ================================================================== --- src/test/Makefile +++ src/test/Makefile @@ -2,11 +2,12 @@ DISTCLEAN = Info.plist STATIC_LIB = libobjfwtest.a -SRCS = OTAssert.m \ +SRCS = OTAssert.m \ + OTOrderedDictionary.m \ OTTestCase.m INCLUDES := ${SRCS:.m=.h} \ ObjFWTest.h SRCS += OTAppDelegate.m \ OTAssertionFailedException.m ADDED src/test/OTOrderedDictionary.h Index: src/test/OTOrderedDictionary.h ================================================================== --- src/test/OTOrderedDictionary.h +++ src/test/OTOrderedDictionary.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * 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. + */ + +#ifdef OBJFWTEST_LOCAL_INCLUDES +# import "ObjFW.h" +#else +# import +#endif + +OF_ASSUME_NONNULL_BEGIN + +@interface OTOrderedDictionary: OFDictionary +{ + OFArray *_keys; + OFArray *_objects; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/test/OTOrderedDictionary.m Index: src/test/OTOrderedDictionary.m ================================================================== --- src/test/OTOrderedDictionary.m +++ src/test/OTOrderedDictionary.m @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * 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 "OTOrderedDictionary.h" + +@implementation OTOrderedDictionary +- (instancetype)initWithObjects: (id const *)objects + forKeys: (id const *)keys + count: (size_t)count +{ + self = [super init]; + + @try { + OFMutableArray *mutableKeys, *mutableObjects; + + mutableKeys = [[OFMutableArray alloc] initWithCapacity: count]; + _keys = mutableKeys; + + mutableObjects = [[OFMutableArray alloc] + initWithCapacity: count]; + _objects = mutableObjects; + + for (size_t i = 0; i < count; i++) { + OFLog(@"key=%@, value=%@", keys[i], objects[i]); + [mutableKeys addObject: keys[i]]; + [mutableObjects addObject: objects[i]]; + } + + [mutableKeys makeImmutable]; + [mutableObjects makeImmutable]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_keys release]; + [_objects release]; + + [super dealloc]; +} + +- (id)objectForKey: (id)key +{ + size_t i = 0; + + for (id iter in _keys) { + if ([iter isEqual: key]) + return [_objects objectAtIndex: i]; + + i++; + } + + return nil; +} + +- (size_t)count +{ + return _keys.count; +} + +- (OFEnumerator *)keyEnumerator +{ + return [_keys objectEnumerator]; +} + +- (OFEnumerator *)objectEnumerator +{ + return [_objects objectEnumerator]; +} +@end Index: src/test/ObjFWTest.h ================================================================== --- src/test/ObjFWTest.h +++ src/test/ObjFWTest.h @@ -13,5 +13,6 @@ * file. */ #import "OTTestCase.h" #import "OTAssert.h" +#import "OTOrderedDictionary.h"