|
**************************** IXTesterController.m ************************
#import "IXTestController.h"
@implementation IXTestController
#define TEMP_RECORD_FILE @"/tmp/IXRecordTest"
NSData *pack(unsigned int num, NSString *string)
{
unsigned int length = sizeof(unsigned int) + ([string cStringLength] * sizeof(char));
void *buffer = malloc(length);
void *ptr = buffer;
bcopy((char *)&num, (char *)ptr, sizeof(unsigned int));
ptr += sizeof(unsigned int);
bcopy([string cString],(char *)ptr, [string cStringLength]);
return [NSData dataWithBytes:buffer length:length];
}
- (NSString *)stringForBTree: (SDBTree *)aBTree
{
SDBTreeCursor *cursor = [[[[SDBTreeCursor alloc] initWithBTree:aBTree] retain] autorelease];
NSMutableString *dataString = [NSMutableString stringWithCapacity:100];
char *key;
unsigned int keyLength;
char *data;
unsigned int dataLength;
// traverse the btree and print out the words into outputText
[cursor setFirst];
do {
[cursor getKey:(void **)&key andLength:&keyLength];
[dataString appendString:[NSString stringWithCString:key length:keyLength]];
[dataString appendString:@"\t"];
dataLength = [cursor readValue:NULL];
data = malloc(dataLength * sizeof(char));
[cursor readValue:(void **)&data];
[dataString appendString:[NSString stringWithCString:data length:dataLength]];
[dataString appendString:@"\n"];
free(data);
} while ([cursor setNext]);
return [NSString stringWithString:dataString];
}
- (void)displayBTree:(SDBTree *)aBTree
{
SDBTreeCursor *cursor = [[[[SDBTreeCursor alloc] initWithBTree:aBTree] retain] autorelease];
NSMutableString *dataString = [NSMutableString stringWithCapacity:100];
char *key;
unsigned int keyLength;
char *data;
unsigned int dataLength;
// traverse the btree and print out the words into outputText
[cursor setFirst];
do {
[cursor getKey:(void **)&key andLength:&keyLength];
[dataString appendString:[NSString stringWithCString:key length:keyLength]];
[dataString appendString:@"\t"];
dataLength = [cursor readValue:NULL];
data = malloc(dataLength * sizeof(char));
[cursor readValue:(void **)&data];
[dataString appendString:[NSString stringWithCString:data length:dataLength]];
[dataString appendString:@"\n"];
free(data);
} while ([cursor setNext]);
[outputText setString:dataString];
[outputText sizeToFit];
}
- (void) cleanUp
{
if ([[NSFileManager defaultManager] fileExistsAtPath:TEMP_RECORD_FILE]) {
[[NSFileManager defaultManager] removeFileAtPath:TEMP_RECORD_FILE handler:nil];
}
}
- (void) processRecords:(id) sender
{
SDStoreFile *storeFile;
SDStoreDirectory *storeDirectory;
SDBTree *recordBTree;
SDBTree *indexBTree;
SDBTreeCursor *recordCursor;
SDBTreeCursor *indexCursor;
NSString *textString;
NSArray *lines;
NSArray *words;
int i, j;
NSString *aLine;
NSString *aWord;
NSData *keyData;
[self cleanUp];
// create an SDStoreFile, SDStoreDirectory, SDBTree, SDBTreeCursor
storeFile = [[[SDStoreFile alloc] initWithFile:TEMP_RECORD_FILE] retain];
storeDirectory = [[[SDStoreDirectory alloc] initInStore:storeFile]retain];
recordBTree = [[storeDirectory addEntryNamed:@"RecordBTree" ofClass:[SDBTree class]]retain];
[recordBTree setComparator:SDCompareIntegers andContext:NULL];
indexBTree = [[storeDirectory addEntryNamed:@"IndexBTree" ofClass:[SDBTree class]]retain];
[indexBTree setComparator:SDCompareCombo andContext:NULL];
// SDCompareCombo assumes the key contains an integer followed by a
// character string. Comparisons are based first on the character strings;
// if they're equal, then the integers are compared.
// get text from enterText
textString = [enterText string];
// divide it into lines
lines = [textString componentsSeparatedByString:@"\n"];
// store the words in the btree
recordCursor = [[[SDBTreeCursor alloc] initWithBTree:recordBTree]retain];
indexCursor = [[[SDBTreeCursor alloc] initWithBTree:indexBTree]retain];
[storeFile startTransaction];
for (i=0; i<[lines count]; i++) {
aLine = [lines objectAtIndex:i];
if (![aLine isEqual:@""]) {
if (![recordCursor setKey:(void *)&i andLength:sizeof(unsigned int)]) {
// the key is the line number; the data is the line
[recordCursor writeValue:(void *)[aLine cString] andLength:[aLine cStringLength]];
// index each word in the line
words = [aLine componentsSeparatedByString:@" "];
for (j=0;j<[words count]; j++) {
aWord = [words objectAtIndex:j];
if (![aWord isEqual:@""]) {
keyData = pack(i,aWord);
// the key is the word, preceded by the record number
// the data is the record number
[indexCursor setKey:keyData];
[indexCursor writeValue:(void *)&i andLength:sizeof(unsigned int)];
}
}
}
}
}
[storeFile commitTransaction];
[self displayBTree:recordBTree];
[storeFile release];
[storeDirectory release];
[indexBTree release];
[recordBTree release];
[indexCursor release];
[recordCursor release];
}
int comparePrefix(NSData *prefix, NSData *key)
{
const void *preData = [prefix bytes];
const void *keyData = [key bytes];
NSString *s1 = [NSString stringWithCString:(preData+sizeof(unsigned int)) length:[prefix length]- sizeof(unsigned int)];
NSString *s2 = [NSString stringWithCString:(keyData+sizeof(unsigned int)) length:[key length]- sizeof(unsigned int)];
if ([s2 length] <= [s1 length]) return [s1 caseInsensitiveCompare:s2];
s2 = [s2 substringToIndex:[s1 length]];
return [s1 caseInsensitiveCompare:s2];
}
- (void) findRecords:sender
{
SDStoreFile *storeFile;
SDStoreDirectory *storeDirectory;
SDBTree *recordBTree;
SDBTree *indexBTree;
SDBTree *foundBTree;
SDBTreeCursor *recordCursor;
SDBTreeCursor *indexCursor;
SDBTreeCursor *foundCursor;
NSString *aWord;
NSData *keyData;
NSData *storedKeyData;
NSData *storedValueData;
NSMutableString *dataString;
int result;
// open an SDStoreFile, SDStoreDirectory, SDBTree, SDBTreeCursor
storeFile = [[[SDStoreFile alloc] initFromFile:TEMP_RECORD_FILE forWriting:NO] autorelease];
storeDirectory = [[[SDStoreDirectory alloc] initFromBlock:1 inStore: storeFile]autorelease];
recordBTree = [[[storeDirectory openEntryNamed:@"RecordBTree"]retain]autorelease];
[recordBTree setComparator:SDCompareIntegers andContext:NULL];
indexBTree = [[[storeDirectory openEntryNamed:@"IndexBTree"]retain]autorelease];
[indexBTree setComparator:SDCompareCombo andContext:NULL];
// creating a btree to contain the found record keys allows us to display
// the records in order.
foundBTree = [[[storeDirectory addEntryNamed:@"foundBTree" ofClass: [SDBTree class]]retain]autorelease];
[foundBTree setComparator:SDCompareIntegers andContext:NULL];
recordCursor = [[[SDBTreeCursor alloc] initWithBTree:recordBTree]autorelease];
indexCursor = [[[SDBTreeCursor alloc] initWithBTree:indexBTree]autorelease];
foundCursor = [[[SDBTreeCursor alloc] initWithBTree:foundBTree]autorelease];
aWord = [enterText string];
keyData = pack(0,aWord);
// set the cursor to the first key that matches the find key (a key
// matches if the key starts with the characters in the find key)
[indexCursor setKey:(void *)[keyData bytes] andLength:[keyData length]];
storedKeyData = [indexCursor getKey];
while (storedKeyData && ((result = comparePrefix(keyData,storedKeyData)) == NSOrderedSame)) {
// get the record number
storedValueData = [indexCursor readData];
// and use the record number as the key in the foundBTree
if (![foundCursor setKey:(void *) [storedValueData bytes] andLength:[storedValueData length]]) {
[foundCursor writeValue:NULL andLength:0];
}
[indexCursor setNext];
storedKeyData = [indexCursor getKey];
}
// traverse the foundBTree and write each record to a string
dataString = [NSMutableString stringWithCapacity:100];
if ([foundCursor setFirst])
do {
storedKeyData = [foundCursor getKey];
if ([recordCursor setKey:(void *)[storedKeyData bytes] andLength:[storedKeyData length]]) {
storedValueData = [recordCursor readData];
[dataString appendString:[NSString stringWithCString: [storedValueData bytes] length:[storedValueData length]]];
[dataString appendString:@"\n"];
}
} while ([foundCursor setNext]);
[outputText setString:dataString];
[outputText sizeToFit];
}
- (void) clearInputField:sender
{
[enterText setString:@""];
[enterText sizeToFit];
}
@end
|
|