mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-10-13 03:57:07 +00:00
Merge branch 'master' of git://github.com/280north/cappuccino
This commit is contained in:
commit
24fbecb2e6
26 files changed
+642
-1086
No files matched your search
@@ -28,7 +28,7 @@
|
||||
|
||||
- (id)mutableArrayValueForKey:(id)aKey
|
||||
{
|
||||
return [[_CPKVCArray alloc] initWithKey:aKey forProxyObject:self];
|
||||
return [[_CPKVCArray alloc] initWithKey:aKey forProxyObject:self];
|
||||
}
|
||||
|
||||
- (id)mutableArrayValueForKeyPath:(id)aKeyPath
|
||||
@@ -430,7 +430,7 @@ kvoOperators["avg"] = function avgOperator(self, _cmd, param)
|
||||
{
|
||||
var objects = [self valueForKeyPath:param],
|
||||
length = [objects count],
|
||||
index = length;
|
||||
index = length,
|
||||
average = 0.0;
|
||||
|
||||
if (!length)
|
||||
@@ -525,7 +525,7 @@ kvoOperators["sum"] = function sumOperator(self, _cmd, param)
|
||||
[super addObserver:observer forKeyPath:aKeyPath options:options context:context];
|
||||
}
|
||||
|
||||
-(void)removeObserver:(id)observer forKeyPath:(CPString)aKeyPath
|
||||
- (void)removeObserver:(id)observer forKeyPath:(CPString)aKeyPath
|
||||
{
|
||||
if ([isa instanceMethodForSelector:_cmd] === [CPArray instanceMethodForSelector:_cmd])
|
||||
[CPException raise:CPInvalidArgumentException reason:"Unsupported method on CPArray"];
|
||||
|
||||
+22
-22
@@ -405,7 +405,7 @@ CPEnumerationReverse = 1 << 1;
|
||||
@param predicate The function to apply to elements of the array. The function receives two arguments:
|
||||
object The element in the array.
|
||||
index The index of the element in the array.
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
or nil to stop the search, which will return CPNotFound to the sender.
|
||||
@return The index of the first matching object, or \c CPNotFound if there is no matching object.
|
||||
*/
|
||||
@@ -420,7 +420,7 @@ CPEnumerationReverse = 1 << 1;
|
||||
object The element in the array.
|
||||
index The index of the element in the array.
|
||||
context The object passed to the receiver in the aContext parameter.
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
or nil to stop the search, which will return CPNotFound to the sender.
|
||||
@param context An object that contains context information you want passed to the predicate function.
|
||||
@return The index of the first matching object, or \c CPNotFound if there is no matching object.
|
||||
@@ -432,29 +432,29 @@ CPEnumerationReverse = 1 << 1;
|
||||
|
||||
/*!
|
||||
Returns the index of the first object in the receiver that passes a test in a given Javascript function.
|
||||
@param opts Specifies the direction in which the array is searched. Pass CPEnumerationNormal to search forwards
|
||||
@param opts Specifies the direction in which the array is searched. Pass CPEnumerationNormal to search forwards
|
||||
or CPEnumerationReverse to search in reverse.
|
||||
@param predicate The function to apply to elements of the array. The function receives two arguments:
|
||||
object The element in the array.
|
||||
index The index of the element in the array.
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
or nil to stop the search, which will return CPNotFound to the sender.
|
||||
@return The index of the first matching object, or \c CPNotFound if there is no matching object.
|
||||
*/
|
||||
- (unsigned)indexOfObjectWithOptions:(CPEnumerationOptions)opts passingTest:(Function)predicate
|
||||
{
|
||||
return [self indexOfObjectWithOptions:opts passingTest:predicate context:undefined];
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the index of the first object in the receiver that passes a test in a given Javascript function.
|
||||
@param opts Specifies the direction in which the array is searched. Pass CPEnumerationNormal to search forwards
|
||||
@param opts Specifies the direction in which the array is searched. Pass CPEnumerationNormal to search forwards
|
||||
or CPEnumerationReverse to search in reverse.
|
||||
@param predicate The function to apply to elements of the array. The function receives two arguments:
|
||||
object The element in the array.
|
||||
index The index of the element in the array.
|
||||
context The object passed to the receiver in the aContext parameter.
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
The predicate function should either return a Boolean value that indicates whether the object passed the test,
|
||||
or nil to stop the search, which will return CPNotFound to the sender.
|
||||
@param context An object that contains context information you want passed to the predicate function.
|
||||
@return The index of the first matching object, or \c CPNotFound if there is no matching object.
|
||||
@@ -463,9 +463,9 @@ CPEnumerationReverse = 1 << 1;
|
||||
{
|
||||
// We don't use an enumerator because they return nil to indicate end of enumeration,
|
||||
// but nil may actually be the value we are looking for, so we have to loop over the array.
|
||||
|
||||
|
||||
var start, stop, increment;
|
||||
|
||||
|
||||
if (opts & CPEnumerationReverse)
|
||||
{
|
||||
start = [self count] - 1;
|
||||
@@ -478,17 +478,17 @@ CPEnumerationReverse = 1 << 1;
|
||||
stop = [self count];
|
||||
increment = 1;
|
||||
}
|
||||
|
||||
|
||||
for (var i = start; i != stop; i += increment)
|
||||
{
|
||||
var result = predicate([self objectAtIndex:i], i, aContext);
|
||||
|
||||
|
||||
if (typeof result === 'boolean' && result)
|
||||
return i;
|
||||
else if (typeof result === 'object' && result == nil)
|
||||
return CPNotFound;
|
||||
}
|
||||
|
||||
|
||||
return CPNotFound;
|
||||
}
|
||||
|
||||
@@ -615,7 +615,7 @@ CPEnumerationReverse = 1 << 1;
|
||||
result = CPOrderedSame;
|
||||
|
||||
while (i < count)
|
||||
if((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
if ((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
@@ -1071,7 +1071,7 @@ CPEnumerationReverse = 1 << 1;
|
||||
result = CPOrderedSame;
|
||||
|
||||
while (i < count)
|
||||
if((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
if ((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
||||
return result;
|
||||
|
||||
return result;
|
||||
@@ -1296,7 +1296,7 @@ CPEnumerationReverse = 1 << 1;
|
||||
{
|
||||
var h, i, j, k, l, m, n = [self count], o;
|
||||
var A, B = [];
|
||||
|
||||
|
||||
for (h = 1; h < n; h += h)
|
||||
{
|
||||
for (m = n - 1 - h; m >= 0; m -= h + h)
|
||||
@@ -1304,10 +1304,10 @@ CPEnumerationReverse = 1 << 1;
|
||||
l = m - h + 1;
|
||||
if (l < 0)
|
||||
l = 0;
|
||||
|
||||
|
||||
for (i = 0, j = l; j <= m; i++, j++)
|
||||
B[i] = self[j];
|
||||
|
||||
|
||||
for (i = 0, k = l; k < j && j <= m + h; k++)
|
||||
{
|
||||
A = self[j];
|
||||
@@ -1320,7 +1320,7 @@ CPEnumerationReverse = 1 << 1;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (k < j)
|
||||
self[k++] = B[i++];
|
||||
}
|
||||
@@ -1345,14 +1345,14 @@ var selectorCompare = function selectorCompare(object1, object2, selector)
|
||||
|
||||
// sort using sort descriptors
|
||||
var compareObjectsUsingDescriptors= function compareObjectsUsingDescriptors(lhs, rhs, descriptors)
|
||||
{
|
||||
{
|
||||
var result = CPOrderedSame,
|
||||
i = 0,
|
||||
i = 0,
|
||||
n = [descriptors count];
|
||||
|
||||
|
||||
while (i < n && result === CPOrderedSame)
|
||||
result = [descriptors[i++] compareObject:lhs withObject:rhs];
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -390,11 +390,11 @@
|
||||
*/
|
||||
- (BOOL)isEqualToAttributedString:(CPAttributedString)aString
|
||||
{
|
||||
if (!aString)
|
||||
return NO;
|
||||
if (!aString)
|
||||
return NO;
|
||||
|
||||
if (_string != [aString string])
|
||||
return NO;
|
||||
if (_string != [aString string])
|
||||
return NO;
|
||||
|
||||
var myRange = CPMakeRange(),
|
||||
comparisonRange = CPMakeRange(),
|
||||
@@ -424,13 +424,13 @@
|
||||
*/
|
||||
- (BOOL)isEqual:(id)anObject
|
||||
{
|
||||
if (anObject == self)
|
||||
return YES;
|
||||
if (anObject == self)
|
||||
return YES;
|
||||
|
||||
if ([anObject isKindOfClass:[self class]])
|
||||
return [self isEqualToAttributedString:anObject];
|
||||
if ([anObject isKindOfClass:[self class]])
|
||||
return [self isEqualToAttributedString:anObject];
|
||||
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
//Extracting a Substring
|
||||
@@ -530,8 +530,8 @@
|
||||
|
||||
endingIndex = startingIndex + 1;
|
||||
|
||||
while(endingIndex < _rangeEntries.length)
|
||||
_rangeEntries[endingIndex++].range.location+=additionalLength;
|
||||
while (endingIndex < _rangeEntries.length)
|
||||
_rangeEntries[endingIndex++].range.location += additionalLength;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
+32
-32
@@ -128,17 +128,17 @@ var _builtInCharacterSets = {};
|
||||
+ (id)_sharedCharacterSetWithName:(id)csname
|
||||
{
|
||||
var cs = _builtInCharacterSets[csname];
|
||||
if(cs == nil)
|
||||
if (cs == nil)
|
||||
{
|
||||
var i,
|
||||
ranges = [CPArray array],
|
||||
rangeArray = eval(csname);
|
||||
|
||||
for(i = 0; i < rangeArray.length; i+= 2)
|
||||
for (i = 0; i < rangeArray.length; i+= 2)
|
||||
{
|
||||
var loc = rangeArray[i];
|
||||
var length = rangeArray[i+1];
|
||||
var range = CPMakeRange(loc,length);
|
||||
var loc = rangeArray[i],
|
||||
length = rangeArray[i + 1],
|
||||
range = CPMakeRange(loc,length);
|
||||
[ranges addObject:range];
|
||||
}
|
||||
cs = [[_CPRangeCharacterSet alloc] initWithRanges:ranges];
|
||||
@@ -196,13 +196,13 @@ var _builtInCharacterSets = {};
|
||||
- (BOOL)characterIsMember:(CPString)aCharacter
|
||||
{
|
||||
c = aCharacter.charCodeAt(0);
|
||||
var enu = [_ranges objectEnumerator];
|
||||
var range;
|
||||
var enu = [_ranges objectEnumerator],
|
||||
range;
|
||||
|
||||
while (range = [enu nextObject])
|
||||
{
|
||||
if (CPLocationInRange(c, range))
|
||||
return !_inverted;
|
||||
return !_inverted;
|
||||
}
|
||||
|
||||
return _inverted;
|
||||
@@ -226,10 +226,10 @@ var _builtInCharacterSets = {};
|
||||
{
|
||||
var i;
|
||||
|
||||
for(i = 0; i < aString.length; i++)
|
||||
for (i = 0; i < aString.length; i++)
|
||||
{
|
||||
var code = aString.charCodeAt(i);
|
||||
var range = CPMakeRange(code,1);
|
||||
var code = aString.charCodeAt(i),
|
||||
range = CPMakeRange(code,1);
|
||||
|
||||
[_ranges addObject:range];
|
||||
}
|
||||
@@ -262,7 +262,7 @@ var _builtInCharacterSets = {};
|
||||
return set;
|
||||
}
|
||||
|
||||
-(id)invertedSet
|
||||
- (id)invertedSet
|
||||
{
|
||||
var set = [[_CPStringContentCharacterSet alloc] initWithString:_string];
|
||||
[set invert];
|
||||
@@ -294,7 +294,7 @@ var _builtInCharacterSets = {};
|
||||
- (void)addCharactersInRange:(CPRange)aRange // Needs _inverted support
|
||||
{
|
||||
var i;
|
||||
for(i = aRange.location; i < aRange.location + aRange.length; i++)
|
||||
for (i = aRange.location; i < aRange.location + aRange.length; i++)
|
||||
{
|
||||
var s = String.fromCharCode(i);
|
||||
|
||||
@@ -307,7 +307,7 @@ var _builtInCharacterSets = {};
|
||||
{
|
||||
var i;
|
||||
|
||||
for(i = 0; i < aString.length; i++)
|
||||
for (i = 0; i < aString.length; i++)
|
||||
{
|
||||
var s = aString.charAt(i);
|
||||
|
||||
@@ -330,34 +330,34 @@ _CPCharacterSetTrimAtEnd = 1 << 2;
|
||||
and the set is [CPCharacterSet whitespaceCharacterSet]
|
||||
the returned array would contain:
|
||||
<pre> ["Baku", "baku", "to", "jest", "", "skład."] </pre>
|
||||
Adjacent occurences of the separator characters produce empty strings in the result.
|
||||
@author Arkadiusz Młynarczyk <arek@tupux.com>
|
||||
Adjacent occurences of the separator characters produce empty strings in the result.
|
||||
@author Arkadiusz Młynarczyk <arek@tupux.com>
|
||||
@param A character set containing the characters to use to split the receiver. Must not be nil.
|
||||
@return An CPArray object containing substrings from the receiver that have been divided by characters in separator.
|
||||
*/
|
||||
- (CPArray)componentsSeparatedByCharactersInSet:(CPCharacterSet)separator
|
||||
{
|
||||
if (!separator)
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
if (!separator)
|
||||
[CPException raise:CPInvalidArgumentException
|
||||
reason:"componentsSeparatedByCharactersInSet: the separator can't be 'nil'"];
|
||||
|
||||
var components = [CPMutableArray array],
|
||||
componentRange = CPMakeRange(0, 0);
|
||||
var components = [CPMutableArray array],
|
||||
componentRange = CPMakeRange(0, 0);
|
||||
|
||||
for (var i=0; i < self.length; i++)
|
||||
{
|
||||
if ([separator characterIsMember:self.charAt(i)])
|
||||
{
|
||||
componentRange.length = i - componentRange.location;
|
||||
[components addObject:[self substringWithRange:componentRange]];
|
||||
componentRange.location += componentRange.length + 1;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < self.length; i++)
|
||||
{
|
||||
if ([separator characterIsMember:self.charAt(i)])
|
||||
{
|
||||
componentRange.length = i - componentRange.location;
|
||||
[components addObject:[self substringWithRange:componentRange]];
|
||||
componentRange.location += componentRange.length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
componentRange.length = self.length - componentRange.location;
|
||||
[components addObject:[self substringWithRange:componentRange]];
|
||||
componentRange.length = self.length - componentRange.location;
|
||||
[components addObject:[self substringWithRange:componentRange]];
|
||||
|
||||
return components;
|
||||
return components;
|
||||
}
|
||||
|
||||
// As per the Cocoa method.
|
||||
|
||||
@@ -364,7 +364,7 @@
|
||||
}
|
||||
|
||||
return matchingKeys;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns an enumerator that enumerates over all the dictionary's keys.
|
||||
|
||||
+33
-33
@@ -23,13 +23,13 @@
|
||||
/*!
|
||||
@class CPFormatter
|
||||
@ingroup foundation
|
||||
@brief CPFormatter is an abstract class that declares an interface for objects that create, interpret,
|
||||
and validate the textual representation of cell contents. The Foundation framework provides two
|
||||
@brief CPFormatter is an abstract class that declares an interface for objects that create, interpret,
|
||||
and validate the textual representation of cell contents. The Foundation framework provides two
|
||||
concrete subclasses of CPFormatter to generate these objects: CPNumberFormatter and CPDateFormatter.
|
||||
|
||||
CPFormatter is intended for subclassing. A custom formatter can restrict the input and enhance the
|
||||
display of data in novel ways. For example, you could have a custom formatter that ensures that serial
|
||||
numbers entered by a user conform to predefined formats. Before you decide to create a custom formatter,
|
||||
CPFormatter is intended for subclassing. A custom formatter can restrict the input and enhance the
|
||||
display of data in novel ways. For example, you could have a custom formatter that ensures that serial
|
||||
numbers entered by a user conform to predefined formats. Before you decide to create a custom formatter,
|
||||
make sure that you cannot configure the public subclasses CPDateFormatter and CPNumberFormatter to satisfy your requirements.
|
||||
*/
|
||||
|
||||
@@ -40,10 +40,10 @@
|
||||
/*!
|
||||
The default implementation of this method raises an exception.
|
||||
|
||||
When implementing a subclass, return the CPString object that textually represents
|
||||
the view's object for display and if editingStringForObjectValue: is unimplemented for editing.
|
||||
First test the passed-in object to see if it's of the correct class. If it isn't, return nil;
|
||||
but if it is of the right class, return a properly formatted and, if necessary, localized string.
|
||||
When implementing a subclass, return the CPString object that textually represents
|
||||
the view's object for display and if editingStringForObjectValue: is unimplemented for editing.
|
||||
First test the passed-in object to see if it's of the correct class. If it isn't, return nil;
|
||||
but if it is of the right class, return a properly formatted and, if necessary, localized string.
|
||||
(See the specification of the CPString class for formatting and localizing details.)
|
||||
|
||||
@param anObject The object for which a textual representation is returned
|
||||
@@ -65,9 +65,9 @@
|
||||
/*!
|
||||
The default implementation of this method invokes stringForObjectValue:.
|
||||
|
||||
When implementing a subclass, override this method only when the string that users see and the string
|
||||
that they edit are different. In your implementation, return an CPString object that is used for editing,
|
||||
following the logic recommended for implementing stringForObjectValue:. As an example, you would implement
|
||||
When implementing a subclass, override this method only when the string that users see and the string
|
||||
that they edit are different. In your implementation, return an CPString object that is used for editing,
|
||||
following the logic recommended for implementing stringForObjectValue:. As an example, you would implement
|
||||
this method if you want the dollar signs in displayed strings removed for editing.
|
||||
|
||||
@param anObject the object for which to return an editing string
|
||||
@@ -82,11 +82,11 @@
|
||||
/*!
|
||||
The default implementation of this method raises an exception.
|
||||
|
||||
When implementing a subclass, return by reference the object anObject after creating it from string.
|
||||
Return YES if the conversion is successful. If you return NO, also return by indirection (in error)
|
||||
a localized user-presentable CPString object that explains the reason why the conversion failed; the delegate
|
||||
(if any) of the CPControl object managing the cell can then respond to the failure in
|
||||
control:didFailToFormatString:errorDescription:. However, if error is nil, the sender is not interested in
|
||||
When implementing a subclass, return by reference the object anObject after creating it from string.
|
||||
Return YES if the conversion is successful. If you return NO, also return by indirection (in error)
|
||||
a localized user-presentable CPString object that explains the reason why the conversion failed; the delegate
|
||||
(if any) of the CPControl object managing the cell can then respond to the failure in
|
||||
control:didFailToFormatString:errorDescription:. However, if error is nil, the sender is not interested in
|
||||
the error description, and you should not attempt to assign one.
|
||||
|
||||
@param anObject if conversion is successful, upon return contains the object created from the string
|
||||
@@ -104,18 +104,18 @@
|
||||
/*!
|
||||
Returns a Boolean value that indicates whether a partial string is valid.
|
||||
|
||||
This method is invoked each time the user presses a key while the cell has the keyboard focus it lets you verify and
|
||||
This method is invoked each time the user presses a key while the cell has the keyboard focus it lets you verify and
|
||||
edit the cell text as the user types it.
|
||||
|
||||
In a subclass implementation, evaluate partialString according to the context, edit the text if necessary, and return
|
||||
by reference any edited string in newString. Return YES if partialString is acceptable and NO if partialString is unacceptable.
|
||||
If you return NO and newString is nil, the cell displays partialString minus the last character typed. If you return NO, you can
|
||||
also return by indirection an CPString object (in error) that explains the reason why the validation failed; the delegate (if any)
|
||||
of the CPControl object managing the cell can then respond to the failure in control:didFailToValidatePartialString:errorDescription:.
|
||||
In a subclass implementation, evaluate partialString according to the context, edit the text if necessary, and return
|
||||
by reference any edited string in newString. Return YES if partialString is acceptable and NO if partialString is unacceptable.
|
||||
If you return NO and newString is nil, the cell displays partialString minus the last character typed. If you return NO, you can
|
||||
also return by indirection an CPString object (in error) that explains the reason why the validation failed; the delegate (if any)
|
||||
of the CPControl object managing the cell can then respond to the failure in control:didFailToValidatePartialString:errorDescription:.
|
||||
The selection range will always be set to the end of the text if replacement occurs.
|
||||
|
||||
This method is a compatibility method. If a subclass overrides this method and does not override
|
||||
isPartialStringValid:proposedSelectedRange:originalString:originalSelectedRange:errorDescription:, this method will be called as before
|
||||
This method is a compatibility method. If a subclass overrides this method and does not override
|
||||
isPartialStringValid:proposedSelectedRange:originalString:originalSelectedRange:errorDescription:, this method will be called as before
|
||||
(isPartialStringValid:proposedSelectedRange:originalString:originalSelectedRange:errorDescription: just calls this one by default).
|
||||
|
||||
@param aPartialString the text currently in the view.
|
||||
@@ -130,20 +130,20 @@
|
||||
}
|
||||
|
||||
/*!
|
||||
This method should be implemented in subclasses that want to validate user changes to a string in a field, where the user changes are
|
||||
not necessarily at the end of the string, and preserve the selection (or set a different one, such as selecting the erroneous part of
|
||||
This method should be implemented in subclasses that want to validate user changes to a string in a field, where the user changes are
|
||||
not necessarily at the end of the string, and preserve the selection (or set a different one, such as selecting the erroneous part of
|
||||
the string the user has typed).
|
||||
|
||||
In a subclass implementation, evaluate partialString according to the context. Return YES if partialStringPtr is acceptable and NO if partialStringPtr
|
||||
is unacceptable. Assign a new string to partialStringPtr and a new range to proposedSelRangePtr and return NO if you want to replace the string and
|
||||
change the selection range. If you return NO, you can also return by indirection an CPString object (in error) that explains the reason why the
|
||||
validation failed; the delegate (if any) of the CPControl object managing the cell can then respond to the failure in
|
||||
In a subclass implementation, evaluate partialString according to the context. Return YES if partialStringPtr is acceptable and NO if partialStringPtr
|
||||
is unacceptable. Assign a new string to partialStringPtr and a new range to proposedSelRangePtr and return NO if you want to replace the string and
|
||||
change the selection range. If you return NO, you can also return by indirection an CPString object (in error) that explains the reason why the
|
||||
validation failed; the delegate (if any) of the CPControl object managing the cell can then respond to the failure in
|
||||
control:didFailToValidatePartialString:errorDescription:.
|
||||
|
||||
@param aPartialString The new string to validate.
|
||||
@param aProposedSelectedRange The selection range that will be used if the string is accepted or replaced.
|
||||
@param originalString The original string, before the proposed change.
|
||||
@param originalSelectedRange The selection range over which the change is to take place.
|
||||
@param originalSelectedRange The selection range over which the change is to take place.
|
||||
@param error If non-nil, if validation fails contains an CPString object that descibes the problem.
|
||||
@return YES if aPartialString is acceptable, otherwise NO.
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -134,7 +134,7 @@ CPJSONPCallbackReplacementString = @"${JSONP_CALLBACK}";
|
||||
{
|
||||
var head = document.getElementsByTagName("head").item(0);
|
||||
|
||||
if(_scriptTag && _scriptTag.parentNode == head)
|
||||
if (_scriptTag && _scriptTag.parentNode == head)
|
||||
head.removeChild(_scriptTag);
|
||||
|
||||
CPJSONPConnectionCallbacks["callback" + [self UID]] = nil;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
@import "CPEnumerator.j"
|
||||
@import "CPPredicate.j"
|
||||
@import "CPExpression.j"
|
||||
@import "CPExpression_operator.j"
|
||||
|
||||
/*!
|
||||
A predicate to compare directly the left and right hand sides.
|
||||
@@ -136,8 +135,8 @@ CPContainsPredicateOperatorType = 99;
|
||||
*/
|
||||
CPBetweenPredicateOperatorType = 100;
|
||||
|
||||
var CPComparisonPredicateModifier;
|
||||
var CPPredicateOperatorType;
|
||||
var CPComparisonPredicateModifier,
|
||||
CPPredicateOperatorType;
|
||||
|
||||
/*!
|
||||
@ingroup foundation
|
||||
@@ -426,8 +425,8 @@ var CPPredicateOperatorType;
|
||||
lhs = lhs.stripDiacritics();
|
||||
rhs = rhs.stripDiacritics();
|
||||
}
|
||||
var commut = (_options & CPCaseInsensitivePredicateOption) ? "gi":"g";
|
||||
var reg = new RegExp(rhs.escapeForRegExp(),commut);
|
||||
var commut = (_options & CPCaseInsensitivePredicateOption) ? "gi":"g",
|
||||
reg = new RegExp(rhs.escapeForRegExp(),commut);
|
||||
return reg.test(lhs);
|
||||
case CPBeginsWithPredicateOperatorType:
|
||||
var range = CPMakeRange(0,[rhs length]);
|
||||
@@ -441,43 +440,19 @@ var CPPredicateOperatorType;
|
||||
if (_options & CPDiacriticInsensitivePredicateOption) string_compare_options |= CPDiacriticInsensitiveSearch;
|
||||
|
||||
return ([lhs compare:rhs options:string_compare_options range:range] == CPOrderedSame);
|
||||
case CPInPredicateOperatorType:
|
||||
// Handle special case where rhs is a collection and lhs an element of it.
|
||||
if (![rhs isKindOfClass: [CPString class]])
|
||||
{
|
||||
if (![rhs respondsToSelector: @selector(objectEnumerator)])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The right hand side for an IN operator must be a collection"];
|
||||
|
||||
var e = [rhs objectEnumerator],
|
||||
value;
|
||||
while (value = [e nextObject])
|
||||
if ([value isEqual:lhs])
|
||||
return YES;
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (_options & CPCaseInsensitivePredicateOption)
|
||||
string_compare_options |= CPCaseInsensitiveSearch;
|
||||
if (_options & CPDiacriticInsensitivePredicateOption)
|
||||
string_compare_options |= CPDiacriticInsensitiveSearch;
|
||||
|
||||
return ([rhs rangeOfString:lhs options:string_compare_options].location != CPNotFound);
|
||||
case CPCustomSelectorPredicateOperatorType:
|
||||
return [lhs performSelector:_customSelector withObject:rhs];
|
||||
case CPInPredicateOperatorType:
|
||||
var a = lhs; // swap
|
||||
lhs = rhs;
|
||||
rhs = a;
|
||||
case CPContainsPredicateOperatorType:
|
||||
if (![lhs isKindOfClass: [CPString class]])
|
||||
if (![lhs isKindOfClass:[CPString class]])
|
||||
{
|
||||
if (![lhs respondsToSelector: @selector(objectEnumerator)])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The left hand side for a CONTAINS operator must be a collection or a string"];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The left/right hand side for a CONTAINS/IN operator must be a collection or a string"];
|
||||
|
||||
var e = [lhs objectEnumerator],
|
||||
value;
|
||||
while (value = [e nextObject])
|
||||
if ([value isEqual:rhs])
|
||||
return YES;
|
||||
|
||||
return NO;
|
||||
return [lhs containsObject:rhs];
|
||||
}
|
||||
|
||||
if (_options & CPCaseInsensitivePredicateOption)
|
||||
@@ -487,13 +462,10 @@ var CPPredicateOperatorType;
|
||||
|
||||
return ([lhs rangeOfString:rhs options:string_compare_options].location != CPNotFound);
|
||||
case CPBetweenPredicateOperatorType:
|
||||
if ([lhs count] < 2)
|
||||
if ([rhs count] < 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The right hand side for a BETWEEN operator must contain 2 objects"];
|
||||
|
||||
var lower = [rhs objectAtIndex:0],
|
||||
upper = [rhs objectAtIndex:1];
|
||||
|
||||
return ([lhs compare:lower] == CPOrderedDescending && [lhs compare:upper] == CPOrderedAscending);
|
||||
return ([lhs compare:rhs[0]] == CPOrderedDescending && [lhs compare:rhs[1]] == CPOrderedAscending);
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
@@ -572,8 +544,8 @@ var CPPredicateOperatorType;
|
||||
|
||||
@end
|
||||
|
||||
var source = ['*','?','(',')','{','}','.','+','|','/','$','^'];
|
||||
var dest = ['.*','.?','\\(','\\)','\\{','\\}','\\.','\\+','\\|','\\/','\\$','\\^'];
|
||||
var source = ['*','?','(',')','{','}','.','+','|','/','$','^'],
|
||||
dest = ['.*','.?','\\(','\\)','\\{','\\}','\\.','\\+','\\|','\\/','\\$','\\^'];
|
||||
|
||||
String.prototype.escapeForRegExp = function()
|
||||
{
|
||||
|
||||
@@ -126,7 +126,7 @@ var CPCompoundPredicateType;
|
||||
i;
|
||||
|
||||
if (count == 0)
|
||||
return @"TRUPREDICATE";
|
||||
return @"TRUPREDICATE";
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
|
||||
@@ -132,7 +132,7 @@ CPMinusSetExpressionType = 9;
|
||||
*/
|
||||
+ (CPExpression)expressionForUnionSet:(CPExpression)left with:(CPExpression)right
|
||||
{
|
||||
return [[CPExpression_unionset alloc] initWithLeft:left right:right];
|
||||
return [[CPExpression_set alloc] initWithType:CPUnionSetExpressionType left:left right:right];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -143,7 +143,7 @@ CPMinusSetExpressionType = 9;
|
||||
*/
|
||||
+ (CPExpression)expressionForIntersectSet:(CPExpression)left with:(CPExpression)right
|
||||
{
|
||||
return [[CPExpression_intersectset alloc] initWithLeft:left right:right];
|
||||
return [[CPExpression_set alloc] initWithType:CPIntersectSetExpressionType left:left right:right];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -154,7 +154,7 @@ CPMinusSetExpressionType = 9;
|
||||
*/
|
||||
+ (CPExpression)expressionForMinusSet:(CPExpression)left with:(CPExpression)right
|
||||
{
|
||||
return [[CPExpression_minusset alloc] initWithLeft:left right:right];
|
||||
return [[CPExpression_set alloc] initWithType:CPMinusSetExpressionType left:left right:right];
|
||||
}
|
||||
|
||||
// Creating an Expression for a Function
|
||||
@@ -319,6 +319,4 @@ CPMinusSetExpressionType = 9;
|
||||
@import "CPExpression_keypath.j"
|
||||
@import "CPExpression_function.j"
|
||||
@import "CPExpression_aggregate.j"
|
||||
@import "CPExpression_unionset.j"
|
||||
@import "CPExpression_intersectset.j"
|
||||
@import "CPExpression_minusset.j"
|
||||
@import "CPExpression_set.j"
|
||||
@@ -15,30 +15,14 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (CPExpression)expressionForAggregate:(CPArray)collection
|
||||
{
|
||||
return [[self alloc] initWithAggregate:collection];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var aggregate = [coder decodeObjectForKey:@"CPExpressionAggregate"];
|
||||
return [self initWithAggregate:aggregate];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_aggregate forKey:@"CPExpressionAggregate"]; // subexpressions must be CPCoding compliant.
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object collection] isEqual:[self collection]])
|
||||
return NO;
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -47,32 +31,16 @@
|
||||
return _aggregate;
|
||||
}
|
||||
|
||||
- (CPExpression)rightExpression
|
||||
{
|
||||
if ([_aggregate count] > 0)
|
||||
return [_aggregate lastObject];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CPExpression)leftExpression
|
||||
{
|
||||
if ([_aggregate count] > 0)
|
||||
return [_aggregate objectAtIndex:0];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
|
||||
{
|
||||
var eval_array = [CPArray array],
|
||||
collection = [_aggregate objectEnumerator],
|
||||
exp;
|
||||
|
||||
|
||||
while (exp = [collection nextObject])
|
||||
{
|
||||
var eval = [exp expressionValueWithObject:object context:context];
|
||||
if (eval != nil)[eval_array addObject:eval];
|
||||
[eval_array addObject:eval];
|
||||
}
|
||||
|
||||
return eval_array;
|
||||
@@ -81,14 +49,14 @@
|
||||
- (CPString)description
|
||||
{
|
||||
var i,
|
||||
count = [_aggregate count],
|
||||
count = [_aggregate count],
|
||||
result = "{";
|
||||
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
result = result + [CPString stringWithFormat:@"%s%s", [[_aggregate objectAtIndex:i] description], (i + 1 < count) ? @", " : @""];
|
||||
|
||||
|
||||
result = result + "}";
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -97,7 +65,7 @@
|
||||
var subst_array = [CPArray array],
|
||||
count = [_aggregate count],
|
||||
i;
|
||||
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
[subst_array addObject:[[_aggregate objectAtIndex:i] _expressionWithSubstitutionVariables:variables]];
|
||||
|
||||
@@ -105,3 +73,20 @@
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPCollectionKey = @"CPCollection";
|
||||
|
||||
@implementation CPExpression_aggregate (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var collection = [coder decodeObjectForKey:CPCollectionKey];
|
||||
return [self initWithAggregate:collection];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_aggregate forKey:CPCollectionKey];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,92 +0,0 @@
|
||||
|
||||
@import "CPExpression.j"
|
||||
@import "CPExpression_variable.j"
|
||||
@import <Foundation/CPString.j>
|
||||
|
||||
|
||||
@implementation CPExpression_assignment: CPExpression
|
||||
{
|
||||
CPExpression_variable _assignmentVariable;
|
||||
CPExpression _subexpression;
|
||||
}
|
||||
|
||||
- (id)initWithAssignmentVariable:(CPString)variable expression:(CPExpression)expression
|
||||
{
|
||||
_assignmentVariable = [CPExpression expressionForVariable:variable];
|
||||
_subexpression = expression;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithAssignmentExpression:(CPExpression)variableExpression expression:(CPExpression)expression
|
||||
{
|
||||
_assignmentVariable = variableExpression;
|
||||
_subexpression = expression;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var variable = [coder decodeObjectForKey:@"CPExpressionAssignmentVariable"];
|
||||
var expression = [coder decodeObjectForKey:@"CPExpressionAssignmentExpression"];
|
||||
|
||||
return [self initWithAssignmentVariable:variable expression:expression];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_assignmentVariable forKey:@"CPExpressionAssignmentVariable"];
|
||||
[coder encodeObject:_subexpression forKey:@"CPExpressionAssignmentExpression"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object subexpression] isEqual:[self subexpression]] || ![[object variable] isEqualToString:[self variable]])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CPExpression)assignmentVariable
|
||||
{
|
||||
return _assignmentVariable;
|
||||
}
|
||||
|
||||
- (CPExpression)subexpression
|
||||
{
|
||||
return _subexpression;
|
||||
}
|
||||
|
||||
- (CPString)variable
|
||||
{
|
||||
return [_assignmentVariable variable];
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
var pretty = [_expression description];
|
||||
|
||||
if ([_subexpression isKindOfClass:[CPExpression_operator class]])
|
||||
pretty = [CPString stringWithFormat:@"(%@)", pretty];
|
||||
|
||||
return [CPString stringWithFormat:@"%@ := %@", [self variable], pretty];
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:(id)object context:(id)context
|
||||
{
|
||||
// UNIMPLEMENTED
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
|
||||
{
|
||||
// UNIMPLEMENTED
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,30 +11,18 @@
|
||||
{
|
||||
[super initWithExpressionType:CPConstantValueExpressionType];
|
||||
_value = value;
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var value = [coder decodeObjectForKey:@"CPExpressionConstantValue"];
|
||||
|
||||
return [self initWithValue:value];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_value forKey:@"CPExpressionConstantValue"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object constantValue] isEqual:[self constantValue]])
|
||||
return NO;
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -63,3 +51,19 @@
|
||||
|
||||
@end
|
||||
|
||||
var CPConstantValueKey = @"CPConstantValue";
|
||||
|
||||
@implementation CPExpression_constant (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var value = [coder decodeObjectForKey:CPConstantValueKey];
|
||||
return [self initWithValue:value];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_value forKey:CPConstantValueKey];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -12,59 +12,38 @@
|
||||
int _argc;
|
||||
}
|
||||
|
||||
- (id)initWithSelector:(SEL)aselector arguments:(CPArray)parameters
|
||||
- (id)initWithSelector:(SEL)aSelector arguments:(CPArray)parameters
|
||||
{
|
||||
[super initWithExpressionType:CPFunctionExpressionType];
|
||||
|
||||
if (![self respondsToSelector:aselector])
|
||||
[CPException raise: CPInvalidArgumentException reason:@"Unknown function implementation: " + aselector];
|
||||
|
||||
_selector = aselector;
|
||||
_operand = nil;
|
||||
_arguments = parameters;
|
||||
_argc = [parameters count];
|
||||
|
||||
return self;
|
||||
var target = [CPPredicateUtilities class];
|
||||
if (![target respondsToSelector:aSelector])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Unknown function implementation: " + aSelector];
|
||||
|
||||
var operand = [CPExpression expressionForConstantValue:target];
|
||||
return [self initWithTarget:operand selector:aSelector arguments:parameters];
|
||||
}
|
||||
|
||||
- (id)initWithTarget:(CPExpression)targetExpression selector:(SEL)aselector arguments:(CPArray)parameters
|
||||
- (id)initWithTarget:(CPExpression)targetExpression selector:aSelector arguments:parameters
|
||||
{
|
||||
[super initWithExpressionType:CPFunctionExpressionType];
|
||||
|
||||
var target = [targetExpression expressionValueWithObject:object context:context];
|
||||
if (![target respondsToSelector:aselector])
|
||||
[CPException raise: CPInvalidArgumentException reason:@"Unknown function implementation: " + aselector];
|
||||
|
||||
_selector = aselector;
|
||||
[super initWithExpressionType:CPFunctionExpressionType];
|
||||
|
||||
// Cocoa doc: "This method throws an exception immediately if the selector is unknown"
|
||||
// but targetExpression's value (selector's target) may be resolved only at runtime.
|
||||
_selector = aSelector;
|
||||
_operand = targetExpression;
|
||||
_arguments = parameters;
|
||||
_argc = [parameters count];
|
||||
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var selector = CPSelectorFromString([coder decodeObjectForKey:@"CPExpressionFunctionName"]);
|
||||
var arguments = [coder decodeObjectForKey:@"CPExpressionFunctionArguments"];
|
||||
|
||||
return [self initWithSelector:selector arguments:arguments];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:[self _function] forKey:@"CPExpressionFunctionName"];
|
||||
[coder encodeObject:_arguments forKey:@"CPExpressionArguments"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object _function] isEqualToString:[self _function]] || ![[object operand] isEqual:[self operand]] || ![[object arguments] isEqualToArray:[self arguments]])
|
||||
return NO;
|
||||
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -90,284 +69,193 @@
|
||||
|
||||
- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
|
||||
{
|
||||
var eval_args = [CPArray array],
|
||||
var target = [_operand expressionValueWithObject:object context:context],
|
||||
objj_args = [target, _selector],
|
||||
i;
|
||||
|
||||
for (i = 0; i < _argc; i++)
|
||||
{
|
||||
var arg = [[_arguments objectAtIndex:i] expressionValueWithObject:object context:context];
|
||||
if (arg != nil)
|
||||
[eval_args addObject:arg];
|
||||
var arg = [_arguments[i] expressionValueWithObject:object context:context];
|
||||
objj_args.push(arg);
|
||||
}
|
||||
|
||||
var target = (_operand == nil) ? self : [_operand expressionValueWithObject:object context:context];
|
||||
return [target performSelector:_selector withObject:eval_args];
|
||||
return objj_msgSend.apply(this, objj_args);
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
var result = [CPString stringWithFormat:@"%@ %s(", [_operand description], [self _function]],
|
||||
i;
|
||||
|
||||
for (i = 0; i < _argc; i++)
|
||||
result = result + [_arguments objectAtIndex:i] + (i+1<_argc) ? ", " : "";
|
||||
|
||||
{
|
||||
var result = _operand + [self _function] + "(";
|
||||
|
||||
for (var i = 0; i < _argc; i++)
|
||||
result = result + [_arguments[i] description] + ((i + 1 < _argc) ? ", " : "");
|
||||
|
||||
result = result + ")";
|
||||
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
- (CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
|
||||
{
|
||||
var array = [CPArray array],
|
||||
i;
|
||||
|
||||
|
||||
for (i = 0; i < _argc; i++)
|
||||
[array addObject:[[_arguments objectAtIndex:i] _expressionWithSubstitutionVariables:variables]];
|
||||
|
||||
return [CPExpression expressionForFunction:[self operand] selectorName:[self _function] arguments:array];
|
||||
}
|
||||
|
||||
- (CPNumber)sum:(CPArray)parameters
|
||||
@end
|
||||
|
||||
var CPSelectorNameKey = @"CPSelectorName",
|
||||
CPArgumentsKey = @"CPArguments",
|
||||
CPOperandKey = @"CPOperand";
|
||||
|
||||
@implementation CPExpression_function (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
if (_argc < 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var i,
|
||||
sum = 0.0;
|
||||
|
||||
for (i = 0; i < _argc; i++)
|
||||
sum += [[parameters objectAtIndex:i] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble: sum];
|
||||
var target = [coder decodeObjectForKey:CPOperandKey],
|
||||
selector = CPSelectorFromString([coder decodeObjectForKey:CPSelectorNameKey]),
|
||||
arguments = [coder decodeObjectForKey:CPArgumentsKey];
|
||||
|
||||
return [self initWithTarget:target selector:selector arguments:arguments];
|
||||
}
|
||||
|
||||
- (CPNumber)count:(CPArray)parameters
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
if (_argc < 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
return [CPNumber numberWithUnsignedInt: [[parameters objectAtIndex:0] count]];
|
||||
[coder encodeObject:[self _function] forKey:CPSelectorNameKey];
|
||||
[coder encodeObject:_arguments forKey:CPArgumentsKey];
|
||||
[coder encodeObject:_operand forKey:CPOperandKey];
|
||||
}
|
||||
|
||||
- (CPNumber)min:(CPArray)parameters
|
||||
@end
|
||||
|
||||
// Built-in functions
|
||||
@implementation CPPredicateUtilities : CPObject
|
||||
{
|
||||
if (_argc < 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
return MIN([parameters objectAtIndex:0],[parameters objectAtIndex:1]);
|
||||
}
|
||||
|
||||
- (CPNumber)max:(CPArray)parameters
|
||||
+ (float)sum:(CPArray)parameters
|
||||
{
|
||||
if (_argc < 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
return MAX([parameters objectAtIndex:0],[parameters objectAtIndex:1]);
|
||||
var sum = 0,
|
||||
count = parameters.length;
|
||||
|
||||
while (count--)
|
||||
sum += parameters[count];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
- (CPNumber)average:(CPArray)parameters
|
||||
+ (float)count:(CPArray)parameters
|
||||
{
|
||||
if (_argc < 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var i,
|
||||
sum = 0.0;
|
||||
|
||||
for (i = 0; i < _argc; i++)
|
||||
sum += [[parameters objectAtIndex:i] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble: sum / _argc];
|
||||
return [parameters count];
|
||||
}
|
||||
|
||||
- (CPNumber)add:to:(CPArray)parameters
|
||||
+ (float)min:(CPArray)parameters
|
||||
{
|
||||
if (_argc != 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var left = [parameters objectAtIndex:0],
|
||||
right = [parameters objectAtIndex:1];
|
||||
|
||||
return [CPNumber numberWithDouble: [left doubleValue] + [right doubleValue]];
|
||||
return parameters.sort()[0];
|
||||
}
|
||||
|
||||
- (CPNumber)from:subtract:(CPArray)parameters
|
||||
+ (float)max:(CPArray)parameters
|
||||
{
|
||||
if (_argc != 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var left = [parameters objectAtIndex:0],
|
||||
right = [parameters objectAtIndex:1];
|
||||
|
||||
return [CPNumber numberWithDouble: [left doubleValue] - [right doubleValue]];
|
||||
return parameters.sort()[parameters.length - 1];
|
||||
}
|
||||
|
||||
- (CPNumber)multiply:by:(CPArray)parameters
|
||||
+ (float)average:(CPArray)parameters
|
||||
{
|
||||
if (_argc != 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var left = [parameters objectAtIndex:0],
|
||||
right = [parameters objectAtIndex:1];
|
||||
|
||||
return [CPNumber numberWithDouble: [left doubleValue] * [right doubleValue]];
|
||||
return [self sum:parameters] / parameters.length;
|
||||
}
|
||||
|
||||
- (CPNumber)divide:by:(CPArray)parameters
|
||||
+ (id)first:(CPArray)parameters
|
||||
{
|
||||
if (_argc != 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var left = [parameters objectAtIndex:0],
|
||||
right = [parameters objectAtIndex:1];
|
||||
|
||||
return [CPNumber numberWithDouble: [left doubleValue] / [right doubleValue]];
|
||||
return parameters[0];
|
||||
}
|
||||
|
||||
- (CPNumber)sqrt:(CPArray)parameters
|
||||
+ (id)last:(CPArray)parameters
|
||||
{
|
||||
if (_argc != 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var num = [[parameters objectAtIndex:0] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble: SQRT(num)];
|
||||
return parameters[parameters.length - 1];
|
||||
}
|
||||
|
||||
- (CPNumber)raise:to:(CPArray)parameters
|
||||
+ (id)fromObject:(id)object index:(id)anIndex
|
||||
{
|
||||
if (_argc < 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var num = [[parameters objectAtIndex:0] doubleValue],
|
||||
power = [[parameters objectAtIndex:1] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble: POW(num,power)];
|
||||
if ([object isKindOfClass:[CPDictionary class]])
|
||||
return [object objectForKey:anIndex];
|
||||
else ([object isKindOfClass:[CPArray class]])
|
||||
return [object objectAtIndex:anIndex];
|
||||
|
||||
[CPException raise:CPInvalidArgumentException reason:@"object[#] requires a CPDictionary or CPArray"];
|
||||
}
|
||||
|
||||
- (CPNumber)abs:(CPArray)parameters
|
||||
+ (float)add:(int)n to:(int)m
|
||||
{
|
||||
if (_argc != 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var num = [[parameters objectAtIndex:0] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble:ABS(num)];
|
||||
return n + m;
|
||||
}
|
||||
|
||||
- (CPDate)now
|
||||
+ (float)from:(int)n substract:(int)m
|
||||
{
|
||||
return n - m;
|
||||
}
|
||||
|
||||
+ (float)multiply:(float)n by:(int)m
|
||||
{
|
||||
return n * m;
|
||||
}
|
||||
|
||||
+ (float)divide:(float)n by:(float)m
|
||||
{
|
||||
return n / m;
|
||||
}
|
||||
|
||||
+ (float)sqrt:(float)n
|
||||
{
|
||||
return SQRT(n);
|
||||
}
|
||||
|
||||
+ (float)raise:(float)num to:(int)power
|
||||
{
|
||||
return POW(num, power);
|
||||
}
|
||||
|
||||
+ (float)abs:(float)num
|
||||
{
|
||||
return ABS(num);
|
||||
}
|
||||
|
||||
+ (CPDate)now
|
||||
{
|
||||
return [CPDate date];
|
||||
}
|
||||
|
||||
- (CPNumber)ln:(CPArray)parameters
|
||||
+ (float)ln:(float)num
|
||||
{
|
||||
if (_argc != 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var num = [[parameters objectAtIndex:0] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble:Math.log(num)];
|
||||
return LN10(num);
|
||||
}
|
||||
|
||||
- (CPNumber)exp:(CPArray)parameters
|
||||
+ (float)exp:(float)num
|
||||
{
|
||||
if (_argc != 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var num = [[parameters objectAtIndex:0] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble:EXP(num)];
|
||||
return EXP(num);
|
||||
}
|
||||
|
||||
- (CPNumber)ceiling:(CPArray)parameters
|
||||
+ (float)ceiling:(float)num
|
||||
{
|
||||
if (_argc != 1)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var num = [[parameters objectAtIndex:0] doubleValue];
|
||||
|
||||
return [CPNumber numberWithDouble:CEIL(num)];
|
||||
return CEIL(num);
|
||||
}
|
||||
|
||||
- (CPNumber)random
|
||||
+ (int)random:(int)num
|
||||
{
|
||||
return [CPNumber numberWithDouble:RAND()];
|
||||
return ROUND(RAND() * num);
|
||||
}
|
||||
|
||||
- (CPNumber)modulus:by:(CPArray)parameters
|
||||
+ (int)modulus:(int)n by:(int)n
|
||||
{
|
||||
if (_argc != 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var left = [parameters objectAtIndex:0],
|
||||
right = [parameters objectAtIndex:1];
|
||||
|
||||
return [CPNumber numberWithInt:([left intValue] % [right intValue])];
|
||||
return n % m;
|
||||
}
|
||||
|
||||
|
||||
- (id)first:(CPArray)parameters
|
||||
+ (float)chs:(int)num
|
||||
{
|
||||
if (_argc == 0)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
return [[parameters objectAtIndex:0] objectAtIndex:0];
|
||||
return -num;
|
||||
}
|
||||
|
||||
- (id)last:(CPArray)parameters
|
||||
{
|
||||
if (_argc == 0)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
return [[parameters objectAtIndex:0] lastObject];
|
||||
}
|
||||
|
||||
- (CPNumber)chs:(CPArray)parameters
|
||||
{
|
||||
if (_argc == 0)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
return [CPNumber numberWithInt: - [[parameters objectAtIndex:0] intValue]];
|
||||
}
|
||||
|
||||
- (id)index:(CPArray)parameters
|
||||
{
|
||||
if (_argc < 2)
|
||||
[CPException raise:CPInvalidArgumentException reason:"Invalid number of parameters"];
|
||||
|
||||
var left = [parameters objectAtIndex:0],
|
||||
right = [parameters objectAtIndex:1];
|
||||
|
||||
if ([left isKindOfClass: [CPDictionary class]])
|
||||
return [left objectForKey:right];
|
||||
else
|
||||
return [left objectAtIndex: [right intValue]];
|
||||
}
|
||||
|
||||
/*
|
||||
- (CPNumber)median:(CPArray)parameters
|
||||
{
|
||||
}
|
||||
- (CPNumber)mode:(CPArray)parameters
|
||||
{
|
||||
}
|
||||
- (CPNumber)stddev:(CPArray)parameters
|
||||
{
|
||||
}
|
||||
- (CPNumber)log:(CPArray)parameters
|
||||
{
|
||||
}
|
||||
- (CPNumber)raise:to:(CPArray)parameters
|
||||
{
|
||||
}
|
||||
- (CPNumber)trunc:(CPArray)parameters
|
||||
{
|
||||
}
|
||||
|
||||
// These functions are used when parsing
|
||||
*/
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
|
||||
@import "CPExpression.j"
|
||||
|
||||
@implementation CPExpression_intersectset : CPExpression
|
||||
{
|
||||
CPExpression _left;
|
||||
CPExpression _right;
|
||||
}
|
||||
|
||||
- (id)initWithLeft:(CPExpression)left right:(CPExpression)right
|
||||
{
|
||||
[super initWithExpressionType:CPIntersectSetExpressionType];
|
||||
_left = left ;
|
||||
_right = right;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var left = [coder decodeObjectForKey:@"CPExpressionUnionSetLeftExpression"];
|
||||
var right = [coder decodeObjectForKey:@"CPExpressionUnionSetRightExpression"];
|
||||
|
||||
return [self initWithLeft:left right:right];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_left forKey:@"CPExpressionUnionSetLeftExpression"];
|
||||
[coder encodeObject:_right forKey:@"CPExpressionUnionSetRightExpression"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object leftExpression] isEqual:[self leftExpression]] || ![[object rightExpression] isEqual:[self rightExpression]])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:object context:(CPDictionary)context
|
||||
{
|
||||
var right = [_right expressionValueWithObject:object context:context];
|
||||
if (![right respondsToSelector: @selector(objectEnumerator)])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The right expression for a CPIntersectSetExpressionType expression must be either a CPArray, CPDictionary or CPSet"];
|
||||
|
||||
var left = [_left expressionValueWithObject:object context:context];
|
||||
if (![left isKindOfClass:[CPSet set]])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The left expression for a CPIntersectSetExpressionType expression must a CPSet"];
|
||||
|
||||
var set = [CPSet setWithSet:left],
|
||||
e = [right objectEnumerator],
|
||||
item;
|
||||
|
||||
while (item = [e nextObject])
|
||||
if ([left containsObject:item])
|
||||
[set addObject:item];
|
||||
|
||||
return [CPExpression expressionForConstantValue:set];
|
||||
}
|
||||
|
||||
- (CPExpression )_expressionWithSubstitutionVariables:(CPDictionary )variables
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPExpression)leftExpression
|
||||
{
|
||||
return _left;
|
||||
}
|
||||
|
||||
- (CPExpression)rightExpression
|
||||
{
|
||||
return _right;
|
||||
}
|
||||
|
||||
- (CPString )description
|
||||
{
|
||||
return [_left description] +" INTERSECT "+ [_right description];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -2,61 +2,39 @@
|
||||
@import "CPExpression.j"
|
||||
@import <Foundation/CPString.j>
|
||||
@import <Foundation/CPKeyValueCoding.j>
|
||||
@import "CPExpression_function.j"
|
||||
|
||||
@implementation CPExpression_keypath : CPExpression
|
||||
@implementation CPExpression_keypath : CPExpression_function
|
||||
{
|
||||
CPString _keyPath;
|
||||
}
|
||||
|
||||
- (id)initWithKeyPath:(CPString)keyPath
|
||||
{
|
||||
[super initWithExpressionType:CPKeyPathExpressionType];
|
||||
_keyPath = keyPath ;
|
||||
|
||||
return [self initWithOperand:[CPExpression expressionForEvaluatedObject] andKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (id)initWithOperand:(CPExpression)operand andKeyPath:(CPString)keyPath
|
||||
{
|
||||
var arg = [CPExpression expressionForConstantValue:keyPath];
|
||||
// Cocoa: if it's a direct path selector is valueForKey:
|
||||
self = [super initWithTarget:operand selector:@selector(valueForKeyPath:) arguments:[arg]];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
- (CPExpression)pathExpression
|
||||
{
|
||||
var keyPath = [coder decodeObjectForKey:@"CPExpressionKeyPath"];
|
||||
|
||||
return [self initWithKeyPath:keyPath];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_keyPath forKey:@"CPExpressionKeyPath"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object keyPath] isEqualToString:[self keyPath]])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
return [[self arguments] objectAtIndex:0];
|
||||
}
|
||||
|
||||
- (CPString)keyPath
|
||||
{
|
||||
return _keyPath;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:object context:(CPDictionary)context
|
||||
{
|
||||
return [object valueForKeyPath:_keyPath];
|
||||
}
|
||||
|
||||
- (CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
|
||||
{
|
||||
return self;
|
||||
return [[self pathExpression] constantValue];
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return _keyPath;
|
||||
return [self keyPath];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
|
||||
@import "CPExpression.j"
|
||||
|
||||
@implementation CPExpression_minusset : CPExpression
|
||||
|
||||
- (id)initWithLeft:(CPExpression)left right:(CPExpression)right
|
||||
{
|
||||
[super initWithExpressionType:CPMinusSetExpressionType];
|
||||
_left = left ;
|
||||
_right = right;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var left = [coder decodeObjectForKey:@"CPExpressionMinusSetLeftExpression"];
|
||||
var right = [coder decodeObjectForKey:@"CPExpressionMinusSetRightExpression"];
|
||||
|
||||
return [self initWithLeft:left right:right];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_left forKey:@"CPExpressionMinusSetLeftExpression"];
|
||||
[coder encodeObject:_right forKey:@"CPExpressionMinusSetRightExpression"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object leftExpression] isEqual:[self leftExpression]] || ![[object rightExpression] isEqual:[self rightExpression]])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:object context:(CPDictionary)context
|
||||
{
|
||||
var right = [_right expressionValueWithObject:object context:context];
|
||||
if (![right respondsToSelector: @selector(objectEnumerator)])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The right expression for a CPIntersectSetExpressionType expression must be either a CPArray, CPDictionary or CPSet"];
|
||||
|
||||
var left = [_left expressionValueWithObject:object context:context];
|
||||
if (![left isKindOfClass:[CPSet set]])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The left expression for a CPIntersectSetExpressionType expression must a CPSet"];
|
||||
|
||||
var set = [CPSet setWithSet:left],
|
||||
e = [right objectEnumerator],
|
||||
item;
|
||||
|
||||
while (item = [e nextObject])
|
||||
[set removeObject:item];
|
||||
|
||||
return [CPExpression expressionForConstantValue:set];
|
||||
}
|
||||
|
||||
- (CPExpression )_expressionWithSubstitutionVariables:(CPDictionary )variables
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPExpression)leftExpression
|
||||
{
|
||||
return _left;
|
||||
}
|
||||
|
||||
- (CPExpression)rightExpression
|
||||
{
|
||||
return _right;
|
||||
}
|
||||
|
||||
- (CPString )description
|
||||
{
|
||||
return [_left description] +" MINUS "+ [_right description];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
|
||||
@import "CPExpression.j"
|
||||
@import <Foundation/CPArray.j>
|
||||
@import <Foundation/CPString.j>
|
||||
@import <Foundation/CPDictionary.j>
|
||||
|
||||
var CPExpressionOperatorNegate = "CPExpressionOperatorNegate";
|
||||
var CPExpressionOperatorAdd = "CPExpressionOperatorAdd";
|
||||
var CPExpressionOperatorSubtract = "CPExpressionOperatorSubtract";
|
||||
var CPExpressionOperatorMultiply = "CPExpressionOperatorMultiply";
|
||||
var CPExpressionOperatorDivide = "CPExpressionOperatorDivide";
|
||||
var CPExpressionOperatorExp = "CPExpressionOperatorExp";
|
||||
var CPExpressionOperatorAssign = "CPExpressionOperatorAssign";
|
||||
var CPExpressionOperatorKeypath = "CPExpressionOperatorKeypath";
|
||||
var CPExpressionOperatorIndex = "CPExpressionOperatorIndex";
|
||||
var CPExpressionOperatorIndexFirst = "CPExpressionOperatorIndexFirst";
|
||||
var CPExpressionOperatorIndexLast = "CPExpressionOperatorIndexLast";
|
||||
var CPExpressionOperatorIndexSize = "CPExpressionOperatorIndexSize";
|
||||
|
||||
@implementation CPExpression_operator : CPExpression
|
||||
{
|
||||
int _operator;
|
||||
CPArray _arguments;
|
||||
}
|
||||
|
||||
- (id)initWithOperator:(int)operator arguments:(CPArray)arguments
|
||||
{
|
||||
_operator = operator;
|
||||
_arguments = arguments;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (CPExpression)expressionForOperator:(CPExpressionOperator)operator arguments:(CPArray)arguments
|
||||
{
|
||||
return [self initWithOperator:operator arguments:arguments];
|
||||
}
|
||||
|
||||
- (CPArray)arguments
|
||||
{
|
||||
return _arguments;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
var result = [CPString string],
|
||||
args = [CPArray array],
|
||||
count = [_arguments count],
|
||||
i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
var check = [_arguments objectAtIndex:i],
|
||||
precedence = [check description];
|
||||
|
||||
if ([check isKindOfClass:[CPExpression_operator class]])
|
||||
precedence = [CPString stringWithFormat:@"(%@)", precedence];
|
||||
|
||||
[args addObject:precedence];
|
||||
}
|
||||
|
||||
switch (_operator)
|
||||
{
|
||||
case CPExpressionOperatorNegate :
|
||||
result = result + [CPString stringWithFormat:@"-%@", [args objectAtIndex:0]];
|
||||
break;
|
||||
case CPExpressionOperatorAdd :
|
||||
result = result + [CPString stringWithFormat:@"%@ + %@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorSubtract :
|
||||
result = result + [CPString stringWithFormat:@"%@ - %@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorMultiply :
|
||||
result = result + [CPString stringWithFormat:@"%@ * %@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorDivide :
|
||||
result = result + [CPString stringWithFormat:@"%@ / %@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorExp :
|
||||
result = result + [CPString stringWithFormat:@"%@ ** %@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorAssign :
|
||||
result = result + [CPString stringWithFormat:@"%@ := %@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorKeypath :
|
||||
result = result + [CPString stringWithFormat:@"%@.%@", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorIndex :
|
||||
result = result + [CPString stringWithFormat:@"%@[%@]", [args objectAtIndex:0], [args objectAtIndex:1]];
|
||||
break;
|
||||
case CPExpressionOperatorIndexFirst :
|
||||
result = result + [CPString stringWithFormat:@"%@[FIRST]", [args objectAtIndex:0]];
|
||||
break;
|
||||
case CPExpressionOperatorIndexLast :
|
||||
result = result + [CPString stringWithFormat:@"%@[LAST]", [args objectAtIndex:0]];
|
||||
break;
|
||||
case CPExpressionOperatorIndexSize :
|
||||
result = result + [CPString stringWithFormat:@"%@[SIZE]", [args objectAtIndex:0]];
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (CPExpression)_expressionWithSubstitutionVariables:(CPDictionary)variables
|
||||
{
|
||||
var array = [CPArray array],
|
||||
count = [_arguments count],
|
||||
i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
[array addObject:[[_arguments objectAtIndex:i] _expressionWithSubstitutionVariables:variables]];
|
||||
|
||||
return [CPExpression_operator expressionForOperator:_operator arguments:array];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -4,13 +4,20 @@
|
||||
@import <Foundation/CPDictionary.j>
|
||||
@import <Foundation/CPCoder.j>
|
||||
|
||||
@implementation CPExpression_self : CPExpression{}
|
||||
var defaultInstance = nil;
|
||||
@implementation CPExpression_self : CPExpression
|
||||
{
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
[super initWithExpressionType:CPEvaluatedObjectExpressionType];
|
||||
if (defaultInstance == nil)
|
||||
{
|
||||
[super initWithExpressionType:CPEvaluatedObjectExpressionType];
|
||||
defaultInstance = self;
|
||||
}
|
||||
|
||||
return self;
|
||||
return defaultInstance;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
@@ -24,10 +31,10 @@
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
return (object == self);
|
||||
return (object === self);
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:object context:(CPDictionary)context
|
||||
- (id)expressionValueWithObject:(id)object context:(CPDictionary)context
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
|
||||
@import "CPExpression.j"
|
||||
|
||||
@implementation CPExpression_set : CPExpression
|
||||
{
|
||||
CPExpression _left;
|
||||
CPExpression _right;
|
||||
}
|
||||
|
||||
- (id)initWithType:(int)type left:(CPExpression)left right:(CPExpression)right
|
||||
{
|
||||
[super initWithExpressionType:type];
|
||||
_left = left;
|
||||
_right = right;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
if (object.isa != self.isa || [object expressionType] != [self expressionType] || ![[object leftExpression] isEqual:[self leftExpression]] || ![[object rightExpression] isEqual:[self rightExpression]])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:object context:(CPDictionary)context
|
||||
{
|
||||
var right = [_right expressionValueWithObject:object context:context];
|
||||
if ([right isKindOfClass:[CPArray class]]) // Or we could do [[right objectEnumerator] allObjects]
|
||||
right = [CPSet setWithArray:right];
|
||||
else if ([right isKindOfClass:[CPDictionary class]])
|
||||
right = [CPSet setWithArray:[right allValues]];
|
||||
else if (![right isKindOfClass:[CPSet class]])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The right expression for a CP*SetExpressionType expression must evaluate to a CPArray, CPDictionary or CPSet"];
|
||||
|
||||
var left = [_left expressionValueWithObject:object context:context];
|
||||
if (![left isKindOfClass:[CPSet class]])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The left expression for a CP*SetExpressionType expression must evaluate to a CPSet"];
|
||||
|
||||
var result = [left copy];
|
||||
switch (_type)
|
||||
{
|
||||
case CPIntersectSetExpressionType : [result intersectSet:right];
|
||||
break;
|
||||
case CPUnionSetExpressionType : [result unionSet:right];
|
||||
break;
|
||||
case CPMinusSetExpressionType : [result minusSet:right];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return [CPExpression expressionForConstantValue:result];
|
||||
}
|
||||
|
||||
- (CPExpression )_expressionWithSubstitutionVariables:(CPDictionary )variables
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPExpression)leftExpression
|
||||
{
|
||||
return _left;
|
||||
}
|
||||
|
||||
- (CPExpression)rightExpression
|
||||
{
|
||||
return _right;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
var desc;
|
||||
switch (_type)
|
||||
{
|
||||
case CPIntersectSetExpressionType : desc = @" INTERSECT ";
|
||||
break;
|
||||
case CPUnionSetExpressionType : desc = @" UNION ";
|
||||
break;
|
||||
case CPMinusSetExpressionType : desc = @" MINUS ";
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return [_left description] + desc + [_right description];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPLeftExpressionKey = @"CPLeftExpression",
|
||||
CPRightExpressionKey = @"CPRightExpression",
|
||||
CPExpressionType = @"CPExpressionType";
|
||||
|
||||
@implementation CPExpression_set (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var left = [coder decodeObjectForKey:CPLeftExpressionKey],
|
||||
right = [coder decodeObjectForKey:CPRightExpressionKey],
|
||||
type = [coder decodeIntForKey:CPExpressionType];
|
||||
|
||||
return [self initWithType:type left:left right:right];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_left forKey:CPLeftExpressionKey];
|
||||
[coder encodeObject:_right forKey:CPRightExpressionKey];
|
||||
[coder encodeInt:_type forKey:CPExpressionType];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
@import "CPExpression.j"
|
||||
|
||||
@implementation CPExpression_unionset : CPExpression
|
||||
|
||||
- (id)initWithLeft:(CPExpression)left right:(CPExpression)right
|
||||
{
|
||||
[super initWithExpressionType:CPUnionSetExpressionType];
|
||||
_left = left;
|
||||
_right = right;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var left = [coder decodeObjectForKey:@"CPExpressionUnionSetLeftExpression"],
|
||||
right = [coder decodeObjectForKey:@"CPExpressionUnionSetRightExpression"];
|
||||
|
||||
return [self initWithLeft:left right:right];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_left forKey:@"CPExpressionUnionSetLeftExpression"];
|
||||
[coder encodeObject:_right forKey:@"CPExpressionUnionSetRightExpression"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
return YES;
|
||||
|
||||
if (object.isa != self.isa
|
||||
|| [object expressionType] != [self expressionType]
|
||||
|| ![[object leftExpression] isEqual:[self leftExpression]]
|
||||
|| ![[object rightExpression] isEqual:[self rightExpression]])
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)expressionValueWithObject:object context:(CPDictionary )context
|
||||
{
|
||||
var right = [_right expressionValueWithObject:object context:context];
|
||||
if (![right respondsToSelector: @selector(objectEnumerator)])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The right expression for a CPIntersectSetExpressionType expression must be either a CPArray, CPDictionary or CPSet"];
|
||||
|
||||
var left = [_left expressionValueWithObject:object context:context];
|
||||
if (![left isKindOfClass:[CPSet set]])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"The left expression for a CPIntersectSetExpressionType expression must a CPSet"];
|
||||
|
||||
var unionset = [CPSet setWithSet:left],
|
||||
e = [right objectEnumerator],
|
||||
item;
|
||||
|
||||
while (item = [e nextObject])
|
||||
[unionset addObject:item];
|
||||
|
||||
return [CPExpression expressionForConstantValue:unionset];
|
||||
}
|
||||
|
||||
- (CPExpression )_expressionWithSubstitutionVariables:(CPDictionary )variables
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CPExpression)leftExpression
|
||||
{
|
||||
return _left;
|
||||
}
|
||||
|
||||
- (CPExpression)rightExpression
|
||||
{
|
||||
return _right;
|
||||
}
|
||||
|
||||
- (CPString )description
|
||||
{
|
||||
return [_left description] +" UNION "+ [_right description];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -16,17 +16,6 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var variable = [coder decodeObjectForKey:@"CPExpressionVariable"];
|
||||
return [self initWithVariable:variable];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_variable forKey:@"CPExpressionVariable"];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self == object)
|
||||
@@ -63,6 +52,22 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
var CPVariableKey = @"CPVariable";
|
||||
|
||||
@implementation CPExpression_variable (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)coder
|
||||
{
|
||||
var variable = [coder decodeObjectForKey:CPVariableKey];
|
||||
return [self initWithVariable:variable];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)coder
|
||||
{
|
||||
[coder encodeObject:_variable forKey:CPVariableKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
@param … A comma-separated list of arguments to substitute into format.
|
||||
@return A new predicate formed by creating a new string with format and parsing the result.
|
||||
*/
|
||||
+ (CPPredicate)predicateWithFormat:(CPString) format, ...
|
||||
+ (CPPredicate)predicateWithFormat:(CPString)format, ...
|
||||
{
|
||||
if (!format)
|
||||
[CPException raise:CPInvalidArgumentException reason:_cmd + " the format can't be 'nil'"];
|
||||
@@ -238,7 +238,7 @@ function(newValue)\
|
||||
unsigned _retrieved;
|
||||
}
|
||||
|
||||
- (id) initWithString:(CPString)format args:(CPArray)args
|
||||
- (id)initWithString:(CPString)format args:(CPArray)args
|
||||
{
|
||||
self = [super initWithString:format];
|
||||
if (self != nil)
|
||||
@@ -248,15 +248,15 @@ function(newValue)\
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) nextArg
|
||||
- (id)nextArg
|
||||
{
|
||||
return [_args nextObject];
|
||||
}
|
||||
|
||||
- (BOOL)scanPredicateKeyword:(CPString)key
|
||||
{
|
||||
var loc = [self scanLocation];
|
||||
var c;
|
||||
var loc = [self scanLocation],
|
||||
c;
|
||||
|
||||
[self setCaseSensitive:NO];
|
||||
if (![self scanString:key intoString:NULL])
|
||||
@@ -274,7 +274,7 @@ function(newValue)\
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CPPredicate) parse
|
||||
- (CPPredicate)parse
|
||||
{
|
||||
var r = nil;
|
||||
|
||||
@@ -296,12 +296,12 @@ function(newValue)\
|
||||
return r;
|
||||
}
|
||||
|
||||
- (CPPredicate) parsePredicate
|
||||
- (CPPredicate)parsePredicate
|
||||
{
|
||||
return [self parseAnd];
|
||||
}
|
||||
|
||||
- (CPPredicate) parseAnd
|
||||
- (CPPredicate)parseAnd
|
||||
{
|
||||
var l = [self parseOr];
|
||||
|
||||
@@ -333,7 +333,7 @@ function(newValue)\
|
||||
return l;
|
||||
}
|
||||
|
||||
- (CPPredicate) parseNot
|
||||
- (CPPredicate)parseNot
|
||||
{
|
||||
if ([self scanString:@"(" intoString:NULL])
|
||||
{
|
||||
@@ -361,7 +361,7 @@ function(newValue)\
|
||||
return [self parseComparison];
|
||||
}
|
||||
|
||||
- (CPPredicate) parseOr
|
||||
- (CPPredicate)parseOr
|
||||
{
|
||||
var l = [self parseNot];
|
||||
while ([self scanPredicateKeyword:@"OR"] || [self scanPredicateKeyword:@"||"])
|
||||
@@ -392,7 +392,7 @@ function(newValue)\
|
||||
return l;
|
||||
}
|
||||
|
||||
- (CPPredicate) parseComparison
|
||||
- (CPPredicate)parseComparison
|
||||
{
|
||||
var modifier = CPDirectPredicateModifier,
|
||||
type = 0,
|
||||
@@ -400,8 +400,7 @@ function(newValue)\
|
||||
left,
|
||||
right,
|
||||
p,
|
||||
negate = NO,
|
||||
swap = NO;
|
||||
negate = NO;
|
||||
|
||||
if ([self scanPredicateKeyword:@"ANY"])
|
||||
{
|
||||
@@ -469,36 +468,11 @@ function(newValue)\
|
||||
}
|
||||
else if ([self scanPredicateKeyword:@"CONTAINS"])
|
||||
{
|
||||
type = CPInPredicateOperatorType;
|
||||
swap = YES;
|
||||
type = CPContainsPredicateOperatorType;
|
||||
}
|
||||
else if ([self scanPredicateKeyword:@"BETWEEN"])
|
||||
{
|
||||
var exp = [self parseSimpleExpression],
|
||||
a = [exp constantValue],
|
||||
lower, upper,
|
||||
lexp, uexp,
|
||||
lp, up;
|
||||
|
||||
if (![a isKindOfClass:[CPArray class]])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"BETWEEN operator requires array argument"];
|
||||
|
||||
lower = [a objectAtIndex:0];
|
||||
upper = [a objectAtIndex:1];
|
||||
lexp = [CPExpression expressionForConstantValue:lower];
|
||||
uexp = [CPExpression expressionForConstantValue:upper];
|
||||
lp = [CPComparisonPredicate predicateWithLeftExpression:left
|
||||
rightExpression:lexp
|
||||
modifier:modifier
|
||||
type:CPGreaterThanPredicateOperatorType
|
||||
options:opts];
|
||||
up = [CPComparisonPredicate predicateWithLeftExpression:left
|
||||
rightExpression:uexp
|
||||
modifier:modifier
|
||||
type:CPLessThanPredicateOperatorType
|
||||
options:opts];
|
||||
return [CPCompoundPredicate andPredicateWithSubpredicates:
|
||||
[CPArray arrayWithObjects:lp, up]];
|
||||
type = CPBetweenPredicateOperatorType;
|
||||
}
|
||||
else
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid comparison predicate: "+ [[self string] substringFromIndex: [self scanLocation]]];
|
||||
@@ -518,14 +492,6 @@ function(newValue)\
|
||||
|
||||
right = [self parseExpression];
|
||||
|
||||
if (swap == YES)
|
||||
{
|
||||
var tmp = left;
|
||||
|
||||
left = right;
|
||||
right = tmp;
|
||||
}
|
||||
|
||||
p = [CPComparisonPredicate predicateWithLeftExpression:left
|
||||
rightExpression:right
|
||||
modifier:modifier
|
||||
@@ -535,12 +501,12 @@ function(newValue)\
|
||||
return negate ? [CPCompoundPredicate notPredicateWithSubpredicate:p]:p;
|
||||
}
|
||||
|
||||
- (CPExpression) parseExpression
|
||||
- (CPExpression)parseExpression
|
||||
{
|
||||
return [self parseBinaryExpression];
|
||||
}
|
||||
|
||||
- (CPExpression) parseSimpleExpression
|
||||
- (CPExpression)parseSimpleExpression
|
||||
{
|
||||
var identifier,
|
||||
location,
|
||||
@@ -548,11 +514,11 @@ function(newValue)\
|
||||
dbl;
|
||||
|
||||
if ([self scanDouble:REFERENCE(dbl)])
|
||||
return [CPExpression expressionForConstantValue:[CPNumber numberWithDouble:dbl]];
|
||||
return [CPExpression expressionForConstantValue:dbl];
|
||||
|
||||
// FIXME: handle integer, hex constants, 0x 0o 0b
|
||||
if ([self scanString:@"-" intoString:NULL])
|
||||
return [CPExpression expressionForFunction:@"chs" arguments:[CPArray arrayWithObject:[self parseExpression]]];
|
||||
return [CPExpression expressionForFunction:@"chs:" arguments:[CPArray arrayWithObject:[self parseExpression]]];
|
||||
|
||||
if ([self scanString:@"(" intoString:NULL])
|
||||
{
|
||||
@@ -578,7 +544,7 @@ function(newValue)\
|
||||
if (![self scanString:@"}" intoString:NULL])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Missing } in aggregate"];
|
||||
|
||||
return [CPExpression expressionForConstantValue:a];
|
||||
return [CPExpression expressionForAggregate:a];
|
||||
}
|
||||
|
||||
if ([self scanPredicateKeyword:@"NULL"] || [self scanPredicateKeyword:@"NIL"])
|
||||
@@ -676,33 +642,36 @@ function(newValue)\
|
||||
if ([self scanString:@"\"" intoString:NULL])
|
||||
{
|
||||
var skip = [self charactersToBeSkipped],
|
||||
str;
|
||||
str = @"";
|
||||
|
||||
[self setCharactersToBeSkipped:nil];
|
||||
if ([self scanUpToString:@"\"" intoString:REFERENCE(str)] == NO)
|
||||
[self scanUpToString:@"\"" intoString:REFERENCE(str)];
|
||||
|
||||
if ([self scanString:@"\"" intoString:NULL] == NO)
|
||||
{
|
||||
[self setCharactersToBeSkipped:skip];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid double quoted literal at "+location];
|
||||
}
|
||||
|
||||
[self scanString:@"\"" intoString:NULL];
|
||||
[self setCharactersToBeSkipped:skip];
|
||||
|
||||
return [CPExpression expressionForConstantValue:str];
|
||||
}
|
||||
|
||||
if ([self scanString:@"'" intoString:NULL])
|
||||
{
|
||||
var skip = [self charactersToBeSkipped],
|
||||
str;
|
||||
str = @"";
|
||||
|
||||
[self setCharactersToBeSkipped:nil];
|
||||
if ([self scanUpToString:@"'" intoString:REFERENCE(str)] == NO)
|
||||
[self scanUpToString:@"'" intoString:REFERENCE(str)];
|
||||
|
||||
if ([self scanString:@"'" intoString:NULL] == NO)
|
||||
{
|
||||
[self setCharactersToBeSkipped:skip];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid single quoted literal at "+location];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid double quoted literal at " + location];
|
||||
}
|
||||
|
||||
[self scanString:@"'" intoString:NULL];
|
||||
[self setCharactersToBeSkipped:skip];
|
||||
|
||||
return [CPExpression expressionForConstantValue:str];
|
||||
@@ -713,9 +682,9 @@ function(newValue)\
|
||||
var e = [self parseExpression];
|
||||
|
||||
if (![e keyPath])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid keypath identifier: "+e];
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid keypath identifier: " + e];
|
||||
|
||||
return [CPExpression expressionForKeyPath:[e keyPath]+"@"];
|
||||
return [CPExpression expressionForKeyPath:[e keyPath] + "@"];
|
||||
}
|
||||
|
||||
[self scanString:@"#" intoString:NULL];
|
||||
@@ -759,28 +728,6 @@ function(newValue)\
|
||||
}
|
||||
left = [CPExpression expressionForFunction:[left keyPath] arguments:args];
|
||||
}
|
||||
else if ([self scanString:@"[" intoString:NULL])
|
||||
{
|
||||
// index expression
|
||||
if ([self scanPredicateKeyword:@"FIRST"])
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"first" arguments:[CPArray arrayWithObject:[self parseExpression]]];
|
||||
}
|
||||
else if ([self scanPredicateKeyword:@"LAST"])
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"last" arguments:[CPArray arrayWithObject:[self parseExpression]]];
|
||||
}
|
||||
else if ([self scanPredicateKeyword:@"SIZE"])
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"count" arguments:[CPArray arrayWithObject:[self parseExpression]]];
|
||||
}
|
||||
else
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"index" arguments:[CPArray arrayWithObjects:left, [self parseExpression]]];
|
||||
}
|
||||
if (![self scanString:@"]" intoString:NULL])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Missing ] in index argument"];
|
||||
}
|
||||
else if ([self scanString:@"." intoString:NULL])
|
||||
{
|
||||
// keypath - this parser allows for (a).(b.c)
|
||||
@@ -791,12 +738,38 @@ function(newValue)\
|
||||
if (![left keyPath])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid left keypath:" + left];
|
||||
|
||||
var right = [self parseExpression];
|
||||
var right = [self parseSimpleExpression];
|
||||
if (![right keyPath])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Invalid right keypath:" + right];
|
||||
|
||||
// concatenate
|
||||
left = [CPExpression expressionForKeyPath:[left keyPath]+ "." + [right keyPath]];
|
||||
|
||||
}
|
||||
else if ([self scanString:@"[" intoString:NULL])
|
||||
{
|
||||
// index expression
|
||||
if ([self scanPredicateKeyword:@"FIRST"])
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"first:" arguments:[CPArray arrayWithObject:left]];
|
||||
}
|
||||
else if ([self scanPredicateKeyword:@"LAST"])
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"last:" arguments:[CPArray arrayWithObject:left]];
|
||||
}
|
||||
else if ([self scanPredicateKeyword:@"SIZE"])
|
||||
{
|
||||
left = [CPExpression expressionForFunction:@"count:" arguments:[CPArray arrayWithObject:left]];
|
||||
}
|
||||
else
|
||||
{
|
||||
var integer;
|
||||
if ([self scanInt:REFERENCE(integer)])
|
||||
left = [CPExpression expressionForFunction:@"fromObject:index:" arguments:[CPArray arrayWithObjects:left, [CPExpression expressionForConstantValue:integer]]];
|
||||
}
|
||||
|
||||
if (![self scanString:@"]" intoString:NULL])
|
||||
[CPException raise:CPInvalidArgumentException reason:@"Missing ] in index argument"];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -817,7 +790,7 @@ function(newValue)\
|
||||
if ([self scanString:@"**" intoString:NULL])
|
||||
{
|
||||
right = [self parseFunctionalExpression];
|
||||
left = [CPExpression expressionForFunction:@"pow" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
left = [CPExpression expressionForFunction:@"raise:to:" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -837,12 +810,12 @@ function(newValue)\
|
||||
if ([self scanString:@"*" intoString:NULL])
|
||||
{
|
||||
right = [self parsePowerExpression];
|
||||
left = [CPExpression expressionForFunction:@"_mul" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
left = [CPExpression expressionForFunction:@"multiply:by:" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
}
|
||||
else if ([self scanString:@"/" intoString:NULL])
|
||||
{
|
||||
right = [self parsePowerExpression];
|
||||
left = [CPExpression expressionForFunction:@"_div" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
left = [CPExpression expressionForFunction:@"divide:by:" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -862,12 +835,12 @@ function(newValue)\
|
||||
if ([self scanString:@"+" intoString:NULL])
|
||||
{
|
||||
right = [self parseMultiplicationExpression];
|
||||
left = [CPExpression expressionForFunction:@"_add" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
left = [CPExpression expressionForFunction:@"add:to:" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
}
|
||||
else if ([self scanString:@"-" intoString:NULL])
|
||||
{
|
||||
right = [self parseMultiplicationExpression];
|
||||
left = [CPExpression expressionForFunction:@"_sub" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
left = [CPExpression expressionForFunction:@"from:substract:" arguments:[CPArray arrayWithObjects:left, right]];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -903,6 +876,3 @@ function(newValue)\
|
||||
@import "CPComparisonPredicate.j"
|
||||
|
||||
@import "CPExpression.j"
|
||||
@import "CPExpression_operator.j"
|
||||
@import "CPExpression_aggregate.j"
|
||||
@import "CPExpression_assignment.j"
|
||||
+16
-11
@@ -22,8 +22,8 @@
|
||||
|
||||
// sprintf:
|
||||
|
||||
var formatRegex = new RegExp("([^%]+|%[\\+\\-\\ \\#0]*[0-9\\*]*(.[0-9\\*]+)?[hlL]?[cbBdieEfgGosuxXpn%@])", "g");
|
||||
var tagRegex = new RegExp("(%)([\\+\\-\\ \\#0]*)([0-9\\*]*)((.[0-9\\*]+)?)([hlL]?)([cbBdieEfgGosuxXpn%@])");
|
||||
var formatRegex = new RegExp("([^%]+|%(?:\\d+\\$)?[\\+\\-\\ \\#0]*[0-9\\*]*(.[0-9\\*]+)?[hlL]?[cbBdieEfgGosuxXpn%@])", "g");
|
||||
var tagRegex = new RegExp("(%)(?:(\\d+)\\$)?([\\+\\-\\ \\#0]*)([0-9\\*]*)((?:.[0-9\\*]+)?)([hlL]?)([cbBdieEfgGosuxXpn%@])");
|
||||
|
||||
exports.sprintf = function(format)
|
||||
{
|
||||
@@ -55,21 +55,27 @@ exports.sprintf = function(format)
|
||||
}
|
||||
|
||||
var percentSign = subtokens[1],
|
||||
flags = subtokens[2],
|
||||
widthString = subtokens[3],
|
||||
precisionString = subtokens[4],
|
||||
argIndex = subtokens[2],
|
||||
flags = subtokens[3],
|
||||
widthString = subtokens[4],
|
||||
precisionString = subtokens[5],
|
||||
length = subtokens[6],
|
||||
specifier = subtokens[7];
|
||||
|
||||
if (argIndex === undefined || argIndex === null || argIndex === "")
|
||||
argIndex = arg++;
|
||||
else
|
||||
argIndex = Number(argIndex);
|
||||
|
||||
var width = null;
|
||||
if (widthString == "*")
|
||||
width = arguments[arg++];
|
||||
width = arguments[argIndex];
|
||||
else if (widthString != "")
|
||||
width = Number(widthString);
|
||||
|
||||
var precision = null;
|
||||
if (precisionString == ".*")
|
||||
precision = arguments[arg++];
|
||||
precision = arguments[argIndex];
|
||||
else if (precisionString != "")
|
||||
precision = Number(precisionString.substring(1));
|
||||
|
||||
@@ -80,7 +86,7 @@ exports.sprintf = function(format)
|
||||
|
||||
if (RegExp("[bBdiufeExXo]").test(specifier))
|
||||
{
|
||||
var num = Number(arguments[arg++]);
|
||||
var num = Number(arguments[argIndex]);
|
||||
|
||||
var sign = "";
|
||||
if (num < 0)
|
||||
@@ -154,12 +160,11 @@ exports.sprintf = function(format)
|
||||
if (specifier == "%")
|
||||
subresult = "%";
|
||||
else if (specifier == "c")
|
||||
subresult = String(arguments[arg++]).charAt(0);
|
||||
subresult = String(arguments[argIndex]).charAt(0);
|
||||
else if (specifier == "s" || specifier == "@")
|
||||
subresult = String(arguments[arg++]);
|
||||
subresult = String(arguments[argIndex]);
|
||||
else if (specifier == "p" || specifier == "n")
|
||||
{
|
||||
arg++;
|
||||
subresult = "";
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
objects;
|
||||
|
||||
dict = [[CPDictionary alloc] init];
|
||||
[dict setObject: @"A Title" forKey:@"title"];
|
||||
[dict setObject: @"Title" forKey:@"title"];
|
||||
|
||||
var keys = [CPArray arrayWithObjects:@"Name",@"Age",@"Children"];
|
||||
objects = [CPArray arrayWithObjects:@"John",[CPNumber numberWithInt:34],[CPArray arrayWithObjects:@"Kid1", @"Kid2"]];
|
||||
@@ -35,7 +35,8 @@
|
||||
{
|
||||
var expression_keypath = [CPExpression expressionForKeyPath:@"name"];
|
||||
[self assertNotNull:expression_keypath message:"KeyPath Expression should not be nil"];
|
||||
|
||||
[self assertTrue:[expression_keypath keyPath] == @"name" message:"-keyPath should not be \"name\""];
|
||||
|
||||
var expression_str = [CPExpression expressionForConstantValue:@"j[a-z]an"];
|
||||
[self assertNotNull:expression_str message:"ConstantValue Expression should not be nil"];
|
||||
|
||||
@@ -51,17 +52,20 @@
|
||||
var expression_function = [CPExpression expressionForFunction:@"sum:" arguments:[CPArray arrayWithObjects:expression_num,expression_num]];
|
||||
[self assertNotNull:expression_function message:"Function Expression should not be nil"];
|
||||
|
||||
var expression_self = [CPExpression expressionForEvaluatedObject];
|
||||
[self assertNotNull:expression_self message:"Function Expression should not be nil"];
|
||||
expression_function = [CPExpression expressionForFunction:expression_num selectorName:@"isEqual:" arguments:[CPArray arrayWithObjects:expression_num]];
|
||||
[self assertNotNull:expression_function message:"Function Expression with target and selector should not be nil"];
|
||||
|
||||
var expression_aggregate = [CPExpression expressionForAggregate:[CPArray arrayWithObjects:expression_str,expression_num,expression_function]];
|
||||
var expression_self = [CPExpression expressionForEvaluatedObject];
|
||||
[self assertNotNull:expression_self message:"Self Expression should not be nil"];
|
||||
|
||||
var expression_aggregate = [CPExpression expressionForAggregate:[CPArray arrayWithObjects:expression_str,expression_num]];
|
||||
[self assertNotNull:expression_aggregate message:"Aggregate Expression should not be nil"];
|
||||
|
||||
var expression_subquery = [CPExpression expressionForSubquery:expression_collection usingIteratorVariable:@"self" predicate:[CPPredicate predicateWithValue:YES]];
|
||||
// [self assertNotNull:expression_subquery message:"Subquery Expression should not be nil"];
|
||||
|
||||
var set = [CPSet setWithObjects:@"a",@"b",@"d"];
|
||||
var array = [CPArray arrayWithObjects:@"a",@"b",@"d"];
|
||||
var set = [CPExpression expressionForConstantValue:[CPSet setWithObjects:@"a",@"b",@"c"]];
|
||||
var array = [CPExpression expressionForConstantValue:[CPArray arrayWithObjects:@"a",@"b",@"d"]];
|
||||
|
||||
var expression_intersect = [CPExpression expressionForIntersectSet:set with:array];
|
||||
[self assertNotNull:expression_intersect message:"IntersectSet Expression should not be nil"];
|
||||
@@ -73,16 +77,40 @@
|
||||
[self assertNotNull:expression_minusset message:"MinusSet Expression should not be nil"];
|
||||
}
|
||||
|
||||
- (void)testFunctionExpression
|
||||
- (void)testSetExpressionEvaluation
|
||||
{
|
||||
var function_exp = [CPExpression expressionForFunction:"sum:" arguments:[CPArray arrayWithObjects:[CPExpression expressionForConstantValue:1],[CPExpression expressionForConstantValue:2],[CPExpression expressionForConstantValue:3]]];
|
||||
var left = [CPExpression expressionForConstantValue:[CPSet setWithObjects:@"a",@"b",@"c"]];
|
||||
var right = [CPExpression expressionForConstantValue:[CPArray arrayWithObjects:@"a",@"b",@"d"]];
|
||||
|
||||
var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:function_exp rightExpression:[CPExpression expressionForConstantValue:3] modifier:CPDirectPredicateModifier type:CPGreaterThanPredicateOperatorType options:0];
|
||||
var expression = [CPExpression expressionForIntersectSet:left with:right];
|
||||
var eval = [[expression expressionValueWithObject:nil context:nil] constantValue];
|
||||
[self assertTrue:[eval isEqualToSet:[CPSet setWithObjects:@"a",@"b"]] message:"Result should be {(a, b)}, is " + eval];
|
||||
|
||||
expression = [CPExpression expressionForUnionSet:left with:right];
|
||||
eval = [[expression expressionValueWithObject:nil context:nil] constantValue];
|
||||
[self assertTrue:[eval isEqualToSet:[CPSet setWithObjects:@"a",@"b",@"c",@"d"]] message:"Result should be {(a, b, c, d)}, is " + eval];
|
||||
|
||||
expression = [CPExpression expressionForMinusSet:left with:right];
|
||||
eval = [[expression expressionValueWithObject:nil context:nil] constantValue];
|
||||
[self assertTrue:[eval isEqualToSet:[CPSet setWithObjects:@"c"]] message:"Result should be {(c)}, is " + eval];
|
||||
}
|
||||
|
||||
- (void)testFunctionExpressionEvaluation
|
||||
{
|
||||
var expression = [CPExpression expressionForConstantValue:[1,2,3]];
|
||||
var function_exp = [CPExpression expressionForFunction:"sum:" arguments:[expression]];
|
||||
|
||||
var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:function_exp rightExpression:[CPExpression expressionForConstantValue:6] modifier:CPDirectPredicateModifier type:CPEqualToPredicateOperatorType options:0];
|
||||
[self assertTrue:[pred evaluateWithObject:nil] message:[pred description] + " should be true"];
|
||||
|
||||
var operand = [CPExpression expressionForConstantValue:@"text"];
|
||||
var arg = [CPExpression expressionForConstantValue:2];
|
||||
function_exp = [CPExpression expressionForFunction:operand selectorName:@"substringFromIndex:" arguments:[arg]];
|
||||
pred = [[CPComparisonPredicate alloc] initWithLeftExpression:function_exp rightExpression:[CPExpression expressionForConstantValue:@"xt"] modifier:CPDirectPredicateModifier type:CPEqualToPredicateOperatorType options:0];
|
||||
[self assertTrue:[pred evaluateWithObject:nil] message:[pred description] + " should be true"];
|
||||
}
|
||||
|
||||
- (void)testVariableExpression
|
||||
- (void)testVariableExpressionEvaluation
|
||||
{
|
||||
var variable_exp = [CPExpression expressionForVariable:@"variable"];
|
||||
var pred = [[CPComparisonPredicate alloc] initWithLeftExpression:[CPExpression expressionForKeyPath:@"Record1.Age"] rightExpression:variable_exp modifier:CPDirectPredicateModifier type:CPGreaterThanPredicateOperatorType options:0];
|
||||
@@ -205,12 +233,56 @@
|
||||
predicate = [CPPredicate predicateWithFormat: @"%f > %K", 40.5, @"Record1.Age"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
// TEST Aggregate
|
||||
// TEST KeyPath
|
||||
predicate = [CPPredicate predicateWithFormat: @"%@ IN %K", @"Kid1", @"Record1.Children"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat: @"%K CONTAINS %@", @"Record1.Children", @"Kid1"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat: @"ANY %K == %@", @"Record2.Children", @"Girl1"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
// Test Aggregate
|
||||
predicate = [CPPredicate predicateWithFormat:@"{Record1 .Name, Record1.Age} = {'John',34}"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
// Test Symbolic token
|
||||
predicate = [CPPredicate predicateWithFormat:@"Record1.Children[FIRST] = 'Kid1'"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"Record1.Children[1] = 'Kid2'"];
|
||||
[self assertTrue:[predicate evaluateWithObject:dict] message:[predicate description] + " should be true"];
|
||||
|
||||
// Test arithm
|
||||
var n = 2;
|
||||
predicate = [CPPredicate predicateWithFormat:@"SELF +1 = 3"];
|
||||
[self assertTrue:[predicate evaluateWithObject:n] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"SELF- 1 = 1"];
|
||||
[self assertTrue:[predicate evaluateWithObject:n] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"SELF / 2 = 1"];
|
||||
[self assertTrue:[predicate evaluateWithObject:n] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"SELF / 2 = 1"];
|
||||
[self assertTrue:[predicate evaluateWithObject:n] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"SELF* 2 = 4"];
|
||||
[self assertTrue:[predicate evaluateWithObject:n] message:[predicate description] + " should be true"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat:@"SELF** 3 = 8"];
|
||||
[self assertTrue:[predicate evaluateWithObject:n] message:[predicate description] + " should be true"];
|
||||
|
||||
// TEST Operator type
|
||||
predicate = [CPPredicate predicateWithFormat: @"a CONTAINS[c] \"b\""];
|
||||
[self assertTrue:([predicate predicateOperatorType] == CPContainsPredicateOperatorType) message:[predicate description] + " operator should be a CPContainsPredicateOperatorType"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat: @"a BETWEEN {%f,%f}", 20, 40];
|
||||
[self assertTrue:([predicate predicateOperatorType] == CPBetweenPredicateOperatorType) message:[predicate description] + " operator should be a CPBetweenPredicateOperatorType"];
|
||||
|
||||
predicate = [CPPredicate predicateWithFormat: @"a CONTAINS \"\""];
|
||||
[self assertNotNull:predicate message:[predicate description] + " should not be nil"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,20 +1,37 @@
|
||||
|
||||
// TODO: add many many more of these...
|
||||
var sprintfTestCases = [
|
||||
[["[%@]", "hello world"], "[hello world]"],
|
||||
[["[%d]", 123], "[123]"],
|
||||
[["[%f]", 123.1234], "[123.1234]"],
|
||||
[["[%d]", 123.1234], "[123]"]
|
||||
];
|
||||
var sprintf = ObjectiveJ.sprintf;
|
||||
|
||||
@implementation sprintfTest : OJTestCase
|
||||
|
||||
- (void)test_sprintf
|
||||
// TODO: add many many more of these...
|
||||
|
||||
- (void)testObjectWithPrefixAndSuffix
|
||||
{
|
||||
for (var i = 0; i < sprintfTestCases.length; i++)
|
||||
{
|
||||
[self assert:ObjectiveJ.sprintf.apply(null, sprintfTestCases[i][0]) equals:sprintfTestCases[i][1]];
|
||||
}
|
||||
[self assert:@"[hello world]" equals:sprintf(@"[%@]", @"hello world")];
|
||||
}
|
||||
|
||||
- (void)testDecimalWithPrefixAndSuffix
|
||||
{
|
||||
[self assert:@"[123]" equals:sprintf(@"[%d]", 123)];
|
||||
}
|
||||
|
||||
- (void)testFloatWithPrefixAndSuffix
|
||||
{
|
||||
[self assert:@"[123.1234]" equals:sprintf(@"[%f]", 123.1234)];
|
||||
}
|
||||
|
||||
- (void)testZeroPaddingWithWidthAndPercentEscaping
|
||||
{
|
||||
[self assert:@"099%" equals:sprintf(@"%03d%%", 99)];
|
||||
}
|
||||
|
||||
- (void)testOutOfOrderExplicitFormatParameterIndexes
|
||||
{
|
||||
[self assert:@"2 > 1" equals:sprintf(@"%2$d > %1$d", 1, 2)];
|
||||
}
|
||||
|
||||
- (void)testMixingImplicitAndExplicitFormatParameterIndexes
|
||||
{
|
||||
[self assert:@"a < b && b > a" equals:sprintf(@"%@ < %2$@ && %@ > %1$@", @"a", @"b")];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in new issue
Block a user