mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 13:07:02 +00:00
262 lines
6.2 KiB
JavaScript
262 lines
6.2 KiB
JavaScript
/*
|
|
* CFDictionary.js
|
|
* Objective-J
|
|
*
|
|
* Created by Francisco Tolmasky.
|
|
* Copyright 2008-2010, 280 North, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
GLOBAL(CFDictionary) = function(/*CFDictionary*/ aDictionary)
|
|
{
|
|
this._keys = [];
|
|
this._count = 0;
|
|
this._buckets = { };
|
|
this._UID = objj_generateObjectUID();
|
|
}
|
|
|
|
var indexOf = Array.prototype.indexOf,
|
|
hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
|
|
CFDictionary.prototype.copy = function()
|
|
{
|
|
// Immutable, so no need to actually copy.
|
|
return this;
|
|
};
|
|
|
|
CFDictionary.prototype.mutableCopy = function()
|
|
{
|
|
var newDictionary = new CFMutableDictionary(),
|
|
keys = this._keys,
|
|
count = this._count;
|
|
|
|
newDictionary._keys = keys.slice();
|
|
newDictionary._count = count;
|
|
|
|
var index = 0,
|
|
buckets = this._buckets,
|
|
newBuckets = newDictionary._buckets;
|
|
|
|
for (; index < count; ++index)
|
|
{
|
|
var key = keys[index];
|
|
|
|
newBuckets[key] = buckets[key];
|
|
}
|
|
|
|
return newDictionary;
|
|
};
|
|
|
|
CFDictionary.prototype.containsKey = function(/*String*/ aKey)
|
|
{
|
|
return hasOwnProperty.apply(this._buckets, [aKey]);
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.containsKey);
|
|
|
|
CFDictionary.prototype.containsValue = function(/*id*/ anObject)
|
|
{
|
|
var keys = this._keys,
|
|
buckets = this._buckets,
|
|
index = 0,
|
|
count = keys.length;
|
|
|
|
for (; index < count; ++index)
|
|
if (buckets[keys[index]] === anObject)
|
|
return YES;
|
|
|
|
return NO;
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.containsValue);
|
|
|
|
CFDictionary.prototype.count = function()
|
|
{
|
|
return this._count;
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.count);
|
|
|
|
CFDictionary.prototype.countOfKey = function(/*String*/ aKey)
|
|
{
|
|
return this.containsKey(aKey) ? 1 : 0;
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.countOfKey);
|
|
|
|
CFDictionary.prototype.countOfValue = function(/*id*/ anObject)
|
|
{
|
|
var keys = this._keys,
|
|
buckets = this._buckets,
|
|
index = 0,
|
|
count = keys.length,
|
|
countOfValue = 0;
|
|
|
|
for (; index < count; ++index)
|
|
if (buckets[keys[index]] === anObject)
|
|
++countOfValue;
|
|
|
|
return countOfValue;
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.countOfValue);
|
|
|
|
CFDictionary.prototype.keys = function()
|
|
{
|
|
return this._keys.slice();
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.keys);
|
|
|
|
CFDictionary.prototype.valueForKey = function(/*String*/ aKey)
|
|
{
|
|
var buckets = this._buckets;
|
|
|
|
if (!hasOwnProperty.apply(buckets, [aKey]))
|
|
return nil;
|
|
|
|
return buckets[aKey];
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.valueForKey);
|
|
|
|
// This allows the use of 'for...of' loops directly on CFDictionary instances.
|
|
CFDictionary.prototype[Symbol.iterator] = function*()
|
|
{
|
|
// Access the internal storage directly for maximum performance.
|
|
// 'this._keys' is the internal array of keys.
|
|
const keys = this._keys;
|
|
|
|
// 'this._buckets' is the internal hash map of key -> value.
|
|
const buckets = this._buckets;
|
|
|
|
// A 'for...of' loop on an array is itself a lazy and efficient way to iterate.
|
|
for (const key of keys)
|
|
{
|
|
// 'yield' pauses the generator and returns the [key, value] pair
|
|
// to the consumer (the for...of loop).
|
|
yield [key, buckets[key]];
|
|
}
|
|
};
|
|
|
|
CFDictionary.prototype.toString = function()
|
|
{
|
|
var string = "{\n",
|
|
keys = this._keys,
|
|
index = 0,
|
|
count = this._count;
|
|
|
|
for (; index < count; ++index)
|
|
{
|
|
var key = keys[index];
|
|
|
|
string += "\t" + key + " = \"" + String(this.valueForKey(key)).split('\n').join("\n\t") + "\"\n";
|
|
}
|
|
|
|
return string + "}";
|
|
};
|
|
|
|
DISPLAY_NAME(CFDictionary.prototype.toString);
|
|
|
|
GLOBAL(CFMutableDictionary) = function(/*CFDictionary*/ aDictionary)
|
|
{
|
|
CFDictionary.apply(this, []);
|
|
}
|
|
|
|
CFMutableDictionary.prototype = new CFDictionary();
|
|
|
|
CFMutableDictionary.prototype.copy = function()
|
|
{
|
|
return this.mutableCopy();
|
|
};
|
|
|
|
CFMutableDictionary.prototype.addValueForKey = function(/*String*/ aKey, /*Object*/ aValue)
|
|
{
|
|
if (this.containsKey(aKey))
|
|
return;
|
|
|
|
++this._count;
|
|
|
|
this._keys.push(aKey);
|
|
this._buckets[aKey] = aValue;
|
|
};
|
|
|
|
DISPLAY_NAME(CFMutableDictionary.prototype.addValueForKey);
|
|
|
|
CFMutableDictionary.prototype.removeValueForKey = function(/*String*/ aKey)
|
|
{
|
|
var indexOfKey = -1;
|
|
|
|
if (indexOf)
|
|
indexOfKey = indexOf.call(this._keys, aKey);
|
|
else
|
|
{
|
|
var keys = this._keys,
|
|
index = 0,
|
|
count = keys.length;
|
|
|
|
for (; index < count; ++index)
|
|
if (keys[index] === aKey)
|
|
{
|
|
indexOfKey = index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (indexOfKey === -1)
|
|
return;
|
|
|
|
--this._count;
|
|
|
|
this._keys.splice(indexOfKey, 1);
|
|
delete this._buckets[aKey];
|
|
};
|
|
|
|
DISPLAY_NAME(CFMutableDictionary.prototype.removeValueForKey);
|
|
|
|
CFMutableDictionary.prototype.removeAllValues = function()
|
|
{
|
|
this._count = 0;
|
|
this._keys = [];
|
|
this._buckets = { };
|
|
};
|
|
|
|
DISPLAY_NAME(CFMutableDictionary.prototype.removeAllValues);
|
|
|
|
CFMutableDictionary.prototype.replaceValueForKey = function(/*String*/ aKey, /*Object*/ aValue)
|
|
{
|
|
if (!this.containsKey(aKey))
|
|
return;
|
|
|
|
this._buckets[aKey] = aValue;
|
|
};
|
|
|
|
DISPLAY_NAME(CFMutableDictionary.prototype.replaceValueForKey);
|
|
|
|
CFMutableDictionary.prototype.setValueForKey = function(/*String*/ aKey, /*Object*/ aValue)
|
|
{
|
|
if (aValue == nil)
|
|
this.removeValueForKey(aKey);
|
|
|
|
else if (this.containsKey(aKey))
|
|
this.replaceValueForKey(aKey, aValue);
|
|
|
|
else
|
|
this.addValueForKey(aKey, aValue);
|
|
};
|
|
|
|
DISPLAY_NAME(CFMutableDictionary.prototype.setValueForKey);
|