Skip to content

Commit

Permalink
Converting [YapDatabaseView findRangeInGroup:usingBlock:blockType:] t…
Browse files Browse the repository at this point in the history
…o modern syntax. (no more explicit blockType parameter)
  • Loading branch information
robbiehanson committed Aug 1, 2015
1 parent 4bc3065 commit e36e3c7
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 59 deletions.
10 changes: 10 additions & 0 deletions YapDatabase/Extensions/Views/Internal/YapDatabaseViewPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ static NSString *const changeset_key_changes = @"changes";
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

@interface YapDatabaseViewFind ()

+ (instancetype)withBlock:(YapDatabaseViewFindBlock)block blockType:(YapDatabaseViewBlockType)blockType;

@end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

@interface YapDatabaseView () {
@protected

Expand Down
23 changes: 6 additions & 17 deletions YapDatabase/Extensions/Views/YapDatabaseViewTransaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,6 @@

#pragma mark Finding

typedef id YapDatabaseViewFindBlock; // One of the YapDatabaseViewFindX types below.

typedef NSComparisonResult (^YapDatabaseViewFindWithKeyBlock) \
(NSString *collection, NSString *key);
typedef NSComparisonResult (^YapDatabaseViewFindWithObjectBlock) \
(NSString *collection, NSString *key, id object);
typedef NSComparisonResult (^YapDatabaseViewFindWithMetadataBlock) \
(NSString *collection, NSString *key, id metadata);
typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \
(NSString *collection, NSString *key, id object, id metadata);

/**
* This method uses a binary search algorithm to find a range of items within the view that match the given criteria.
* For example:
Expand Down Expand Up @@ -234,20 +223,20 @@ typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \
* @param group
* The group within the view to search.
*
* @param block
* One of the YapDatabaseViewFindWithXBlock types.
*
* @param blockType
* The proper YapDatabaseViewBlockTypeWithX type that matches the given block.
* @param find
* Instance of YapDatabaseViewFind. (See YapDatabaseViewTypes.h)
*
* @return
* If found, the range that matches the items within the desired range.
* That is, is these items were passed to the given block, the block would return NSOrderedSame.
* If not found, returns NSMakeRange(NSNotFound, 0).
**/
- (NSRange)findRangeInGroup:(NSString *)group using:(YapDatabaseViewFind *)find;

- (NSRange)findRangeInGroup:(NSString *)group
usingBlock:(YapDatabaseViewFindBlock)block
blockType:(YapDatabaseViewBlockType)blockType;
blockType:(YapDatabaseViewBlockType)blockType
__attribute((deprecated("Use method findRangeInGroup:using: instead")));

#pragma mark Enumerating

Expand Down
123 changes: 81 additions & 42 deletions YapDatabase/Extensions/Views/YapDatabaseViewTransaction.m
Original file line number Diff line number Diff line change
Expand Up @@ -4311,16 +4311,9 @@ - (NSString *)versionTag
/**
* See header file for extensive documentation for this method.
**/
- (NSRange)findRangeInGroup:(NSString *)group
usingBlock:(YapDatabaseViewFindBlock)block
blockType:(YapDatabaseViewBlockType)blockType
- (NSRange)findRangeInGroup:(NSString *)group using:(YapDatabaseViewFind *)find
{
BOOL invalidBlockType = blockType != YapDatabaseViewBlockTypeWithKey &&
blockType != YapDatabaseViewBlockTypeWithObject &&
blockType != YapDatabaseViewBlockTypeWithMetadata &&
blockType != YapDatabaseViewBlockTypeWithRow;

if (group == nil || block == NULL || invalidBlockType)
if (group == nil || find == NULL)
{
return NSMakeRange(NSNotFound, 0);
}
Expand All @@ -4338,9 +4331,11 @@ - (NSRange)findRangeInGroup:(NSString *)group
return NSMakeRange(NSNotFound, 0);
}

NSComparisonResult (^compare)(NSUInteger) = ^NSComparisonResult (NSUInteger index){

int64_t rowid = 0;
// Helper block:
//
// Finds the rowid for a given index (within the view.group).

int64_t (^findRowid)(NSUInteger) = ^int64_t (NSUInteger index){

NSUInteger pageOffset = 0;
for (YapDatabaseViewPageMetadata *pageMetadata in pagesMetadataForGroup)
Expand All @@ -4349,59 +4344,92 @@ - (NSRange)findRangeInGroup:(NSString *)group
{
YapDatabaseViewPage *page = [self pageForPageKey:pageMetadata->pageKey];

rowid = [page rowidAtIndex:(index - pageOffset)];
break;
return [page rowidAtIndex:(index - pageOffset)];
}
else
{
pageOffset += pageMetadata->count;
}
}

if (blockType == YapDatabaseViewBlockTypeWithKey)
NSAssert(NO, @"index(%lu) not found !!!", (unsigned long)index);
return (int64_t)0;
};

// Helper block:
//
// Executes the findBlock against the row represented by the given index (within the view.group).

NSComparisonResult (^compare)(NSUInteger);

switch (find.findBlockType)
{
case YapDatabaseViewBlockTypeWithKey :
{
__unsafe_unretained YapDatabaseViewFindWithKeyBlock findBlock =
(YapDatabaseViewFindWithKeyBlock)block;

YapCollectionKey *ck = [databaseTransaction collectionKeyForRowid:rowid];
(YapDatabaseViewFindWithKeyBlock)find.findBlock;

return findBlock(ck.collection, ck.key);
compare = ^NSComparisonResult (NSUInteger index){

int64_t rowid = findRowid(index);

YapCollectionKey *ck = [databaseTransaction collectionKeyForRowid:rowid];

return findBlock(ck.collection, ck.key);
};
}
else if (blockType == YapDatabaseViewBlockTypeWithObject)
case YapDatabaseViewBlockTypeWithObject :
{
__unsafe_unretained YapDatabaseViewFindWithObjectBlock findBlock =
(YapDatabaseViewFindWithObjectBlock)block;

YapCollectionKey *ck = nil;
id object = nil;
[databaseTransaction getCollectionKey:&ck object:&object forRowid:rowid];
(YapDatabaseViewFindWithObjectBlock)find.findBlock;

return findBlock(ck.collection, ck.key, object);
compare = ^NSComparisonResult (NSUInteger index){

int64_t rowid = findRowid(index);

YapCollectionKey *ck = nil;
id object = nil;
[databaseTransaction getCollectionKey:&ck object:&object forRowid:rowid];

return findBlock(ck.collection, ck.key, object);
};
}
else if (blockType == YapDatabaseViewBlockTypeWithMetadata)
case YapDatabaseViewBlockTypeWithMetadata :
{
__unsafe_unretained YapDatabaseViewFindWithMetadataBlock findBlock =
(YapDatabaseViewFindWithMetadataBlock)block;

YapCollectionKey *ck = nil;
id metadata = nil;
[databaseTransaction getCollectionKey:&ck metadata:&metadata forRowid:rowid];
(YapDatabaseViewFindWithMetadataBlock)find.findBlock;

return findBlock(ck.collection, ck.key, metadata);
compare = ^NSComparisonResult (NSUInteger index){

int64_t rowid = findRowid(index);

YapCollectionKey *ck = nil;
id metadata = nil;
[databaseTransaction getCollectionKey:&ck metadata:&metadata forRowid:rowid];

return findBlock(ck.collection, ck.key, metadata);
};
}
else
default :
{
__unsafe_unretained YapDatabaseViewFindWithRowBlock findBlock =
(YapDatabaseViewFindWithRowBlock)block;

YapCollectionKey *ck = nil;
id object = nil;
id metadata = nil;
[databaseTransaction getCollectionKey:&ck object:&object metadata:&metadata forRowid:rowid];
(YapDatabaseViewFindWithRowBlock)find.findBlock;

return findBlock(ck.collection, ck.key, object, metadata);
compare = ^NSComparisonResult (NSUInteger index){

int64_t rowid = findRowid(index);

YapCollectionKey *ck = nil;
id object = nil;
id metadata = nil;
[databaseTransaction getCollectionKey:&ck object:&object metadata:&metadata forRowid:rowid];

return findBlock(ck.collection, ck.key, object, metadata);
};
}
};

} // end switch (blockType)


