Skip to content

Commit

Permalink
testing ways to optimize GITCommit#parseRawData:
Browse files Browse the repository at this point in the history
Signed-off-by: Geoff Garside <geoff@geoffgarside.co.uk>
  • Loading branch information
chapados authored and geoffgarside committed Jun 17, 2009
1 parent cdfdb2a commit 84af0e4
Show file tree
Hide file tree
Showing 2 changed files with 254 additions and 7 deletions.
248 changes: 246 additions & 2 deletions Source/Types/GITCommit.m
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,257 @@ - (NSArray *)parents

#pragma mark -
#pragma mark Data Parser

typedef struct parseInfo {
char *startPattern;
NSUInteger startLen;
NSInteger matchLen;
char endChar;

} parseInfo;

static parseInfo p_tree = { "tree ", 5, 40, '\n' };
static parseInfo p_parent = { "parent ", 7, 40, '\n' };
static parseInfo p_cName = { "committer ", 10, 0, '<' };
static parseInfo p_aName = { "author ", 7, 0, '<' };
static parseInfo p_email = { "", 0, 0, '>' };
static parseInfo p_dateString = { " ", 1, 0, '\n' };
//static parseInfo p_date = { " ", 1, 0, ' ' };
//static parseInfo p_tz = { " ", 1, 0, '\n' };

//NSString *parseTree(const char **buffer)
//{
// const char *buf = *buffer;
// // "tree <40-cahr sha1>\n"
// if ( memcmp(buf, p_tree.startPattern, p_tree.startLen) ||
// buf[p_tree.startLen + p_tree.matchLen] != p_tree.endChar ) {
// return nil;
// }
// NSString *commitTree = [[NSString alloc] initWithBytes:(buf+p_tree.startLen)
// length:p_tree.matchLen
// encoding:NSASCIIStringEncoding];
// if ( !commitTree )
// return nil;
// *buffer += p_tree.startLen + p_tree.matchLen + 1;
// return [commitTree autorelease];
//}

NSString *parseBuffer(const char **buffer, parseInfo *delim)
{
const char *buf = *buffer;
if ( delim->startLen > 0 && memcmp(buf, delim->startPattern, delim->startLen) ) {
//NSLog(@"start pattern does not match: %s\nbuf:%s", delim->startPattern, buf);
return nil;
}

NSUInteger matchLen;
if ( delim->matchLen > 0 ) {
matchLen = delim->matchLen;
} else {
//char *end = memchr(buf+delim->startLen, delim->endChar, strlen(buf));
char *end = (char *)buf+delim->startLen;
while ( *end++ != delim->endChar )
;
end--;
// if ( end == NULL ) {
// NSLog(@"could not determine matchLen");
// return nil;
// }
matchLen = end - (buf+delim->startLen);
}

if ( buf[delim->startLen+matchLen] != delim->endChar ) {
NSLog(@"end delimiter (%c) does not match end char:%c\n matchLen = %d", delim->endChar, buf[delim->startLen+matchLen], matchLen);
return nil;
}
NSString *s = [[NSString alloc] initWithBytes:buf+delim->startLen
length:matchLen
encoding:NSASCIIStringEncoding];
if ( !s )
return nil;
*buffer += delim->startLen + matchLen + 1;
return [s autorelease];
}


- (BOOL)parseRawDataWithC:(NSData*)raw error:(NSError**)error
{
NSMutableArray *commitParents = [NSMutableArray new];

const char *rawString = [raw bytes];

NSString *commitTree = parseBuffer(&rawString, &p_tree);
if ( !commitTree )
return NO;
[self setTreeSha1:commitTree];

// parents
NSString *commitParent;
while ( commitParent = parseBuffer(&rawString, &p_parent) ) {
[commitParents addObject:commitParent];
}

NSString *authorName = parseBuffer(&rawString, &p_aName);
NSString *authorEmail = parseBuffer(&rawString, &p_email);
NSString *authorDateString = parseBuffer(&rawString, &p_dateString);
[self setAuthor:[GITActor actorWithName:authorName email:authorEmail]];
//NSLog(@"name: %@, email: %@, date: %@", authorName, authorEmail, authorDateString);

NSString *committerName = parseBuffer(&rawString, &p_cName);
NSString *committerEmail = parseBuffer(&rawString, &p_email);
NSString *committerDateString = parseBuffer(&rawString, &p_dateString);
[self setCommitter:[GITActor actorWithName:committerName email:committerEmail]];

[self setParentShas:commitParents];
[commitParents release];

return YES;
}

typedef struct CFParseInfo {
CFStringRef startPattern;
CFIndex startLen;
CFIndex matchLen;
UniChar endChar;

} CFParseInfo;

static CFParseInfo cf_tree = { CFSTR("tree "), 5, 40, '\n' };
static CFParseInfo cf_parent = { CFSTR("parent "), 7, 40, '\n' };
//static CFParseInfo cf_cName = { CFSTR("committer "), 10, 0, '<' };
//static CFParseInfo cf_aName = { CFSTR("author "), 7, 0, '<' };
//static CFParseInfo cf_email = { CFSTR(""), 0, 0, '>' };
//static CFParseInfo cf_dateString = { CFSTR(" "), 1, 0, '\n' };

