mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
@@ -0,0 +1,125 @@
|
||||
@import "CPObject.j"
|
||||
@import "CPEnumerator.j"
|
||||
@import "CPDictionary.j"
|
||||
@import "CPArray.j"
|
||||
|
||||
/*!
|
||||
@class CPMapTable
|
||||
@ingroup foundation
|
||||
A mutable collection modeled after NSDictionary that allows for arbitrary
|
||||
objects or values to be used as keys. This implementation uses the native
|
||||
ECMAScript 6 Map object for its underlying storage.
|
||||
*/
|
||||
@implementation CPMapTable : CPObject
|
||||
{
|
||||
// The underlying ES6 Map to store the key-value pairs.
|
||||
id _map;
|
||||
}
|
||||
|
||||
/*!
|
||||
Initializes a new, empty CPMapTable.
|
||||
*/
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_map = new Map();
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Accessing Content
|
||||
|
||||
/*!
|
||||
Returns the value associated with a given key.
|
||||
@param aKey The key for which to return the corresponding value.
|
||||
@return The value associated with aKey, or nil if no value is associated with aKey.
|
||||
*/
|
||||
- (id)objectForKey:(id)aKey
|
||||
{
|
||||
var value = _map.get(aKey);
|
||||
return value === undefined ? nil : value;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an enumerator object that lets you access each key in the map table.
|
||||
@return A CPEnumerator object for the keys in the map table.
|
||||
*/
|
||||
- (CPEnumerator)keyEnumerator
|
||||
{
|
||||
return [[..._map.keys()] objectEnumerator];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an enumerator object that lets you access each value in the map table.
|
||||
@return A CPEnumerator object for the values in the map table.
|
||||
*/
|
||||
- (CPEnumerator)objectEnumerator
|
||||
{
|
||||
return [[..._map.values()] objectEnumerator];
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of key-value pairs in the map table.
|
||||
@return The number of entries in the map table.
|
||||
*/
|
||||
- (unsigned int)count
|
||||
{
|
||||
return _map.size;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Manipulating Content
|
||||
|
||||
/*!
|
||||
Adds a given key-value pair to the map table.
|
||||
If aKey already exists in the map table, anObject takes its place.
|
||||
@param anObject The value for aKey.
|
||||
@param aKey The key for anObject.
|
||||
*/
|
||||
- (void)setObject:(id)anObject forKey:(id)aKey
|
||||
{
|
||||
_map.set(aKey, anObject);
|
||||
}
|
||||
|
||||
/*!
|
||||
Removes a given key and its associated value from the map table.
|
||||
@param aKey The key to remove.
|
||||
*/
|
||||
- (void)removeObjectForKey:(id)aKey
|
||||
{
|
||||
_map.delete(aKey);
|
||||
}
|
||||
|
||||
/*!
|
||||
Empties the map table of its entries.
|
||||
*/
|
||||
- (void)removeAllObjects
|
||||
{
|
||||
_map.clear();
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Creating a Dictionary Representation
|
||||
|
||||
/*!
|
||||
Returns a dictionary representation of the map table.
|
||||
Note: This will only work correctly if all keys are strings.
|
||||
|
||||
@return A CPDictionary containing the entries of the map table.
|
||||
*/
|
||||
- (CPDictionary)dictionaryRepresentation
|
||||
{
|
||||
var dictionary = [CPDictionary dictionary];
|
||||
|
||||
for (var [key, value] of _map.entries())
|
||||
{
|
||||
[dictionary setObject:value forKey:key];
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,153 @@
|
||||
@import <Foundation/CPMapTable.j>
|
||||
@import <Foundation/CPDictionary.j>
|
||||
@import <Foundation/CPEnumerator.j>
|
||||
@import <Foundation/CPMutableArray.j>
|
||||
@import <OJUnit/OJTestCase.j>
|
||||
|
||||
@implementation CPMapTableTest : OJTestCase
|
||||
{
|
||||
CPMapTable map_table;
|
||||
id objectKey;
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
map_table = [[CPMapTable alloc] init];
|
||||
objectKey = [[CPObject alloc] init];
|
||||
}
|
||||
|
||||
- (void)testInit
|
||||
{
|
||||
[self assert:[map_table count] equals:0];
|
||||
}
|
||||
|
||||
- (void)testSetObjectForKey
|
||||
{
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[self assert:[map_table count] equals:1];
|
||||
[self assert:[map_table objectForKey:@"key1"] equals:@"value1"];
|
||||
|
||||
[map_table setObject:@"value2" forKey:123];
|
||||
[self assert:[map_table count] equals:2];
|
||||
[self assert:[map_table objectForKey:123] equals:@"value2"];
|
||||
|
||||
[map_table setObject:@"value3" forKey:objectKey];
|
||||
[self assert:[map_table count] equals:3];
|
||||
[self assert:[map_table objectForKey:objectKey] equals:@"value3"];
|
||||
|
||||
// Test overriding a value
|
||||
[map_table setObject:@"newValue" forKey:@"key1"];
|
||||
[self assert:[map_table count] equals:3];
|
||||
[self assert:[map_table objectForKey:@"key1"] equals:@"newValue"];
|
||||
}
|
||||
|
||||
- (void)testObjectForKey
|
||||
{
|
||||
[self assertNull:[map_table objectForKey:@"nonExistentKey"]];
|
||||
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[self assert:[map_table objectForKey:@"key1"] equals:@"value1"];
|
||||
}
|
||||
|
||||
- (void)testCount
|
||||
{
|
||||
[self assert:[map_table count] equals:0];
|
||||
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[self assert:[map_table count] equals:1];
|
||||
|
||||
[map_table setObject:@"value2" forKey:@"key2"];
|
||||
[self assert:[map_table count] equals:2];
|
||||
|
||||
[map_table removeObjectForKey:@"key1"];
|
||||
[self assert:[map_table count] equals:1];
|
||||
}
|
||||
|
||||
- (void)testRemoveObjectForKey
|
||||
{
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[map_table setObject:@"value2" forKey:123];
|
||||
|
||||
[map_table removeObjectForKey:@"key1"];
|
||||
[self assert:[map_table count] equals:1];
|
||||
[self assertNull:[map_table objectForKey:@"key1"]];
|
||||
[self assert:[map_table objectForKey:123] equals:@"value2"];
|
||||
|
||||
[map_table removeObjectForKey:123];
|
||||
[self assert:[map_table count] equals:0];
|
||||
[self assertNull:[map_table objectForKey:123]];
|
||||
}
|
||||
|
||||
- (void)testRemoveAllObjects
|
||||
{
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[map_table setObject:@"value2" forKey:@"key2"];
|
||||
|
||||
[map_table removeAllObjects];
|
||||
[self assert:[map_table count] equals:0];
|
||||
[self assertNull:[map_table objectForKey:@"key1"]];
|
||||
[self assertNull:[map_table objectForKey:@"key2"]];
|
||||
}
|
||||
|
||||
- (void)testKeyEnumeratorOnEmptyMap
|
||||
{
|
||||
[self assert:[map_table count] equals:0 message:@"Pre-condition failed: map should be empty."];
|
||||
[self assertNull:[[map_table keyEnumerator] nextObject]];
|
||||
}
|
||||
|
||||
- (void)testKeyEnumeratorOnPopulatedMap
|
||||
{
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[map_table setObject:@"value2" forKey:123];
|
||||
[map_table setObject:@"value3" forKey:objectKey];
|
||||
|
||||
var foundKeys = [CPMutableArray array],
|
||||
enumerator = [map_table keyEnumerator],
|
||||
aKey;
|
||||
|
||||
while (aKey = [enumerator nextObject])
|
||||
[foundKeys addObject:aKey];
|
||||
|
||||
[self assert:[foundKeys count] equals:3];
|
||||
[self assertTrue:[foundKeys containsObject:@"key1"]];
|
||||
[self assertTrue:[foundKeys containsObject:123]];
|
||||
[self assertTrue:[foundKeys containsObject:objectKey]];
|
||||
}
|
||||
|
||||
- (void)testObjectEnumeratorOnEmptyMap
|
||||
{
|
||||
[self assert:[map_table count] equals:0 message:@"Pre-condition failed: map should be empty."];
|
||||
[self assertNull:[[map_table objectEnumerator] nextObject]];
|
||||
}
|
||||
|
||||
- (void)testObjectEnumeratorOnPopulatedMap
|
||||
{
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[map_table setObject:@"value2" forKey:123];
|
||||
[map_table setObject:@"value3" forKey:objectKey];
|
||||
|
||||
var foundValues = [CPMutableArray array],
|
||||
enumerator = [map_table objectEnumerator],
|
||||
aValue;
|
||||
|
||||
while (aValue = [enumerator nextObject])
|
||||
[foundValues addObject:aValue];
|
||||
|
||||
[self assert:[foundValues count] equals:3];
|
||||
[self assertTrue:[foundValues containsObject:@"value1"]];
|
||||
[self assertTrue:[foundValues containsObject:@"value2"]];
|
||||
[self assertTrue:[foundValues containsObject:@"value3"]];
|
||||
}
|
||||
|
||||
- (void)testDictionaryRepresentation
|
||||
{
|
||||
[map_table setObject:@"value1" forKey:@"key1"];
|
||||
[map_table setObject:@"value2" forKey:@"key2"];
|
||||
|
||||
var dictionary = [map_table dictionaryRepresentation];
|
||||
[self assert:[dictionary count] equals:2];
|
||||
[self assert:[dictionary objectForKey:@"key1"] equals:@"value1"];
|
||||
[self assert:[dictionary objectForKey:@"key2"] equals:@"value2"];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user