mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-06 18:57:12 +00:00
Merge branch 'loader' of github.com:280north/cappuccino into loader
This commit is contained in:
@@ -55,6 +55,11 @@
|
||||
return [_array objectAtIndex:_index];
|
||||
}
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
return [_array countByEnumeratingWithState:aState objects:objects count:aCount];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* @ignore */
|
||||
@@ -1206,6 +1211,23 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPArray (CPFastEnumeration)
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
var count = [self count];
|
||||
|
||||
if (aState.state >= count)
|
||||
return 0;
|
||||
|
||||
aState.items = self;
|
||||
aState.state = count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPArray (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
|
||||
@@ -532,6 +532,31 @@
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPDictionary (CPFastEnumeration)
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
var count = [self count];
|
||||
|
||||
if (aState.state >= count)
|
||||
return 0;
|
||||
|
||||
var keys = [self allKeys],
|
||||
index = count,
|
||||
objects = [];
|
||||
|
||||
while (count--)
|
||||
objects[index] = [self objectForKey:keys[index]];
|
||||
|
||||
aState.items0 = objects;
|
||||
aState.items1 = keys;
|
||||
aState.state = count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@class CPMutableDictionary
|
||||
@ingroup compatability
|
||||
|
||||
@@ -56,4 +56,11 @@
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
// This is pretty terrible, but what do you expect.
|
||||
return [[self allObjects] countByEnumeratingWithState:aState objects:objects count:aCount];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -834,6 +834,30 @@ var CPIndexSetCountKey = @"CPIndexSetCountKey",
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPIndexSet (CPFastEnumeration)
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
var rangeIndex = aState.state;
|
||||
|
||||
if (aState.state >= _ranges.length)
|
||||
return 0;
|
||||
|
||||
var range = _ranges[rangeIndex],
|
||||
index = 0,
|
||||
start = range.location,
|
||||
end = CPMaxRange(range);
|
||||
|
||||
for (; start < end; ++start, ++index)
|
||||
objects[index] = start;
|
||||
|
||||
++aState.state;
|
||||
|
||||
return range.length;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@class CPMutableIndexSet
|
||||
@ingroup compatability
|
||||
|
||||
@@ -58,3 +58,12 @@ var CPNullSharedNull = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPNull (CPFastEnumeration)
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -499,6 +499,22 @@ var CPSetObjectsKey = @"CPSetObjectsKey";
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPSet (CPFastEnumeration)
|
||||
|
||||
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||
{
|
||||
var count = [self count];
|
||||
|
||||
if (aState.state >= count)
|
||||
return 0;
|
||||
|
||||
count = [[self allObjects] countByEnumeratingWithState:aState objects:objects count:aCount];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/*!
|
||||
@class CPMutableSet
|
||||
@ingroup compatability
|
||||
|
||||
+116
-15
@@ -29,10 +29,13 @@ var TOKEN_ACCESSORS = "accessors",
|
||||
TOKEN_FUNCTION = "function",
|
||||
TOKEN_IMPLEMENTATION = "implementation",
|
||||
TOKEN_IMPORT = "import",
|
||||
TOKEN_EACH = "each",
|
||||
TOKEN_NEW = "new",
|
||||
TOKEN_SELECTOR = "selector",
|
||||
TOKEN_SUPER = "super",
|
||||
|
||||
TOKEN_VAR = "var",
|
||||
TOKEN_IN = "in",
|
||||
|
||||
TOKEN_EQUAL = '=',
|
||||
TOKEN_PLUS = '+',
|
||||
TOKEN_MINUS = '-',
|
||||
@@ -52,7 +55,7 @@ var TOKEN_ACCESSORS = "accessors",
|
||||
TOKEN_QUESTION_MARK = '?',
|
||||
TOKEN_OPEN_PARENTHESIS = '(',
|
||||
TOKEN_CLOSE_PARENTHESIS = ')',
|
||||
|
||||
|
||||
TOKEN_WHITESPACE = /^(?:(?:\s+$)|(?:\/(?:\/|\*)))/,
|
||||
TOKEN_NUMBER = /^[+-]?\d+(([.]\d+)*([eE][+-]?\d+))?$/,
|
||||
TOKEN_IDENTIFIER = /^[a-zA-Z_$](\w|$)*$/;
|
||||
@@ -290,7 +293,7 @@ Preprocessor.prototype.directive = function(tokens, aStringBuffer, allowedDirect
|
||||
|
||||
// Currently we simply swallow forward declarations and only provide them to allow
|
||||
// compatibility with Objective-C files.
|
||||
else if (token == TOKEN_CLASS)
|
||||
else if (token === TOKEN_CLASS)
|
||||
{
|
||||
tokens.skip_whitespace();
|
||||
|
||||
@@ -298,24 +301,119 @@ Preprocessor.prototype.directive = function(tokens, aStringBuffer, allowedDirect
|
||||
}
|
||||
|
||||
// @implementation Class implementations
|
||||
else if (token == TOKEN_IMPLEMENTATION)
|
||||
else if (token === TOKEN_IMPLEMENTATION)
|
||||
this.implementation(tokens, buffer);
|
||||
|
||||
// @import
|
||||
else if (token == TOKEN_IMPORT)
|
||||
else if (token === TOKEN_IMPORT)
|
||||
this._import(tokens);
|
||||
|
||||
else if (token === TOKEN_EACH)
|
||||
this.each(tokens, buffer);
|
||||
|
||||
// @selector
|
||||
else if (token == TOKEN_SELECTOR)
|
||||
else if (token === TOKEN_SELECTOR)
|
||||
this.selector(tokens, buffer);
|
||||
|
||||
else if (token == TOKEN_ACCESSORS)
|
||||
else if (token === TOKEN_ACCESSORS)
|
||||
return this.accessors(tokens);
|
||||
|
||||
if (!aStringBuffer)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
var fastEnumeratorCount = 0;
|
||||
|
||||
Preprocessor.prototype.each = function(tokens, /*StringBuffer*/ aStringBuffer)
|
||||
{
|
||||
var token = tokens.skip_whitespace();
|
||||
|
||||
// If we reach an open parenthesis, we are declaring a category.
|
||||
if (token !== TOKEN_OPEN_PARENTHESIS)
|
||||
throw new SyntaxError(this.error_message("*** Expecting (, found: \"" + token + "\"."));
|
||||
|
||||
var identifiers = [],
|
||||
isVared = NO;
|
||||
|
||||
do
|
||||
{
|
||||
token = tokens.skip_whitespace();
|
||||
|
||||
if (identifiers.length === 0 && token === TOKEN_VAR)
|
||||
{
|
||||
isVared = YES;
|
||||
|
||||
token = tokens.skip_whitespace();
|
||||
}
|
||||
|
||||
if (!TOKEN_IDENTIFIER.test(token))
|
||||
throw new SyntaxError(this.error_message("*** Expecting identifier, found: \"" + token + "\"."));
|
||||
|
||||
identifiers.push(token);
|
||||
|
||||
token = tokens.skip_whitespace();
|
||||
|
||||
if (token !== TOKEN_COMMA && token !== TOKEN_IN)
|
||||
throw new SyntaxError(this.error_message("*** Expecting \",\", found: \"" + token + "\"."));
|
||||
|
||||
} while (token && token === TOKEN_COMMA);
|
||||
|
||||
if (token !== TOKEN_IN)
|
||||
throw new SyntaxError(this.error_message("*** Expecting \"in\", found: \"" + token + "\"."));
|
||||
|
||||
var generatedFastEnumeratorName = "$OBJJ_GENERATED_FAST_ENUMERATOR_" + fastEnumeratorCount++;
|
||||
|
||||
CONCAT(aStringBuffer, "var ");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, " = new objj_fastEnumerator(");
|
||||
|
||||
this.preprocess(tokens, aStringBuffer, TOKEN_CLOSE_PARENTHESIS, TOKEN_OPEN_PARENTHESIS);
|
||||
|
||||
CONCAT(aStringBuffer, ", ");
|
||||
CONCAT(aStringBuffer, identifiers.length);
|
||||
CONCAT(aStringBuffer, ");\n");
|
||||
|
||||
// for ([var] arg1[, arg2[, ... argN]], $E = new objj_fastEnumerator(expression);
|
||||
// $E.i < $E.l || $E.e() && ((arg1 = $E.o0[$E.i][, $E.o1[$E.i][, ... $E.oN[$E.i]]]) || YES);
|
||||
// ++$E.i)
|
||||
|
||||
CONCAT(aStringBuffer, "for (");
|
||||
|
||||
if (isVared)
|
||||
{
|
||||
CONCAT(aStringBuffer, "var ");
|
||||
CONCAT(aStringBuffer, identifiers.join(", "));
|
||||
}
|
||||
|
||||
CONCAT(aStringBuffer, ";(");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, ".i < ");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, ".l || ");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, ".e()) && ((");
|
||||
|
||||
// Man don't you wish we had fast enumeration here!!
|
||||
for (var index = 0, count = identifiers.length; index < count; ++index)
|
||||
{
|
||||
CONCAT(aStringBuffer, identifiers[index]);
|
||||
CONCAT(aStringBuffer, " = ");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, ".o");
|
||||
CONCAT(aStringBuffer, index);
|
||||
CONCAT(aStringBuffer, "[");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, ".i]");
|
||||
|
||||
if (index + 1 < count)
|
||||
CONCAT(aStringBuffer, ", ");
|
||||
}
|
||||
|
||||
CONCAT(aStringBuffer, ") || YES); ++");
|
||||
CONCAT(aStringBuffer, generatedFastEnumeratorName);
|
||||
CONCAT(aStringBuffer, ".i)");
|
||||
}
|
||||
|
||||
Preprocessor.prototype.implementation = function(tokens, /*StringBuffer*/ aStringBuffer)
|
||||
{
|
||||
var buffer = aStringBuffer,
|
||||
@@ -651,7 +749,7 @@ Preprocessor.prototype.preprocess = function(tokens, /*StringBuffer*/ aStringBuf
|
||||
closures = [0, 0, 0];
|
||||
}
|
||||
|
||||
while ((token = tokens.next()) && ((token != terminator) || count))
|
||||
while ((token = tokens.next()) && ((token !== terminator) || count))
|
||||
{
|
||||
if (tuple)
|
||||
{
|
||||
@@ -762,12 +860,12 @@ Preprocessor.prototype.preprocess = function(tokens, /*StringBuffer*/ aStringBuf
|
||||
}
|
||||
|
||||
if (instigator)
|
||||
{
|
||||
if (token == instigator)
|
||||
{
|
||||
if (token === instigator)
|
||||
++count;
|
||||
|
||||
else if (token == terminator)
|
||||
--count;
|
||||
|
||||
else if (token === terminator)
|
||||
--count;
|
||||
}
|
||||
|
||||
// Safari can't handle function declarations of the form function [name]([arguments]) { }
|
||||
@@ -778,13 +876,16 @@ Preprocessor.prototype.preprocess = function(tokens, /*StringBuffer*/ aStringBuf
|
||||
var accumulator = "";
|
||||
|
||||
// Following the function identifier we can either have an open parenthesis or an identifier:
|
||||
while((token = tokens.next()) && token != TOKEN_OPEN_PARENTHESIS && !(/^\w/).test(token))
|
||||
while((token = tokens.next()) && token !== TOKEN_OPEN_PARENTHESIS && !(/^\w/).test(token))
|
||||
accumulator += token;
|
||||
|
||||
|
||||
// If the next token is an open parenthesis, we have a standard function and we don't have to
|
||||
// change it:
|
||||
if (token === TOKEN_OPEN_PARENTHESIS)
|
||||
{
|
||||
if (instigator === TOKEN_OPEN_PARENTHESIS)
|
||||
++count;
|
||||
|
||||
CONCAT(buffer, "function" + accumulator + '(');
|
||||
|
||||
if (tuple)
|
||||
|
||||
@@ -534,6 +534,91 @@ function sel_registerName(aName)
|
||||
return aName;
|
||||
}
|
||||
|
||||
var fastEnumerationSelector = sel_getUid("countByEnumeratingWithState:objects:count:");
|
||||
|
||||
function objj_fastEnumerator(/*Object*/ anObject, /*Integer*/ anAssigneeCount)
|
||||
{
|
||||
// If this object doesn't respond to countByEnumeratingWithState:objects:count:
|
||||
// (which is obviously the case for non-Objective-J objects), then just iterate
|
||||
// this one object.
|
||||
if (anObject && (!anObject.isa || !class_getInstanceMethod(anObject.isa, fastEnumerationSelector)))
|
||||
this._target = [anObject];
|
||||
|
||||
// Else, use it's implementation.
|
||||
else
|
||||
this._target = anObject;
|
||||
|
||||
this._state = { state:0, assigneeCount:anAssigneeCount };
|
||||
this._index = 0;
|
||||
|
||||
// Nothing to iterate in this case.
|
||||
if (!anObject)
|
||||
{
|
||||
this.i = 0;
|
||||
this.l = 0;
|
||||
}
|
||||
else
|
||||
this.e();
|
||||
}
|
||||
|
||||
objj_fastEnumerator.prototype.e = function()
|
||||
{
|
||||
// Nothing to iterate, don't iterate
|
||||
if (!this._target)
|
||||
return NO;
|
||||
|
||||
var state = this._state,
|
||||
index = state.assigneeCount;
|
||||
|
||||
// Clear out all the old state.
|
||||
state.items = nil;
|
||||
state.itemsPtr = nil;
|
||||
|
||||
while (index--)
|
||||
state["items" + index] = nil;
|
||||
|
||||
this.o0 = [];
|
||||
this.i = 0;
|
||||
this.l = objj_msgSend(this._target, fastEnumerationSelector, state, this.o0, 10);
|
||||
|
||||
// We're flexible on this.
|
||||
this.o0 = state.items || state.itemsPtr || state.items0 || this.o0;
|
||||
|
||||
// We allow the user to not explictly return anything in countByEnumeratingWithState:objects:count:
|
||||
if (this.l === undefined)
|
||||
this.l = this.o0.length;
|
||||
|
||||
var assigneeCount = state.assigneeCount;
|
||||
|
||||
index = assigneeCount - 1;
|
||||
|
||||
// Handle all items from [1 .. assigneeCount - 1]
|
||||
while (index-- > 1)
|
||||
this["o" + index] = state["items" + index] || [];
|
||||
|
||||
var lastAssigneeIndex = assigneeCount - 1;
|
||||
|
||||
// Autogenerate the indexes if this was left blank.
|
||||
if (lastAssigneeIndex > 0)
|
||||
|
||||
if (state["items" + lastAssigneeIndex])
|
||||
this["o" + lastAssigneeIndex] = state["items" + lastAssigneeIndex];
|
||||
|
||||
else
|
||||
{
|
||||
var count = this.l,
|
||||
indexIndex = 0,
|
||||
indexes = new Array(count)
|
||||
|
||||
for (; indexIndex < count; ++indexIndex, ++this._index)
|
||||
indexes[indexIndex] = this._index;
|
||||
|
||||
this["o" + lastAssigneeIndex] = indexes;
|
||||
}
|
||||
|
||||
return this.l > 0;
|
||||
}
|
||||
|
||||
// Exports and Globals
|
||||
|
||||
exports.objj_ivar = objj_ivar;
|
||||
@@ -586,5 +671,7 @@ exports.sel_getUid = sel_getUid;
|
||||
exports.sel_isEqual = sel_isEqual;
|
||||
exports.sel_registerName = sel_registerName;
|
||||
|
||||
exports.objj_fastEnumerator = objj_fastEnumerator;
|
||||
|
||||
exports.objj_generateObjectUID = generateObjectUID;
|
||||
exports._objj_generateObjectHash = generateObjectUID;
|
||||
|
||||
Reference in New Issue
Block a user