From 80f95e4d58ab69d885b9c1ccd0d9fdfd32f3fe80 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Sun, 26 Oct 2008 23:06:23 -0700 Subject: [PATCH] Fix binary search in CPArray to allow searching for 0. --- Foundation/CPArray.j | 4 +- Tests/Foundation/CPAttributedStringTest.j | 449 ---------------------- 2 files changed, 2 insertions(+), 451 deletions(-) delete mode 100644 Tests/Foundation/CPAttributedStringTest.j diff --git a/Foundation/CPArray.j b/Foundation/CPArray.j index 90942d1a6..b486b5a1a 100755 --- a/Foundation/CPArray.j +++ b/Foundation/CPArray.j @@ -461,9 +461,9 @@ */ - (unsigned)indexOfObject:(id)anObject sortedByFunction:(Function)aFunction context:(id)aContext { - if (!aFunction || !anObject) + if (!aFunction || anObject === undefined) return CPNotFound; - + var mid, c, first = 0, last = length - 1; while (first <= last) { diff --git a/Tests/Foundation/CPAttributedStringTest.j b/Tests/Foundation/CPAttributedStringTest.j deleted file mode 100644 index d559c6dd4..000000000 --- a/Tests/Foundation/CPAttributedStringTest.j +++ /dev/null @@ -1,449 +0,0 @@ -import "CPAttributedString.j" - -@implementation CPAttributedStringTest : OJTestCase - - -- (id)testInitWithString -{ - var string = [[CPAttributedString alloc] initWithString:@"hi there"]; - - [self assertTrue:([string string] === @"hi there") - message:"testInitWithString: expected:" + @"hi there" + " actual:" + [string string]]; -} -/* -- (id)testInitWithAttributedString -{ - var string = [[CPAttributedString alloc] initWithString:@"hi there"], - attributedString = [[CPAttributedString alloc] initWithAttributedString:string]; - - [self assertTrue:([string isEqualToAttributedString:attributedString]) - message:"testInitWithAttributedString: expected:" + string + " actual:" + attributedString]; - - //add a case where we init with a string that actually adds attributes -} - -- (id)testIinitWithString_attributes -{ - var string = [[CPAttributedString alloc] initWithString:@"hi there" attributes:[CPDictionary dictionary]]; - - [self assertTrue:([string string] === @"hi there") - message:"testIinitWithString_attributes: expected:" + @"hi there" + " actual:" + [string string]]; - - var string = [[CPAttributedString alloc] initWithString:@"hi there" attributes:[CPDictionary dictionaryWithObjects:[1, "bar"] forKeys["number", "foo"]]]; - - [self assertTrue:([[string attributesAtIndex:0 effectiveRange:nil] objectForKey:@"number"] === 1) - message:"testIinitWithString_attributes: value for key 'number' expected:" + 1 + " actual:" + [[string attributesAtIndex:0 effectiveRange:nil] objectForKey:@"number"]]; - - [self assertTrue:([[string attributesAtIndex:0 effectiveRange:nil] objectForKey:@"bar"] === "foo") - message:"testIinitWithString_attributes: value for key 'foo' expected:" + "bar" + " actual:" + [[string attributesAtIndex:0 effectiveRange:nil] objectForKey:@"foo"]]; -} - -//Retrieving Character Information -- (CPString)testString -{ - var string = [[CPAttributedString alloc] initWithString:@"hi there"]; - - [self assertTrue:([string string] === string._string) - message:"testString: expected:" + @"hi there" + " actual:" + [string string]]; -} - -- (unsigned)testLength -{ - var string = [[CPAttributedString alloc] initWithString:@"hi there"]; - - [self assertTrue:([string length] === 8) - message:"testLength: expected:" + 8 + " actual:" + [string length]]; -} - -- (unsigned)test_indexOfEntryWithIndex -{ - -} - -//Retrieving Attribute Information -- (CPDictionary)attributesAtIndex:(unsigned)anIndex effectiveRange:(CPRangePointer)aRange -{ - //find the range entry that contains anIndex. - var entryIndex = [self _indexOfEntryWithIndex:anIndex]; - - if (entryIndex == CPNotFound) - return nil; - - var matchingRange = _rangeEntries[entryIndex]; - - if (aRange) - { - aRange.location = matchingRange.range.location; - aRange.length = matchingRange.range.length; - } - - return matchingRange.attributes; -} - -- (CPDictionary)attributesAtIndex:(unsigned)anIndex longestEffectiveRange:(CPRangePointer)aRange inRange:(CPRange)rangeLimit -{ - var startingEntryIndex = [self _indexOfEntryWithIndex:anIndex]; - - if (startingEntryIndex == CPNotFound) - return nil; - - if (!aRange) - return _rangeEntries[startingEntryIndex].attributes; - - if (CPRangeInRange(_rangeEntries[startingEntryIndex].range, rangeLimit)) - { - aRange.location = rangeLimit.location; - aRange.length = rangeLimit.length; - - return _rangeEntries[startingEntryIndex].attributes; - } - - var currentRange = _rangeEntries[startingEntryIndex], - currentRangeIndex = startingEntryIndex, - comparisonDict = currentRange.attributes; - - while (CPMaxRange(currentRange) > rangeLimit.location && [currentRange.attributes isEqualToDictionary:comparisonDict]) - currentRange = _rangeEntries[--currentRangeIndex]; - - aRange.location = currentRange.location; - currentRange = _rangeEntries[startingEntryIndex], - currentRangeIndex = startingEntryIndex; - - while (currentRange.location < CPMaxRange(rangeLimit) && [currentRange.attributes isEqualToDictionary:comparisonDict]) - currentRange = _rangeEntries[++currentRangeIndex]; - - aRange.length = CPMaxRange(currentRange) - aRange.location; - - return currentRange.attributes; -} - -- (id)attribute:(CPString)attribute atIndex:(unsigned)index effectiveRange:(CPRangePointer)aRange -{ - if (!attribute) - { - if (aRange) - { - aRange.location = 0; - aRange.length = _string.length; - } - - return nil; - } - - return [[self attributesAtIndex:index effectiveRange:aRange] valueForKey:attribute]; -} - -- (id)attribute:(CPString)attribute atIndex:(unsigned)index longestEffectiveRange:(CPRangePointer)aRange inRange:(CPRange)rangeLimit -{ - //find the range entry that contains anIndex. - var startingEntryIndex = [self _indexOfEntryWithIndex:anIndex]; - - if (startingEntryIndex == CPNotFound || !attribute) - return nil; - - if (!aRange) - return [_rangeEntries[startingEntryIndex].attributes objectForKey:attribute]; - - if (CPRangeInRange(_rangeEntries[startingEntryIndex].range, rangeLimit)) - { - aRange.location = rangeLimit.location; - aRange.length = rangeLimit.length; - - return [_rangeEntries[startingEntryIndex].attributes objectForKey:attribute]; - } - - var currentRange = _rangeEntries[startingEntryIndex], - currentRangeIndex = startingEntryIndex, - comparisonAttribute = [currentRange.attributes objectForKey:attribute]; - - while (CPMaxRange(currentRange) > rangeLimit.location) - { - var thisAttribute = [currentRange.attributes objectForKey:attribute]; - - if (isEqual(comparisonAttribute, thisAttribute)) - currentRange = _rangeEntries[--currentRangeIndex]; - else - break; - } - - aRange.location = currentRange.location; - currentRange = _rangeEntries[startingEntryIndex], - currentRangeIndex = startingEntryIndex; - - while (currentRange.location < CPMaxRange(rangeLimit)) - { - var thisAttribute = [currentRange.attributes objectForKey:attribute]; - - if (isEqual(comparisonAttribute, thisAttribute)) - currentRange = _rangeEntries[++currentRangeIndex]; - else - break; - } - - aRange.length = CPMaxRange(currentRange) - aRange.location; - - return comparisonAttribute; -} - -//Comparing Attributed Strings -- (BOOL)isEqualToAttributedString:(CPAttributedString)aString -{ - if(!aString) - return NO; - - if(_string != [aString string]) - return NO; - - var myRange = CPMakeRange(), - comparisonRange = CPMakeRange(), - myAttributes = [self attributesAtIndex:0 effectiveRange:myRange], - comparisonAttributes = [aString attributesAtIndex:0 effectiveRange:comparisonRange], - length = _string.length; - - while (CPMaxRange(CPUnionRange(myRange, comparisonRange)) < length) - { - if (CPIntersectionRange(myRange, comparisonRange).length > 0 && ![myAttributes isEqualToDictionary:comparisonAttributes]) - return NO; - - if (CPMaxRange(myRange) < CPMaxRange(comparisonRange)) - myAttributes = [self attributesAtIndex:CPMaxRange(myRange) effectiveRange:myRange]; - else - comparisonAttributes = [aString attributesAtIndex:CPMaxRange(comparisonRange) effectiveRange:comparisonRange]; - } - - return YES; -} - -- (BOOL)isEqual:(id)anObject -{ - if (anObject == self) - return YES; - - if ([anObject isKindOfClass:[self class]]) - return [self isEqualToAttributedString:anObject]; - - return NO; -} - -//Extracting a Substring -- (CPAttributedString)attributedSubstringFromRange:(CPRange)aRange -{ - if (!aRange || CPMaxRange(aRange) > _string.length || aRange.location < 0) - [CPException raise:CPRangeException - reason:"tried to get attributedSubstring for an invalid range: "+(aRange?CPStringFromRange(aRange):"nil")]; - - var newString = [[CPAttributedString alloc] initWithString:_string.substring(aRange.location, CPMaxRange(aRange))], - entryIndex = [self _indexOfEntryWithIndex:aRange.location], - currentRangeEntry = _rangeEntries[entryIndex], - lastIndex = CPMaxRange(aRange); - - while (CPMaxRange(currentRangeEntry.range) < lastIndex); - { - newString._rangeEntries.push(copyRangeEntry(currentRangeEntry)); - currentRangeEntry = _rangeEntries[++entryIndex]; - } - - var newRangeEntry = copyRangeEntry(currentRangeEntry); - newString._rangeEntries.push(newRangeEntry); - - newRangeEntry.range.length = CPMaxRange(aRange) - newRangeEntry.range.location; - - return newString; -} - -//Changing Characters -- (void)replaceCharactersInRange:(CPRange)aRange withString:(CPString)aString -{ - [self beginEditing]; - - if (!aString) - aString = ""; - - var startingIndex = [self _indexOfEntryWithIndex:characterIndex], - startingRangeEntry = _rangeEntries[index], - endingIndex = [self _indexOfEntryWithIndex:CPMaxRange(aRange)], - endingRangeEntry = _rangeEntries[endingIndex], - additionalLength = aString.length - aRange.length; - - _string = _string.substring(0, aRange.location) + aString + _string.substring(CPMaxRange(aRange)); - - if (startingIndex == endingIndex) - startingRangeEntry.range.length += additionalLength; - else - { - endingRangeEntry.range.length = CPMaxRange(endingRangeEntry.range) - CPMaxRange(aRange); - endingRangeEntry.range.location = CPMaxRange(aRange); - - startingRangeEntry.range.length = CPMaxRange(aRange) - startingRangeEntry.range.location; - - _rangeEntries.splice(startingIndex, endingIndex - startingIndex); - } - - [self endEditing]; -} - -- (void)deleteCharactersInRange:(CPRange)aRange -{ - [self replaceCharactersInRange:aRange withString:nil]; -} - -//Changing Attributes -- (void)setAttributes:(CPDictionary)aDictionary range:(CPRange)aRange -{ - [self beginEditing]; - - var startingEntryIndex = [self _indexOfRangeEntryForIndex:aRange.location splitIfNecessary:YES], - endingEntryIndex = [self _indexOfRangeEntryForIndex:CPMaxRange(aRange) splitIfNecessary:YES] - 1, - current = startingEntryIndex; - - while (current < endingEntryIndex) - _rangeEntries[current++].attributes = [aDictionary copy]; - - //necessary? - [self _coalesceRangeEntriesFromIndex:startingEntryIndex toIndex:endingEntryIndex]; - - [self endEditing]; -} - -- (void)addAttributes:(CPDictionary)aDictionary range:(CPRange)aRange -{ - [self beginEditing]; - - var startingEntryIndex = [self _indexOfRangeEntryForIndex:aRange.location splitIfNecessary:YES], - endingEntryIndex = [self _indexOfRangeEntryForIndex:CPMaxRange(aRange) splitIfNecessary:YES] - 1, - current = startingEntryIndex; - - while (current < endingEntryIndex) - { - var keys = [aDictionary keys], - count = [keys count]; - - while (count--) - [_rangeEntries[current].attributes setObject:[aDictionary objectForKey:keys[count]] forKey:keys[count]]; - - current++; - } - - //necessary? - [self _coalesceRangeEntriesFromIndex:startingEntryIndex toIndex:endingEntryIndex]; - - [self endEditing]; -} - -- (void)addAttribute:(CPString)anAttribute value:(id)aValue range:(CPRange)aRange -{ - [self beginEditing]; - - var startingEntryIndex = [self _indexOfRangeEntryForIndex:aRange.location splitIfNecessary:YES], - endingEntryIndex = [self _indexOfRangeEntryForIndex:CPMaxRange(aRange) splitIfNecessary:YES] - 1, - current = startingEntryIndex; - - while (current < endingEntryIndex) - [_rangeEntries[current++].attributes setObject:aValue forKey:anAttribute]; - - //necessary? - //[self _coalesceRangeEntriesFromIndex:startingEntryIndex toIndex:endingEntryIndex]; - - [self endEditing]; -} - -- (void)removeAttribute:(CPString)anAttribute range:(CPRange)aRange -{ - [self addAttribute:anAttribute value:nil range:aRange]; -} - -//Changing Characters and Attributes -- (void)appendAttributedString:(CPAttributedString)aString -{ - [self insertAttributedString:aString atIndex:_string.length]; -} - -- insertAttributedString:(CPAttributedString)aString atIndex:(CPString)anIndex -{ - [self beginEditing]; - - var startingEntryIndex = [self _indexOfRangeEntryForIndex:anIndex splitIfNecessary:YES], - rangeEntries = aString._rangeEntries, - count = rangeEntries.length; - - _string = _string.substring(0, anIndex) + aString._string + _string.substring(anIndex); - - while (count--) - { - var newEntry = copyRangeEntry(rangeEntries[count]); - - newEntry.range.location += anIndex; - - _rangeEntries.splice(startingEntryIndex, 0, newEntry); - } - - //necessary? - //[self _coalesceRangeEntriesFromIndex:startingEntryIndex toIndex:endingEntryIndex]; - - [self endEditing]; -} - -- (void)replaceCharactersInRange:(CPRange)aRange withAttributedString:(CPAttributedString)aString -{ - [self beginEditing]; - - [self deleteCharactersInRange:aRange]; - [self insertAttributeString:aString atIndex:aRange.location]; - - [self endEditing]; -} - -- (void)setAttributedString:(CPAttributedString)aString -{ - [self beginEditing]; - - _string = aString; - _rangeEntries = []; - - for (var i=0, count = aString._rangeEntries.length; i