Permalink
Browse files

improved JSON parser

Signed-off-by: Rifat Nabi <to.rifat@gmail.com>
  • Loading branch information...
1 parent 9c1acf0 commit 1576baa7a372dcda53135abe5396282a0c0509af @torifat committed Jun 28, 2012
Showing with 113 additions and 2,817 deletions.
  1. +2 −1 AvroParser.h
  2. +110 −95 AvroParser.m
  3. +1 −2,721 data.json
View
@@ -11,7 +11,8 @@
NSString* _vowel;
NSString* _consonant;
NSString* _casesensitive;
- NSDictionary* _patterns;
+ NSArray* _patterns;
+ int _maxPatternLength;
}
+ (void)allocateSharedInstance;
View
@@ -30,6 +30,7 @@ - (id)init {
_consonant = [jsonArray objectForKey:@"consonant"];
_casesensitive = [jsonArray objectForKey:@"casesensitive"];
_patterns = [jsonArray objectForKey:@"patterns"];
+ _maxPatternLength = [[[_patterns objectAtIndex:0] objectForKey:@"find"] length];
}
} else {
@@ -87,113 +88,126 @@ - (NSString*)parse:(NSString *)string {
int start = cur, end;
BOOL matched = FALSE;
- for(NSDictionary *pattern in _patterns) {
- NSString* find = [pattern objectForKey:@"find"];
- int findLen = [find length];
- end = cur + findLen;
- int diff = (end - start);
- if(end <= len && diff == findLen) {
- NSString* chunk = [fixed substringWithRange:NSMakeRange(start, diff)];
- if(chunk && [chunk length] && [chunk isEqualToString:find]) {
- NSArray* rules = [pattern objectForKey:@"rules"];
- for(NSDictionary* rule in rules) {
-
- BOOL replace = TRUE;
- int chk = 0;
- NSArray* matches = [rule objectForKey:@"matches"];
- for(NSDictionary* match in matches) {
- NSString* value = [match objectForKey:@"value"];
- NSString* type = [match objectForKey:@"type"];
- NSString* scope = [match objectForKey:@"scope"];
- BOOL isNegative = [[match objectForKey:@"negative"] boolValue];
-
- if([type isEqualToString:@"suffix"]) {
- chk = end;
- }
- // Prefix
- else {
- chk = start - 1;
- }
+ int chunkLen;
+ for(chunkLen = _maxPatternLength; chunkLen > 0; --chunkLen) {
+ end = start + chunkLen;
+ if(end <= len) {
+ NSString* chunk = [fixed substringWithRange:NSMakeRange(start, chunkLen)];
+
+ // Binary Search
+ int left = 0, right = [_patterns count] - 1, mid;
+ while(right >= left) {
+ mid = (right + left) / 2;
+ NSDictionary* pattern = [_patterns objectAtIndex:mid];
+ NSString* find = [pattern objectForKey:@"find"];
+ if([find isEqualToString:chunk]) {
+ NSArray* rules = [pattern objectForKey:@"rules"];
+ for(NSDictionary* rule in rules) {
- // Beginning
- if([scope isEqualToString:@"punctuation"]) {
- if(
- ! (
- (chk < 0 && [type isEqualToString:@"prefix"]) ||
- (chk >= len && [type isEqualToString:@"suffix"]) ||
- [self isPunctuation:[fixed characterAtIndex:chk]]
- ) ^ isNegative
- ) {
- replace = FALSE;
- break;
- }
- }
- // Vowel
- else if([scope isEqualToString:@"vowel"]) {
- if(
- ! (
- (
- (chk >= 0 && [type isEqualToString:@"prefix"]) ||
- (chk < len && [type isEqualToString:@"suffix"])
- ) &&
- [self isVowel:[fixed characterAtIndex:chk]]
- ) ^ isNegative
- ) {
- replace = FALSE;
- break;
- }
- }
- // Consonant
- else if([scope isEqualToString:@"consonant"]) {
- if(
- ! (
- (
- (chk >= 0 && [type isEqualToString:@"prefix"]) ||
- (chk < len && [type isEqualToString:@"suffix"])
- ) &&
- [self isConsonant:[fixed characterAtIndex:chk]]
- ) ^ isNegative
- ) {
- replace = FALSE;
- break;
- }
- }
- // Exact
- else if([scope isEqualToString:@"exact"]) {
- int s, e;
+ BOOL replace = TRUE;
+ int chk = 0;
+ NSArray* matches = [rule objectForKey:@"matches"];
+ for(NSDictionary* match in matches) {
+ NSString* value = [match objectForKey:@"value"];
+ NSString* type = [match objectForKey:@"type"];
+ NSString* scope = [match objectForKey:@"scope"];
+ BOOL isNegative = [[match objectForKey:@"negative"] boolValue];
+
if([type isEqualToString:@"suffix"]) {
- s = end;
- e = end + [value length];
+ chk = end;
}
// Prefix
else {
- s = start - [value length];
- e = start;
+ chk = start - 1;
}
- if(![self isExact:value heystack:fixed start:s end:e not:isNegative]) {
- replace = FALSE;
- break;
+
+ // Beginning
+ if([scope isEqualToString:@"punctuation"]) {
+ if(
+ ! (
+ (chk < 0 && [type isEqualToString:@"prefix"]) ||
+ (chk >= len && [type isEqualToString:@"suffix"]) ||
+ [self isPunctuation:[fixed characterAtIndex:chk]]
+ ) ^ isNegative
+ ) {
+ replace = FALSE;
+ break;
+ }
}
+ // Vowel
+ else if([scope isEqualToString:@"vowel"]) {
+ if(
+ ! (
+ (
+ (chk >= 0 && [type isEqualToString:@"prefix"]) ||
+ (chk < len && [type isEqualToString:@"suffix"])
+ ) &&
+ [self isVowel:[fixed characterAtIndex:chk]]
+ ) ^ isNegative
+ ) {
+ replace = FALSE;
+ break;
+ }
+ }
+ // Consonant
+ else if([scope isEqualToString:@"consonant"]) {
+ if(
+ ! (
+ (
+ (chk >= 0 && [type isEqualToString:@"prefix"]) ||
+ (chk < len && [type isEqualToString:@"suffix"])
+ ) &&
+ [self isConsonant:[fixed characterAtIndex:chk]]
+ ) ^ isNegative
+ ) {
+ replace = FALSE;
+ break;
+ }
+ }
+ // Exact
+ else if([scope isEqualToString:@"exact"]) {
+ int s, e;
+ if([type isEqualToString:@"suffix"]) {
+ s = end;
+ e = end + [value length];
+ }
+ // Prefix
+ else {
+ s = start - [value length];
+ e = start;
+ }
+ if(![self isExact:value heystack:fixed start:s end:e not:isNegative]) {
+ replace = FALSE;
+ break;
+ }
+ }
+ }
+
+ if(replace) {
+ [output appendString:[rule objectForKey:@"replace"]];
+ cur = end - 1;
+ matched = TRUE;
+ break;
}
+
}
- if(replace) {
- [output appendString:[rule objectForKey:@"replace"]];
- cur = end - 1;
- matched = TRUE;
- break;
- }
+ if(matched == TRUE) break;
+ // Default
+ [output appendString:[pattern objectForKey:@"replace"]];
+ cur = end - 1;
+ matched = TRUE;
+ break;
+ }
+ else if ([find length] > [chunk length] ||
+ ([find length] == [chunk length] && [find compare:chunk] == NSOrderedAscending)) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
}
-
- if(matched == true) break;
-
- // Default
- [output appendString:[pattern objectForKey:@"replace"]];
- cur = end - 1;
- matched = TRUE;
- break;
}
+ if(matched == TRUE) break;
}
}
@@ -254,7 +268,8 @@ - (BOOL)isCaseSensitive:(unichar)c {
- (BOOL)isExact:(NSString*) needle heystack:(NSString*)heystack start:(int)start end:(int)end not:(BOOL)not {
// NSLog(@"Cut: %@", [heystack substringWithRange:NSMakeRange(start, end)]);
int len = end - start;
- return ((start >=0 && end < [heystack length] && [[heystack substringWithRange:NSMakeRange(start, len)] isEqualToString:needle]) ^ not);
+ return ((start >= 0 && end < [heystack length]
+ && [[heystack substringWithRange:NSMakeRange(start, len)] isEqualToString:needle]) ^ not);
}
- (unichar) smallCap:(unichar) letter {
Oops, something went wrong.

0 comments on commit 1576baa

Please sign in to comment.