mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-09 20:27:13 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80097ea2a2 | ||
|
|
ea7257c00d | ||
|
|
2f0de57c92 | ||
|
|
bb659e3c06 | ||
|
|
3c98ed78ee | ||
|
|
458481af4e |
@@ -87,6 +87,40 @@
|
|||||||
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
|
[_childNodes[count] sortWithSortDescriptors:sortDescriptors recursively:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (CPEnumerator)preOrder
|
||||||
|
{
|
||||||
|
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorPreOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CPEnumerator)inOrder
|
||||||
|
{
|
||||||
|
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorInOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CPEnumerator)postOrder
|
||||||
|
{
|
||||||
|
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorPostOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CPEnumerator)levelOrder
|
||||||
|
{
|
||||||
|
return [_CPTreeNodeEnumerator enumeratorWithTreeNode:self order:_CPTreeNodeEnumeratorLevelOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||||
|
{
|
||||||
|
if (aState.state !== 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// FIXME: Change this to inorder when implemented?
|
||||||
|
var count = [[self preOrder] countByEnumeratingWithState:aState objects:objects count:aCount];
|
||||||
|
|
||||||
|
// Dangerous?
|
||||||
|
aState.state = YES;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
|
var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
|
||||||
@@ -117,3 +151,166 @@ var CPTreeNodeRepresentedObjectKey = @"CPTreeNodeRepresentedObjectKey",
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
var _CPTreeNodeEnumeratorPreOrder = 0,
|
||||||
|
_CPTreeNodeEnumeratorInOrder = 1,
|
||||||
|
_CPTreeNodeEnumeratorPostOrder = 2,
|
||||||
|
_CPTreeNodeEnumeratorLevelOrder = 3;
|
||||||
|
|
||||||
|
@implementation _CPTreeNodeEnumerator : CPEnumerator
|
||||||
|
{
|
||||||
|
int _order;
|
||||||
|
Object _state;
|
||||||
|
CPTreeNode _treeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (_CPTreeNodeEnumerator)enumeratorWithTreeNode:(CPTreeNode)aTreeNode order:(int)anOrder
|
||||||
|
{
|
||||||
|
return [[self alloc] initWithTreeNode:aTreeNode order:anOrder];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithTreeNode:(CPTreeNode)aTreeNode order:(int)anOrder
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self)
|
||||||
|
{
|
||||||
|
_order = anOrder
|
||||||
|
_state = [self _newState];
|
||||||
|
_treeNode = aTreeNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)_newState
|
||||||
|
{
|
||||||
|
return { stack:[_treeNode], visited:[CPSet set] };
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)_preOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
|
||||||
|
{
|
||||||
|
var stack = state.stack;
|
||||||
|
|
||||||
|
if (stack.length <= 0)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
if (shouldReturnAllObjects)
|
||||||
|
var allObjects = [];
|
||||||
|
|
||||||
|
while (stack.length)
|
||||||
|
{
|
||||||
|
var currentNode = stack.pop(),
|
||||||
|
childNodes = currentNode._childNodes,
|
||||||
|
count = childNodes.length;
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
stack.push(childNodes[count]);
|
||||||
|
|
||||||
|
if (shouldReturnAllObjects)
|
||||||
|
allObjects.push(currentNode);
|
||||||
|
else
|
||||||
|
return currentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return allObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)_inOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
|
||||||
|
{
|
||||||
|
// Implement.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)_postOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
|
||||||
|
{
|
||||||
|
var stack = state.stack;
|
||||||
|
|
||||||
|
if (stack.length <= 0)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
var visited = state.visited;
|
||||||
|
|
||||||
|
if (shouldReturnAllObjects)
|
||||||
|
var allObjects = [];
|
||||||
|
|
||||||
|
while (stack.length)
|
||||||
|
{
|
||||||
|
var currentNode = [stack lastObject],
|
||||||
|
childNodes = currentNode._childNodes,
|
||||||
|
originalCount = stack.length,
|
||||||
|
count = childNodes.length;
|
||||||
|
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
var treeNode = childNodes[count];
|
||||||
|
|
||||||
|
if ([visited containsObject:treeNode])
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
stack.push(treeNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalCount === stack.length)
|
||||||
|
{
|
||||||
|
[visited addObject:currentNode];
|
||||||
|
|
||||||
|
if (shouldReturnAllObjects)
|
||||||
|
allObjects.push(stack.pop());
|
||||||
|
else
|
||||||
|
return stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)_levelOrderFromState:(Object)state allObjects:(BOOL)shouldReturnAllObjects
|
||||||
|
{
|
||||||
|
// Implement.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)nextObject
|
||||||
|
{
|
||||||
|
if (_order === _CPTreeNodeEnumeratorPreOrder)
|
||||||
|
return [self _preOrderFromState:[self _newState] allObjects:NO];
|
||||||
|
|
||||||
|
else if (_order === _CPTreeNodeEnumeratorInOrder)
|
||||||
|
return [self _inOrderFromState:[self _newState] allObjects:NO];
|
||||||
|
|
||||||
|
else if (_order === _CPTreeNodeEnumeratorPostOrder)
|
||||||
|
return [self _postOrderFromState:[self _newState] allObjects:NO];
|
||||||
|
|
||||||
|
//else if (_order === _CPTreeNodeEnumeratorLevelOrder)
|
||||||
|
return [self _levelOrderFromState:[self _newState] allObjects:NO];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CPArray)allObjects
|
||||||
|
{
|
||||||
|
if (_order === _CPTreeNodeEnumeratorPreOrder)
|
||||||
|
return [self _preOrderFromState:[self _newState] allObjects:YES];
|
||||||
|
|
||||||
|
else if (_order === _CPTreeNodeEnumeratorInOrder)
|
||||||
|
return [self _inOrderFromState:[self _newState] allObjects:YES];
|
||||||
|
|
||||||
|
else if (_order === _CPTreeNodeEnumeratorPostOrder)
|
||||||
|
return [self _postOrderFromState:[self _newState] allObjects:YES];
|
||||||
|
|
||||||
|
//else if (_order === _CPTreeNodeEnumeratorLevelOrder)
|
||||||
|
return [self _levelOrderFromState:[self _newState] allObjects:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||||
|
{
|
||||||
|
if (aState.state !== 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var count = [[self allObjects] countByEnumeratingWithState:aState objects:objects count:aCount];
|
||||||
|
|
||||||
|
// Dangerous?
|
||||||
|
aState.state = YES;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ CPEnumerationReverse = 1 << 1;
|
|||||||
return [_array objectAtIndex:_index];
|
return [_array objectAtIndex:_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||||
|
{
|
||||||
|
return [_array countByEnumeratingWithState:aState objects:objects count:aCount];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* @ignore */
|
/* @ignore */
|
||||||
@@ -1370,6 +1375,31 @@ CPEnumerationReverse = 1 << 1;
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation CPArray (CPFastEnumeration)
|
||||||
|
|
||||||
|
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||||
|
{
|
||||||
|
var count = [self count],
|
||||||
|
index = aState.state;
|
||||||
|
|
||||||
|
if (index >= count)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var indexIndex = 0,
|
||||||
|
last = MIN(index + aCount, count);
|
||||||
|
|
||||||
|
aCount = last - index;
|
||||||
|
|
||||||
|
for (; index < last; ++index, ++indexIndex)
|
||||||
|
objects[indexIndex] = [self objectAtIndex:index];
|
||||||
|
|
||||||
|
aState.state = last;
|
||||||
|
|
||||||
|
return aCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
var selectorCompare = function selectorCompare(object1, object2, selector)
|
var selectorCompare = function selectorCompare(object1, object2, selector)
|
||||||
{
|
{
|
||||||
return [object1 performSelector:selector withObject:object2];
|
return [object1 performSelector:selector withObject:object2];
|
||||||
|
|||||||
@@ -590,6 +590,31 @@
|
|||||||
|
|
||||||
@end
|
@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 = new Array(count);
|
||||||
|
|
||||||
|
while (index--)
|
||||||
|
objects[index] = [self objectForKey:keys[index]];
|
||||||
|
|
||||||
|
aState.items0 = objects;
|
||||||
|
aState.items1 = keys;
|
||||||
|
aState.state = count;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@class CPMutableDictionary
|
@class CPMutableDictionary
|
||||||
@ingroup compatability
|
@ingroup compatability
|
||||||
|
|||||||
@@ -53,4 +53,11 @@
|
|||||||
return [];
|
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
|
@end
|
||||||
|
|||||||
@@ -857,6 +857,32 @@ var CPIndexSetCountKey = @"CPIndexSetCountKey",
|
|||||||
|
|
||||||
@end
|
@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 = start + range.length,
|
||||||
|
indexes = new Array(range.length);
|
||||||
|
|
||||||
|
while (start < end)
|
||||||
|
indexes[index++] = start++;
|
||||||
|
|
||||||
|
aState.items = indexes;
|
||||||
|
++aState.state;
|
||||||
|
|
||||||
|
return range.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@class CPMutableIndexSet
|
@class CPMutableIndexSet
|
||||||
@ingroup compatability
|
@ingroup compatability
|
||||||
|
|||||||
@@ -86,3 +86,12 @@ var CPNullSharedNull = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation CPNull (CPFastEnumeration)
|
||||||
|
|
||||||
|
- (int)countByEnumeratingWithState:(id)aState objects:(id)objects count:(id)aCount
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
@@ -523,6 +523,22 @@ var CPSetObjectsKey = @"CPSetObjectsKey";
|
|||||||
|
|
||||||
@end
|
@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
|
@class CPMutableSet
|
||||||
@ingroup compatability
|
@ingroup compatability
|
||||||
|
|||||||
@@ -358,6 +358,9 @@ Preprocessor.prototype.directive = function(tokens, aStringBuffer, allowedDirect
|
|||||||
else if (token === TOKEN_IMPORT)
|
else if (token === TOKEN_IMPORT)
|
||||||
this._import(tokens);
|
this._import(tokens);
|
||||||
|
|
||||||
|
else if (token === TOKEN_EACH)
|
||||||
|
this.each(tokens, buffer);
|
||||||
|
|
||||||
// @selector
|
// @selector
|
||||||
else if (token === TOKEN_SELECTOR)
|
else if (token === TOKEN_SELECTOR)
|
||||||
this.selector(tokens, buffer);
|
this.selector(tokens, buffer);
|
||||||
@@ -366,6 +369,99 @@ Preprocessor.prototype.directive = function(tokens, aStringBuffer, allowedDirect
|
|||||||
return buffer;
|
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");
|
||||||
|
|
||||||
|
// var $E = new objj_fastEnumerator(expression);
|
||||||
|
// for ([[var] arg1[, arg2[, ... argN]]];
|
||||||
|
// $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.hash = function(tokens, aStringBuffer)
|
Preprocessor.prototype.hash = function(tokens, aStringBuffer)
|
||||||
{
|
{
|
||||||
// Grab the next token, C preprocessor directives follow '#' immediately.
|
// Grab the next token, C preprocessor directives follow '#' immediately.
|
||||||
|
|||||||
@@ -624,3 +624,110 @@ GLOBAL(sel_registerName) = function(/*String*/ aName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DISPLAY_NAME(sel_registerName);
|
DISPLAY_NAME(sel_registerName);
|
||||||
|
|
||||||
|
var fastEnumerationSelector = sel_getUid("countByEnumeratingWithState:objects:count:");
|
||||||
|
|
||||||
|
GLOBAL(objj_fastEnumerator) = function(/*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();
|
||||||
|
}
|
||||||
|
|
||||||
|
DISPLAY_NAME(objj_fastEnumerator);
|
||||||
|
|
||||||
|
objj_fastEnumerator.prototype.e = function()
|
||||||
|
{
|
||||||
|
var object = this._target;
|
||||||
|
|
||||||
|
// Nothing to iterate, don't iterate
|
||||||
|
if (!object)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
var state = this._state,
|
||||||
|
index = state.assigneeCount;
|
||||||
|
|
||||||
|
while (index--)
|
||||||
|
state["items" + index] = nil;
|
||||||
|
|
||||||
|
this.i = 0;
|
||||||
|
|
||||||
|
// We optimize the array case.
|
||||||
|
if (CPArray && object.isa === CPArray)
|
||||||
|
{
|
||||||
|
if (this.l)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
this.o0 = object;
|
||||||
|
this.l = object.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear out all the old state.
|
||||||
|
state.items = nil;
|
||||||
|
state.itemsPtr = nil;
|
||||||
|
|
||||||
|
this.o0 = [];
|
||||||
|
this.l = objj_msgSend(object, fastEnumerationSelector, state, this.o0, 16);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is the last iteration, set target to nil so that we don't call the
|
||||||
|
// fast enumeration method again.
|
||||||
|
return this.l > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DISPLAY_NAME(objj_fastEnumerator.prototype.e);
|
||||||
|
|||||||
Reference in New Issue
Block a user