CFRange parseString(CFStringRef *sPtr, CFRange r, CFParseInfo delim, CFRange *rest)
{
CFStringRef s = *sPtr;
if ( CFStringCompareWithOptions(s, delim.startPattern, CFRangeMake(r.location, delim.startLen), 0) != 0 ) {
//NSLog(@"r.location = %u, bad line for prefix %@\n", r.location, delim.startPattern);
return CFRangeMake(-1, 0);
}

NSUInteger matchLen;
if ( delim.matchLen > 0 ) {
matchLen = delim.matchLen;
} else {
CFRange searchRange = CFRangeMake(r.location + delim.startLen, r.length - delim.startLen);
CFStringInlineBuffer buf;
CFStringInitInlineBuffer(s, &buf, searchRange);
CFIndex i = 0;
while ( CFStringGetCharacterFromInlineBuffer(&buf, i++) != (UniChar)delim.endChar )
;
matchLen = (i - 1) - (r.location + delim.startLen);
}

CFIndex end = r.location + delim.startLen + matchLen;
//printf("r.location = %u, end = %u\n", r.location, end);
if ( CFStringGetCharacterAtIndex(s, end) != delim.endChar ) {
//NSLog(@"delim = %@ - end delimiter (%d) does not match end char:%d\n matchLen = %d", delim.startPattern, delim.endChar, CFStringGetCharacterAtIndex(s, end), matchLen);
return CFRangeMake(-1, 0);
}

*rest = CFRangeMake(end + 1, r.length - end + 1);
return CFRangeMake(r.location + delim.startLen, matchLen);
}

- (BOOL)parseRawData:(NSData*)raw error:(NSError**)error
{
NSMutableArray *commitParents = [NSMutableArray new];

CFStringRef rawString = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, [raw bytes], [raw length], kCFStringEncodingASCII, false, kCFAllocatorNull);
CFIndex length = CFStringGetLength(rawString);
CFRange rawRange = CFRangeMake(0, length);

CFRange treeRange = parseString(&rawString, rawRange, cf_tree, &rawRange);
//printf("** rawRange = %u, %u", rawRange.location, rawRange.length);
CFStringRef commitTree = CFStringCreateWithSubstring(NULL, rawString, treeRange);
//NSLog(@"tree = %@", commitTree);
[self setTreeSha1:(NSString *)commitTree];
CFRelease(commitTree);

CFRange parentRange;
while ( (parentRange = parseString(&rawString, rawRange, cf_parent, &rawRange)).location != -1 ) {
CFStringRef p = CFStringCreateWithSubstring(NULL, rawString, parentRange);
//NSLog(@"parent = %@",p);
[commitParents addObject:(NSString *)p];
CFRelease(p);
}
[self setParentShas:commitParents];
[commitParents release];
CFRelease(rawString);

return YES;
}


- (BOOL)BCparseRawData:(NSData*)raw error:(NSError**)error
{
// TODO: Update this method to support errors
NSString * errorDescription;

NSString *dataStr = [[NSString alloc] initWithBytesNoCopy:(char *)[raw bytes]
length:strlen([raw bytes])
encoding:[NSString defaultCStringEncoding]
freeWhenDone:NO];
NSMutableArray *commitParents = [NSMutableArray new];

// const char *rawString = [raw bytes];
//
// // "tree <40-cahr sha1>\n", len = 5 + 40 + 1, pos[45] = '\n'
// rawString += 5; // "tree "
// NSString *commitTree = [[NSString alloc] initWithBytes:rawString
// length:40
// encoding:NSASCIIStringEncoding];
// [self setTreeSha1:commitTree];
// [commitTree release];
//
//
// rawString += 41;
// //printf("%s",rawString);
// while (!memcmp(rawString, "parent ", 7)) {
// rawString += 7;
// NSString *commitParent = [[NSString alloc] initWithBytes:rawString
// length:40
// encoding:NSASCIIStringEncoding];
// if ( commitParent ) {
// //NSLog(@"bad parent: %@, (%d)", commitParent, [commitParent length]);
// [commitParents addObject:commitParent];
// }
// rawString += 41;
// [commitParent release];
// }

NSRange treeRange = NSMakeRange(5, 40);
NSRange parentsRange;
parentsRange = NSMakeRange(46, 47);

//NSLog(@"parentsRange string = %@", [dataStr substringWithRange:parentsRange]);

NSString *p;
while ( [(p = [dataStr substringWithRange:parentsRange]) hasPrefix:@"parent "] ) {
NSString *commitParent = [p substringFromIndex:7];
[commitParents addObject:commitParent];
parentsRange = NSMakeRange(parentsRange.location+parentsRange.length+1, parentsRange.length);
}


[self setParentShas:commitParents];
//NSLog(@"parsed raw data for tree: %@", self.treeSha1);

[commitParents release];
[dataStr release];
return YES;
}


- (BOOL)parseRawDataWithScanner:(NSData*)raw error:(NSError**)error
{
// TODO: Update this method to support errors
NSString * errorDescription;

NSString * dataStr = [[NSString alloc] initWithData:raw
encoding:NSASCIIStringEncoding];
NSString *dataStr = [[NSString alloc] initWithData:raw
encoding:NSASCIIStringEncoding];
NSScanner * scanner = [NSScanner scannerWithString:dataStr];
[dataStr release];

Expand Down
13 changes: 8 additions & 5 deletions Source/Types/GITObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,18 @@ - (id)initWithSha1:(NSString*)theSha1 type:(GITObjectType)theType data:(NSData*)
return nil;
}

// Should only need to override -parseRawData:error: in subclasses
if (! [self parseRawData:theData error:error])
return nil;

self.sha1 = theSha1;
// Remove when type is changed to a GITObjectType instead of a string
self.type = [[self class] stringForObjectType:theType];
self.size = [theData length];
self.repo = theRepo;

// Should only need to override -parseRawData:error: in subclasses
if (! [self parseRawData:theData error:error]) {
[self release];
return nil;
}

self.size = [theData length];

return self;
}
Expand Down

0 comments on commit 84af0e4

Please sign in to comment.