diff options
author | Georg Brandl <georg@python.org> | 2010-01-30 19:18:54 +0100 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2010-01-30 19:18:54 +0100 |
commit | 8c9504600671ab4fe67dd8f90abcf2e23e56b9ac (patch) | |
tree | 22ecf0e0eaf95ff4c4253086df6fb51b98ff6f75 | |
parent | 995e36cb8f5cdf9418587cc59b859da9e975fe28 (diff) | |
download | pygments-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-- | AUTHORS | 2 | ||||
-rw-r--r-- | CHANGES | 1 | ||||
-rw-r--r-- | pygments/lexers/_mapping.py | 3 | ||||
-rw-r--r-- | pygments/lexers/web.py | 77 | ||||
-rwxr-xr-x | tests/examplefiles/CPDictionary.j | 611 |
5 files changed, 661 insertions, 33 deletions
@@ -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 @@ -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; |