summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-01-30 19:18:54 +0100
committerGeorg Brandl <georg@python.org>2010-01-30 19:18:54 +0100
commit8c9504600671ab4fe67dd8f90abcf2e23e56b9ac (patch)
tree22ecf0e0eaf95ff4c4253086df6fb51b98ff6f75
parent995e36cb8f5cdf9418587cc59b859da9e975fe28 (diff)
downloadpygments-8c9504600671ab4fe67dd8f90abcf2e23e56b9ac.tar.gz
Objective-J lexer: Clean up, regenerate mapping, add to CHANGES, add AUTHORS, and add test file to test suite.
-rw-r--r--AUTHORS2
-rw-r--r--CHANGES1
-rw-r--r--pygments/lexers/_mapping.py3
-rw-r--r--pygments/lexers/web.py77
-rwxr-xr-xtests/examplefiles/CPDictionary.j611
5 files changed, 661 insertions, 33 deletions
diff --git a/AUTHORS b/AUTHORS
index f717c320..f8a6adfe 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -11,6 +11,7 @@ Other contributors, listed alphabetically, are:
* Stefan Matthias Aust -- Smalltalk lexer
* Ben Bangert -- Mako lexers
* Max Battcher -- Darcs patch lexer
+* Paul Baumgart, 280 North, Inc. -- Objective-J lexer
* Michael Bayer -- Myghty lexers
* Jarrett Billingsley -- MiniD lexer
* Adam Blinkinsop -- Haskell, Redcode lexers
@@ -28,6 +29,7 @@ Other contributors, listed alphabetically, are:
* Matthew Harrison -- SVG formatter
* Steven Hazel -- Tcl lexer
* Aslak Hellesøy -- Gherkin lexer
+* David Hess, Fish Software, Inc. -- Objective-J lexer
* Varun Hiremath -- Debian control lexer
* Dennis Kaarsemaker -- sources.list lexer
* Marek Kubica -- Scheme lexer
diff --git a/CHANGES b/CHANGES
index 21406334..e239a632 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,7 @@ Version 1.3
* Coldfusion
* haXe
* R console
+ * Objective-J
Version 1.2.2
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py
index bd4b704e..8b02ca53 100644
--- a/pygments/lexers/_mapping.py
+++ b/pygments/lexers/_mapping.py
@@ -133,6 +133,7 @@ LEXERS = {
'NumPyLexer': ('pygments.lexers.math', 'NumPy', ('numpy',), (), ()),
'ObjdumpLexer': ('pygments.lexers.asm', 'objdump', ('objdump',), ('*.objdump',), ('text/x-objdump',)),
'ObjectiveCLexer': ('pygments.lexers.compiled', 'Objective-C', ('objective-c', 'objectivec', 'obj-c', 'objc'), ('*.m',), ('text/x-objective-c',)),
+ 'ObjectiveJLexer': ('pygments.lexers.web', 'Objective-J', ('objective-j', 'objectivej', 'obj-j', 'objj'), ('*.j',), ('text/x-objective-j',)),
'OcamlLexer': ('pygments.lexers.compiled', 'OCaml', ('ocaml',), ('*.ml', '*.mli', '*.mll', '*.mly'), ('text/x-ocaml',)),
'OcamlLexer': ('pygments.lexers.functional', 'OCaml', ('ocaml',), ('*.ml', '*.mli', '*.mll', '*.mly'), ('text/x-ocaml',)),
'OocLexer': ('pygments.lexers.compiled', 'Ooc', ('ooc',), ('*.ooc',), ('text/x-ooc',)),
@@ -143,7 +144,7 @@ LEXERS = {
'Python3Lexer': ('pygments.lexers.agile', 'Python 3', ('python3', 'py3'), (), ('text/x-python3', 'application/x-python3')),
'Python3TracebackLexer': ('pygments.lexers.agile', 'Python 3.0 Traceback', ('py3tb',), ('*.py3tb',), ('text/x-python3-traceback',)),
'PythonConsoleLexer': ('pygments.lexers.agile', 'Python console session', ('pycon',), (), ('text/x-python-doctest',)),
- 'PythonLexer': ('pygments.lexers.agile', 'Python', ('python', 'py'), ('*.py', '*.pyw', '*.sc', 'SConstruct', 'SConscript'), ('text/x-python', 'application/x-python')),
+ 'PythonLexer': ('pygments.lexers.agile', 'Python', ('python', 'py'), ('*.py', '*.pyw', '*.sc', 'SConstruct', 'SConscript', '*.tac'), ('text/x-python', 'application/x-python')),
'PythonTracebackLexer': ('pygments.lexers.agile', 'Python Traceback', ('pytb',), ('*.pytb',), ('text/x-python-traceback',)),
'RConsoleLexer': ('pygments.lexers.math', 'RConsole', ('rconsole', 'rout'), ('*.Rout',), ()),
'RagelCLexer': ('pygments.lexers.parsers', 'Ragel in C Host', ('ragel-c',), ('*.rl',), ()),
diff --git a/pygments/lexers/web.py b/pygments/lexers/web.py
index 90278cc5..49b12996 100644
--- a/pygments/lexers/web.py
+++ b/pygments/lexers/web.py
@@ -24,7 +24,7 @@ from pygments.util import get_bool_opt, get_list_opt, looks_like_xml, \
__all__ = ['HtmlLexer', 'XmlLexer', 'JavascriptLexer', 'CssLexer',
'PhpLexer', 'ActionScriptLexer', 'XsltLexer', 'ActionScript3Lexer',
- 'MxmlLexer', 'HaxeLexer']
+ 'MxmlLexer', 'HaxeLexer', 'ObjectiveJLexer']
class JavascriptLexer(RegexLexer):
@@ -393,6 +393,8 @@ class CssLexer(RegexLexer):
class ObjectiveJLexer(RegexLexer):
"""
For Objective-J source code with preprocessor directives.
+
+ *New in Pygments 1.3.*
"""
name = 'Objective-J'
@@ -406,13 +408,13 @@ class ObjectiveJLexer(RegexLexer):
flags = re.DOTALL | re.MULTILINE
tokens = {
- 'root': [
+ 'root': [
include('whitespace'),
# function definition
(r'^(' + _ws + r'[\+-]' + _ws + r')([\(a-zA-Z_].*?[^\(])(' + _ws + '{)',
- bygroups(using(this), using(this, state='function_signature'), using(this))),
-
+ bygroups(using(this), using(this, state='function_signature'),
+ using(this))),
# class definition
(r'(@interface|@implementation)(\s+)', bygroups(Keyword, Text),
@@ -423,14 +425,18 @@ class ObjectiveJLexer(RegexLexer):
include('statements'),
('[{\(\)}]', Punctuation),
- (';', Punctuation)
+ (';', Punctuation),
],
'whitespace': [
- (r'(@import)(\s+)("(\\\\|\\"|[^"])*")', bygroups(Comment.Preproc, Text, String.Double)),
- (r'(@import)(\s+)(<(\\\\|\\>|[^>])*>)', bygroups(Comment.Preproc, Text, String.Double)),
- (r'(#(?:include|import))(\s+)("(\\\\|\\"|[^"])*")', bygroups(Comment.Preproc, Text, String.Double)),
- (r'(#(?:include|import))(\s+)(<(\\\\|\\>|[^>])*>)', bygroups(Comment.Preproc, Text, String.Double)),
-
+ (r'(@import)(\s+)("(\\\\|\\"|[^"])*")',
+ bygroups(Comment.Preproc, Text, String.Double)),
+ (r'(@import)(\s+)(<(\\\\|\\>|[^>])*>)',
+ bygroups(Comment.Preproc, Text, String.Double)),
+ (r'(#(?:include|import))(\s+)("(\\\\|\\"|[^"])*")',
+ bygroups(Comment.Preproc, Text, String.Double)),
+ (r'(#(?:include|import))(\s+)(<(\\\\|\\>|[^>])*>)',
+ bygroups(Comment.Preproc, Text, String.Double)),
+
(r'#if\s+0', Comment.Preproc, 'if0'),
(r'#', Comment.Preproc, 'macro'),
@@ -446,14 +452,15 @@ class ObjectiveJLexer(RegexLexer):
(r'/(\\.|[^[/\\\n]|\[(\\.|[^\]\\\n])*])+/'
r'([gim]+\b|\B)', String.Regex, '#pop'),
(r'(?=/)', Text, ('#pop', 'badregex')),
- (r'', Text, '#pop')
+ (r'', Text, '#pop'),
],
'badregex': [
- ('\n', Text, '#pop')
+ ('\n', Text, '#pop'),
],
'statements': [
(r'(L|@)?"', String, 'string'),
- (r"(L|@)?'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])'", String.Char),
+ (r"(L|@)?'(\\.|\\[0-7]{1,3}|\\x[a-fA-F0-9]{1,2}|[^\\\'\n])'",
+ String.Char),
(r'"(\\\\|\\"|[^"])*"', String.Double),
(r"'(\\\\|\\'|[^'])*'", String.Single),
(r'(\d+\.\d*|\.\d+|\d+)[eE][+-]?\d+[lL]?', Number.Float),
@@ -465,29 +472,32 @@ class ObjectiveJLexer(RegexLexer):
(r'^(?=\s|/|<!--)', Text, 'slashstartsregex'),
(r'\+\+|--|~|&&|\?|:|\|\||\\(?=\n)|'
- r'(<<|>>>?|==?|!=?|[-<>+*%&\|\^/])=?', Operator, 'slashstartsregex'),
+ r'(<<|>>>?|==?|!=?|[-<>+*%&\|\^/])=?',
+ Operator, 'slashstartsregex'),
(r'[{(\[;,]', Punctuation, 'slashstartsregex'),
(r'[})\].]', Punctuation),
- (r'(for|in|while|do|break|return|continue|switch|case|default|if|else|'
- r'throw|try|catch|finally|new|delete|typeof|instanceof|void'
- r'|prototype|__proto__)\b', Keyword, 'slashstartsregex'),
+ (r'(for|in|while|do|break|return|continue|switch|case|default|if|'
+ r'else|throw|try|catch|finally|new|delete|typeof|instanceof|void|'
+ r'prototype|__proto__)\b', Keyword, 'slashstartsregex'),
(r'(var|with|function)\b', Keyword.Declaration, 'slashstartsregex'),
-
+
(r'(@selector|@private|@protected|@public|@encode|'
r'@synchronized|@try|@throw|@catch|@finally|@end|@property|'
r'@synthesize|@dynamic|@for|@accessors|new)\b', Keyword),
(r'(int|long|float|short|double|char|unsigned|signed|void|'
- r'id|BOOL|bool|boolean|IBOutlet|IBAction|SEL|@outlet|@action)\b', Keyword.Type),
+ r'id|BOOL|bool|boolean|IBOutlet|IBAction|SEL|@outlet|@action)\b',
+ Keyword.Type),
(r'(self|super)\b', Name.Builtin),
(r'(TRUE|YES|FALSE|NO|Nil|nil|NULL)\b', Keyword.Constant),
(r'(true|false|null|NaN|Infinity|undefined)\b', Keyword.Constant),
- (r'(ABS|ASIN|ACOS|ATAN|ATAN2|SIN|COS|TAN|EXP|POW|CEIL|FLOOR|ROUND|MIN|MAX'
- r'RAND|SQRT|E|LN2|LN10|LOG2E|LOG10E|PI|PI2|PI_2|SQRT1_2|SQRT2)\b', Keyword.Constant),
+ (r'(ABS|ASIN|ACOS|ATAN|ATAN2|SIN|COS|TAN|EXP|POW|CEIL|FLOOR|ROUND|'
+ r'MIN|MAX|RAND|SQRT|E|LN2|LN10|LOG2E|LOG10E|PI|PI2|PI_2|SQRT1_2|'
+ r'SQRT2)\b', Keyword.Constant),
(r'(Array|Boolean|Date|Error|Function|Math|netscape|'
r'Number|Object|Packages|RegExp|String|sun|decodeURI|'
@@ -495,25 +505,27 @@ class ObjectiveJLexer(RegexLexer):
r'Error|eval|isFinite|isNaN|parseFloat|parseInt|document|this|'
r'window)\b', Name.Builtin),
- (r'([$a-zA-Z_][a-zA-Z0-9_]*)(' + _ws + r')(?=\()', bygroups(Name.Function, using(this))),
+ (r'([$a-zA-Z_][a-zA-Z0-9_]*)(' + _ws + r')(?=\()',
+ bygroups(Name.Function, using(this))),
(r'[$a-zA-Z_][a-zA-Z0-9_]*', Name),
],
'classname' : [
# interface definition that inherits
- (r'([a-zA-Z_][a-zA-Z0-9_]*)(' + _ws + r':' + _ws + r')([a-zA-Z_][a-zA-Z0-9_]*)?',
+ (r'([a-zA-Z_][a-zA-Z0-9_]*)(' + _ws + r':' + _ws +
+ r')([a-zA-Z_][a-zA-Z0-9_]*)?',
bygroups(Name.Class, using(this), Name.Class), '#pop'),
# interface definition for a category
(r'([a-zA-Z_][a-zA-Z0-9_]*)(' + _ws + r'\()([a-zA-Z_][a-zA-Z0-9_]*)(\))',
bygroups(Name.Class, using(this), Name.Label, Text), '#pop'),
# simple interface / implementation
- (r'([a-zA-Z_][a-zA-Z0-9_]*)', Name.Class, '#pop')
+ (r'([a-zA-Z_][a-zA-Z0-9_]*)', Name.Class, '#pop'),
],
'forward_classname' : [
(r'([a-zA-Z_][a-zA-Z0-9_]*)(\s*,\s*)',
bygroups(Name.Class, Text), '#push'),
(r'([a-zA-Z_][a-zA-Z0-9_]*)(\s*;?)',
- bygroups(Name.Class, Text), '#pop')
+ bygroups(Name.Class, Text), '#pop'),
],
'function_signature': [
include('whitespace'),
@@ -533,7 +545,7 @@ class ObjectiveJLexer(RegexLexer):
r'([$a-zA-Z_][a-zA-Z0-9_]+)', # function name
bygroups(using(this), Keyword.Type, using(this),
Name.Function), "#pop"),
-
+
# no return type given, start of a selector w/ parameters
(r'([$a-zA-Z_][a-zA-Z0-9_]+' + _ws + r':)', # function name
bygroups (Name.Function), 'function_parameters'),
@@ -542,7 +554,6 @@ class ObjectiveJLexer(RegexLexer):
(r'([$a-zA-Z_][a-zA-Z0-9_]+)', # function name
bygroups(Name.Function), "#pop"),
-
('', Text, '#pop'),
],
'function_parameters': [
@@ -565,11 +576,13 @@ class ObjectiveJLexer(RegexLexer):
# var args
(r'(,' + _ws + r'...)', using(this)),
- (r'([$a-zA-Z_][a-zA-Z0-9_]+)', Text)# param name
+ # param name
+ (r'([$a-zA-Z_][a-zA-Z0-9_]+)', Text),
],
'expression' : [
- (r'([$a-zA-Z_][a-zA-Z0-9_]*)(\()', bygroups(Name.Function, Punctuation)),
- (r'(\))', Punctuation, "#pop")
+ (r'([$a-zA-Z_][a-zA-Z0-9_]*)(\()', bygroups(Name.Function,
+ Punctuation)),
+ (r'(\))', Punctuation, "#pop"),
],
'string': [
(r'"', String, '#pop'),
@@ -594,7 +607,8 @@ class ObjectiveJLexer(RegexLexer):
}
def analyse_text(text):
- if re.match('^\s*@import\s+[<"]', text, re.MULTILINE): # special directive found in most Objective-J files
+ if re.search('^\s*@import\s+[<"]', text, re.MULTILINE):
+ # special directive found in most Objective-J files
return True
return False
@@ -889,7 +903,6 @@ class XsltLexer(XmlLexer):
return 0.8
-
class MxmlLexer(RegexLexer):
"""
For MXML markup.
diff --git a/tests/examplefiles/CPDictionary.j b/tests/examplefiles/CPDictionary.j
new file mode 100755
index 00000000..50243f1d
--- /dev/null
+++ b/tests/examplefiles/CPDictionary.j
@@ -0,0 +1,611 @@
+/*
+ * CPDictionary.j
+ * Foundation
+ *
+ * Created by Francisco Tolmasky.
+ * Copyright 2008, 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
+ */
+
+//@import "CPRange.j"
+@import "CPObject.j"
+@import "CPEnumerator.j"
+@import "CPException.j"
+
+/* @ignore */
+@implementation _CPDictionaryValueEnumerator : CPEnumerator
+{
+ CPEnumerator _keyEnumerator;
+ CPDictionary _dictionary;
+}
+
+- (id)initWithDictionary:(CPDictionary)aDictionary
+{
+ self = [super init];
+
+ if (self)
+ {
+ _keyEnumerator = [aDictionary keyEnumerator];
+ _dictionary = aDictionary;
+ }
+
+ return self;
+}
+
+- (id)nextObject
+{
+ var key = [_keyEnumerator nextObject];
+
+ if (!key)
+ return nil;
+
+ return [_dictionary objectForKey:key];
+}
+
+@end
+
+/*!
+ @class CPDictionary
+ @ingroup foundation
+ @brief A mutable key-value pair collection.
+
+ A dictionary is the standard way of passing around key-value pairs in
+ the Cappuccino framework. It is similar to the
+ <a href="http://java.sun.com/javase/6/docs/api/index.html">Java map interface</a>,
+ except all keys are CPStrings and values can be any
+ Cappuccino or JavaScript object.
+
+ If you are familiar with dictionaries in Cocoa, you'll notice that
+ there is no CPMutableDictionary class. The regular CPDictionary
+ has \c -setObject:forKey: and \c -removeObjectForKey: methods.
+ In Cappuccino there is no distinction between immutable and mutable classes.
+ They are all mutable.
+*/
+@implementation CPDictionary : CPObject
+{
+}
+
+/*
+ @ignore
+*/
++ (id)alloc
+{
+ return new objj_dictionary();
+}
+
+/*!
+ Returns a new empty CPDictionary.
+*/
++ (id)dictionary
+{
+ return [[self alloc] init];
+}
+
+/*!
+ Returns a new dictionary, initialized with the contents of \c aDictionary.
+ @param aDictionary the dictionary to copy key-value pairs from
+ @return the new CPDictionary
+*/
++ (id)dictionaryWithDictionary:(CPDictionary)aDictionary
+{
+ return [[self alloc] initWithDictionary:aDictionary];
+}
+
+/*!
+ Creates a new dictionary with single key-value pair.
+ @param anObject the object for the paring
+ @param aKey the key for the pairing
+ @return the new CPDictionary
+*/
++ (id)dictionaryWithObject:(id)anObject forKey:(id)aKey
+{
+ return [[self alloc] initWithObjects:[anObject] forKeys:[aKey]];
+}
+
+/*!
+ Creates a dictionary with multiple key-value pairs.
+ @param objects the objects to place in the dictionary
+ @param keys the keys for each of the objects
+ @throws CPInvalidArgumentException if the number of objects and keys is different
+ @return the new CPDictionary
+*/
++ (id)dictionaryWithObjects:(CPArray)objects forKeys:(CPArray)keys
+{
+ return [[self alloc] initWithObjects:objects forKeys:keys];
+}
+
+/*!
+ Creates a dictionary with multiple key-value pairs.
+ @param JavaScript object
+ @return the new CPDictionary
+*/
++ (id)dictionaryWithJSObject:(JSObject)object
+{
+ return [self dictionaryWithJSObject:object recursively:NO];
+}
+
+/*!
+ Creates a dictionary with multiple key-value pairs, recursively.
+ @param JavaScript object
+ @return the new CPDictionary
+*/
++ (id)dictionaryWithJSObject:(JSObject)object recursively:(BOOL)recursively
+{
+ var dictionary = [[self alloc] init];
+
+ for (var key in object)
+ {
+ var value = object[key];
+
+ if (recursively && value.constructor === Object)
+ value = [CPDictionary dictionaryWithJSObject:value recursively:YES];
+
+ [dictionary setObject:value forKey:key];
+ }
+
+ return dictionary;
+}
+
+/*!
+ Creates and returns a dictionary constructed by a given pairs of keys and values.
+ @param firstObject first object value
+ @param ... key for the first object and ongoing value-key pairs for more objects.
+ @throws CPInvalidArgumentException if the number of objects and keys is different
+ @return the new CPDictionary
+
+ Assuming that there's no object retaining in Cappuccino, you can create
+ dictionaries same way as with alloc and initWithObjectsAndKeys:
+ var dict = [CPDictionary dictionaryWithObjectsAndKeys:
+ @"value1", @"key1",
+ @"value2", @"key2"];
+
+ Note, that there's no final nil like in Objective-C/Cocoa.
+
+ @see [CPDictionary initWithObjectsAndKeys:]
+*/
++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...
+{
+ arguments[0] = [self alloc];
+ arguments[1] = @selector(initWithObjectsAndKeys:);
+
+ return objj_msgSend.apply(this, arguments);
+}
+
+/*!
+ Initializes the dictionary with the contents of another dictionary.
+ @param aDictionary the dictionary to copy key-value pairs from
+ @return the initialized dictionary
+*/
+- (id)initWithDictionary:(CPDictionary)aDictionary
+{
+ var key = "",
+ dictionary = [[CPDictionary alloc] init];
+
+ for (key in aDictionary._buckets)
+ [dictionary setObject:[aDictionary objectForKey:key] forKey:key];
+
+ return dictionary;
+}
+
+/*!
+ Initializes the dictionary from the arrays of keys and objects.
+ @param objects the objects to put in the dictionary
+ @param keyArray the keys for the objects to put in the dictionary
+ @throws CPInvalidArgumentException if the number of objects and keys is different
+ @return the initialized dictionary
+*/
+- (id)initWithObjects:(CPArray)objects forKeys:(CPArray)keyArray
+{
+ self = [super init];
+
+ if ([objects count] != [keyArray count])
+ [CPException raise:CPInvalidArgumentException reason:"Counts are different.("+[objects count]+"!="+[keyArray count]+")"];
+
+ if (self)
+ {
+ var i = [keyArray count];
+
+ while (i--)
+ [self setObject:objects[i] forKey:keyArray[i]];
+ }
+
+ return self;
+}
+
+/*!
+ Creates and returns a dictionary constructed by a given pairs of keys and values.
+ @param firstObject first object value
+ @param ... key for the first object and ongoing value-key pairs for more objects.
+ @throws CPInvalidArgumentException if the number of objects and keys is different
+ @return the new CPDictionary
+
+ You can create dictionaries this way:
+ var dict = [[CPDictionary alloc] initWithObjectsAndKeys:
+ @"value1", @"key1",
+ @"value2", @"key2"];
+
+ Note, that there's no final nil like in Objective-C/Cocoa.
+*/
+- (id)initWithObjectsAndKeys:(id)firstObject, ...
+{
+ var argCount = arguments.length;
+
+ if (argCount % 2 !== 0)
+ [CPException raise:CPInvalidArgumentException reason:"Key-value count is mismatched. (" + argCount + " arguments passed)"];
+
+ self = [super init];
+
+ if (self)
+ {
+ // The arguments array contains self and _cmd, so the first object is at position 2.
+ var index = 2;
+
+ for(; index < argCount; index += 2)
+ {
+ var value = arguments[index];
+
+ if (value === nil)
+ break;
+
+ [self setObject:value forKey:arguments[index + 1]];
+ }
+ }
+
+ return self;
+}
+
+/*!
+ return a copy of the receiver (does not deep copy the objects contained in the dictionary).
+*/
+- (CPDictionary)copy
+{
+ return [CPDictionary dictionaryWithDictionary:self];
+}
+
+/*!
+ Returns the number of entries in the dictionary
+*/
+- (int)count
+{
+ return count;
+}
+
+/*!
+ Returns an array of keys for all the entries in the dictionary.
+*/
+- (CPArray)allKeys
+{
+ return _keys;
+}
+
+/*!
+ Returns an array of values for all the entries in the dictionary.
+*/
+- (CPArray)allValues
+{
+ var index = _keys.length,
+ values = [];
+
+ while (index--)
+ values.push(dictionary_getValue(self, [_keys[index]]));
+
+ return values;
+}
+
+/*!
+ Returns an enumerator that enumerates over all the dictionary's keys.
+*/
+- (CPEnumerator)keyEnumerator
+{
+ return [_keys objectEnumerator];
+}
+
+/*!
+ Returns an enumerator that enumerates over all the dictionary's values.
+*/
+- (CPEnumerator)objectEnumerator
+{
+ return [[_CPDictionaryValueEnumerator alloc] initWithDictionary:self];
+}
+
+/*!
+ Compare the receiver to this dictionary, and return whether or not they are equal.
+*/
+- (BOOL)isEqualToDictionary:(CPDictionary)aDictionary
+{
+ if (count !== [aDictionary count])
+ return NO;
+
+ var index = count;
+ while (index--)
+ {
+ var currentKey = _keys[index],
+ lhsObject = _buckets[currentKey],
+ rhsObject = aDictionary._buckets[currentKey];
+
+ if (lhsObject === rhsObject)
+ continue;
+
+ if (lhsObject.isa && rhsObject.isa && [lhsObject respondsToSelector:@selector(isEqual:)] && [lhsObject isEqual:rhsObject])
+ continue;
+
+ return NO;
+ }
+
+ return YES;
+}
+
+/*
+ Instance.isEqualToDictionary(aDictionary)
+ {
+ if(this.count()!=aDictionary.count()) return NO;
+
+ var i= this._keys.count();
+ while(i--) if(this.objectForKey(this._keys[i])!=aDictionary.objectForKey(this._keys[i])) return NO;
+
+ return YES;
+ }
+
+ Instance.allKeys()
+ {
+ return this._keys;
+ }
+
+ Instance.allKeysForObject(anObject)
+ {
+ var i= 0,
+ keys= CPArray.array(),
+ count= this.count();
+
+ while((i= this._objects.indexOfObjectInRage(0, count-i))!=CPNotFound) keys.addObject(this._keys[i]);
+
+ return keys;
+ }
+
+ Instance.allValues()
+ {
+ return this._objects;
+ }
+
+ Instance.keyEnumerator()
+ {
+ return this._keys.objectEnumerator();
+ }
+
+ Instance.keysSortedByValueUsingSelector(aSelector)
+ {
+ var dictionary= this,
+ objectSelector= function(rhs)
+ {
+ return aSelector.apply(dictionary.objectForKey(this), [dictionary.objectForKey(rhs)]);
+ };
+
+ return this._keys.sortedArrayUsingSelector(objectSelector);
+ }
+
+ Instance.objectEnumerator()
+ {
+ return this._objects.objectEnumerator();
+ }
+*/
+/*!
+ Returns the object for the entry with key \c aKey.
+ @param aKey the key for the object's entry
+ @return the object for the entry
+*/
+- (id)objectForKey:(CPString)aKey
+{
+ var object = _buckets[aKey];
+
+ return (object === undefined) ? nil : object;
+}
+/*
+ Instance.objectsForKeys(keys, aNotFoundMarker)
+ {
+ var i= keys.length,
+ objects= CPArray.array();
+
+ while(i--)
+ {
+ var object= this.objectForKey(keys[i]);
+ objects.addObject(object==nil?aNotFoundMarker:object);
+ }
+
+ return objects;
+ }
+
+ Instance.valueForKey(aKey)
+ {
+ if(aKey.length && aKey[0]=="@") return this.objectForKey(aKey.substr(1));
+
+ return base.valueForKey(aKey);
+ }
+
+ //
+
+ Instance.addEntriesFromDictionary(aDictionary)
+ {
+ var key,
+ keyEnumerator= aDictionary.keyEnumerator();
+
+ while(key= keyEnumerator.nextObject()) this.setObjectForKey(aDictionary.objectForKey(key), key);
+ }
+*/
+/*!
+ Removes all the entries from the dictionary.
+*/
+- (void)removeAllObjects
+{
+ _keys = [];
+ count = 0;
+ _buckets = {};
+}
+
+/*!
+ Removes the entry for the specified key.
+ @param aKey the key of the entry to be removed
+*/
+- (void)removeObjectForKey:(id)aKey
+{
+ dictionary_removeValue(self, aKey);
+}
+
+/*!
+ Removes each entry in allKeys from the receiver.
+ @param allKeys an array of keys that will be removed from the dictionary
+*/
+- (void)removeObjectsForKeys:(CPArray)allKeys
+{
+ var index = allKeys.length;
+
+ while (index--)
+ dictionary_removeValue(self, allKeys[index]);
+}
+
+/*
+ Instance.removeObjectForKey(aKey)
+ {
+ var entry= this._dictionary[aKey];
+
+ if(entry)
+ {
+ var range= CPMakeRange(entry.index, 1);
+
+ this._keys.removeObjectsInRange(range);
+ this._objects.removeObjectsInRange(range);
+
+ delete this._dictionary[aKey];
+ }
+ }
+
+ Instance.setDictionary(aDictionary)
+ {
+ this._keys= CPArray.arrayWithArray(aDictionary.allKeys());
+ this._objects= CPArray.arrayWithArray(aDictionary.allValues());
+
+ this._dictionary= { };
+
+ var i= this._keys.count();
+ while(i--) this._dictionary[this._keys[i]]= { object: this._objects[i], index: i };
+ }
+*/
+/*!
+ Adds an entry into the dictionary.
+ @param anObject the object for the entry
+ @param aKey the entry's key
+*/
+- (void)setObject:(id)anObject forKey:(id)aKey
+{
+ dictionary_setValue(self, aKey, anObject);
+}
+/*
+ Instance.setValueForKey(aValue, aKey)
+ {
+ if(!aValue) this.removeObjectForKey(aKey);
+ else this.setObjectForKey(aValue, aKey);
+ }
+
+ Instance.copy()
+ {
+ return CPDictionary.alloc().dictionaryWithDictionary(this);
+ }
+*/
+
+/*!
+ Take all the key/value pairs in aDictionary and apply them to this dictionary.
+*/
+- (void)addEntriesFromDictionary:(CPDictionary)aDictionary
+{
+ if (!aDictionary)
+ return;
+
+ var keys = [aDictionary allKeys],
+ index = [keys count];
+
+ while (index--)
+ {
+ var key = keys[index];
+
+ [self setObject:[aDictionary objectForKey:key] forKey:key];
+ }
+}
+
+/*!
+ Returns a human readable description of the dictionary.
+*/
+- (CPString)description
+{
+ var description = @"CPDictionary {\n";
+
+ var i = _keys.length;
+
+ while (i--)
+ {
+ description += _keys[i] + ":";
+
+ var object = _buckets[_keys[i]];
+
+ if (object && object.isa)
+ description += [object description];
+ else
+ description += object;
+
+ description += "\n";
+ }
+
+ description += "}";
+
+ return description;
+}
+
+@end
+
+@implementation CPDictionary (CPCoding)
+
+/*
+ Initializes the dictionary by unarchiving the data from a coder.
+ @param aCoder the coder from which the data will be unarchived.
+ @return the initialized dictionary
+*/
+- (id)initWithCoder:(CPCoder)aCoder
+{
+ return [aCoder _decodeDictionaryOfObjectsForKey:@"CP.objects"];
+}
+
+/*!
+ Archives the dictionary to a provided coder.
+ @param aCoder the coder to which the dictionary data will be archived.
+*/
+- (void)encodeWithCoder:(CPCoder)aCoder
+{
+ [aCoder _encodeDictionaryOfObjects:self forKey:@"CP.objects"];
+}
+
+@end
+
+/*!
+ @class CPMutableDictionary
+ @ingroup compatability
+
+ This class is just an empty subclass of CPDictionary.
+ CPDictionary already implements mutable methods and
+ this class only exists for source compatability.
+*/
+@implementation CPMutableDictionary : CPDictionary
+
+@end
+
+objj_dictionary.prototype.isa = CPDictionary;