NSUInteger loopCount = 0;

Expand Down Expand Up @@ -4479,6 +4507,17 @@ - (NSRange)findRangeInGroup:(NSString *)group
return NSMakeRange(sMin, (eMax - sMin));
}

/**
* This method is deprecated.
* Use findRangeInGroup:using: instead.
**/
- (NSRange)findRangeInGroup:(NSString *)group
usingBlock:(YapDatabaseViewFindBlock)block
blockType:(YapDatabaseViewBlockType)blockType
{
return [self findRangeInGroup:group using:[YapDatabaseViewFind withBlock:block blockType:blockType]];
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Public API - Enumerating
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
77 changes: 77 additions & 0 deletions YapDatabase/Extensions/Views/YapDatabaseViewTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ typedef NSString* (^YapDatabaseViewGroupingWithRowBlock) \

@end

#pragma mark -

/**
* The sorting block handles sorting of objects within their group.
*
Expand Down Expand Up @@ -130,3 +132,78 @@ typedef NSComparisonResult (^YapDatabaseViewSortingWithRowBlock)
@property (nonatomic, assign, readonly) YapDatabaseViewBlockType sortingBlockType;

@end

#pragma mark -

/**
* A find block is used to efficiently find items within a view.
* It allows you to perform a binary search on the pre-sorted items within a view.
*
* The return values from the YapDatabaseViewFindBlock have the following meaning:
*
* - NSOrderedAscending : The given row (block parameters) is less than the range I'm looking for.
* That is, the row would have a smaller index within the view than would the range I seek.
*
* - NSOrderedDecending : The given row (block parameters) is greater than the range I'm looking for.
* That is, the row would have a greater index within the view than would the range I seek.
*
* - NSOrderedSame : The given row (block parameters) is within the range I'm looking for.
*
* Keep in mind 2 things:
*
* #1 : This method can only be used if you need to find items according to their sort order.
* That is, according to how the items are sorted via the view's sortingBlock.
* Attempting to use this method in any other manner makes no sense.
*
* #2 : The findBlock that you pass needs to be setup in the same manner as the view's sortingBlock.
* That is, the following rules must be followed, or the results will be incorrect:
*
* For example, say you have a view like this, looking for the following range of 3 items:
* myView = @[ A, B, C, D, E, F, G ]
* ^^^^^^^
* sortingBlock(A, B) => NSOrderedAscending
* findBlock(A) => NSOrderedAscending
*
* sortingBlock(E, D) => NSOrderedDescending
* findBlock(E) => NSOrderedDescending
*
* findBlock(B) => NSOrderedSame
* findBlock(C) => NSOrderedSame
* findBlock(D) => NSOrderedSame
*
* In other words, you can't sort one way in the sortingBlock, and "sort" another way in the findBlock.
* Another way to think about it is in terms of how the Apple docs define the NSOrdered enums:
*
* NSOrderedAscending : The left operand is smaller than the right operand.
* NSOrderedDescending : The left operand is greater than the right operand.
*
* For the findBlock, the "left operand" is the row that is passed,
* and the "right operand" is the desired range.
*
* And NSOrderedSame means: "the passed row is within the range I'm looking for".
**/
@interface YapDatabaseViewFind : NSObject

typedef id YapDatabaseViewFindBlock; // One of the YapDatabaseViewFindX types below.

typedef NSComparisonResult (^YapDatabaseViewFindWithKeyBlock) \
(NSString *collection, NSString *key);

typedef NSComparisonResult (^YapDatabaseViewFindWithObjectBlock) \
(NSString *collection, NSString *key, id object);

typedef NSComparisonResult (^YapDatabaseViewFindWithMetadataBlock) \
(NSString *collection, NSString *key, id metadata);

typedef NSComparisonResult (^YapDatabaseViewFindWithRowBlock) \
(NSString *collection, NSString *key, id object, id metadata);

+ (instancetype)withKeyBlock:(YapDatabaseViewFindWithKeyBlock)findBlock;
+ (instancetype)withObjectBlock:(YapDatabaseViewFindWithObjectBlock)findBlock;
+ (instancetype)withMetadataBlock:(YapDatabaseViewFindWithMetadataBlock)findBlock;
+ (instancetype)withRowBlock:(YapDatabaseViewFindWithRowBlock)findBlock;

@property (nonatomic, strong, readonly) YapDatabaseViewFindBlock findBlock;
@property (nonatomic, assign, readonly) YapDatabaseViewBlockType findBlockType;

@end
Loading

0 comments on commit e36e3c7

Please sign in to comment.