Playlist Generator  1.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Defines
SBJsonStreamParser.m
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, Stig Brautaset.
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without
00006  modification, are permitted provided that the following conditions are
00007  met:
00008 
00009  Redistributions of source code must retain the above copyright
00010  notice, this list of conditions and the following disclaimer.
00011 
00012  Redistributions in binary form must reproduce the above copyright
00013  notice, this list of conditions and the following disclaimer in the
00014  documentation and/or other materials provided with the distribution.
00015 
00016  Neither the name of the the author nor the names of its contributors
00017  may be used to endorse or promote products derived from this software
00018  without specific prior written permission.
00019 
00020  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00024  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00025  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00026  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00027  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00028  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00030  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #import "SBJsonStreamParser.h"
00034 #import "SBJsonTokeniser.h"
00035 #import "SBJsonStreamParserState.h"
00036 #import <limits.h>
00037 
00038 @implementation SBJsonStreamParser
00039 
00040 @synthesize supportMultipleDocuments;
00041 @synthesize error;
00042 @synthesize delegate;
00043 @synthesize maxDepth;
00044 @synthesize state;
00045 @synthesize stateStack;
00046 
00047 #pragma mark Housekeeping
00048 
00049 - (id)init {
00050         self = [super init];
00051         if (self) {
00052                 maxDepth = 32u;
00053         stateStack = [[NSMutableArray alloc] initWithCapacity:maxDepth];
00054         state = [SBJsonStreamParserStateStart sharedInstance];
00055                 tokeniser = [[SBJsonTokeniser alloc] init];
00056         }
00057         return self;
00058 }
00059 
00060 - (void)dealloc {
00061     self.state = nil;
00062 }
00063 
00064 #pragma mark Methods
00065 
00066 - (NSString*)tokenName:(sbjson_token_t)token {
00067         switch (token) {
00068                 case sbjson_token_array_start:
00069                         return @"start of array";
00070                         break;
00071 
00072                 case sbjson_token_array_end:
00073                         return @"end of array";
00074                         break;
00075 
00076                 case sbjson_token_number:
00077                         return @"number";
00078                         break;
00079 
00080                 case sbjson_token_string:
00081                         return @"string";
00082                         break;
00083 
00084                 case sbjson_token_true:
00085                 case sbjson_token_false:
00086                         return @"boolean";
00087                         break;
00088 
00089                 case sbjson_token_null:
00090                         return @"null";
00091                         break;
00092 
00093                 case sbjson_token_keyval_separator:
00094                         return @"key-value separator";
00095                         break;
00096 
00097                 case sbjson_token_separator:
00098                         return @"value separator";
00099                         break;
00100 
00101                 case sbjson_token_object_start:
00102                         return @"start of object";
00103                         break;
00104 
00105                 case sbjson_token_object_end:
00106                         return @"end of object";
00107                         break;
00108 
00109                 case sbjson_token_eof:
00110                 case sbjson_token_error:
00111                         break;
00112         }
00113         NSAssert(NO, @"Should not get here");
00114         return @"<aaiiie!>";
00115 }
00116 
00117 - (void)maxDepthError {
00118     self.error = [NSString stringWithFormat:@"Input depth exceeds max depth of %lu", maxDepth];
00119     self.state = [SBJsonStreamParserStateError sharedInstance];
00120 }
00121 
00122 - (void)handleObjectStart {
00123         if (stateStack.count >= maxDepth) {
00124         [self maxDepthError];
00125         return;
00126         }
00127 
00128     [delegate parserFoundObjectStart:self];
00129     [stateStack addObject:state];
00130     self.state = [SBJsonStreamParserStateObjectStart sharedInstance];
00131 }
00132 
00133 - (void)handleObjectEnd: (sbjson_token_t) tok  {
00134     self.state = [stateStack lastObject];
00135     [stateStack removeLastObject];
00136     [state parser:self shouldTransitionTo:tok];
00137     [delegate parserFoundObjectEnd:self];
00138 }
00139 
00140 - (void)handleArrayStart {
00141         if (stateStack.count >= maxDepth) {
00142         [self maxDepthError];
00143         return;
00144     }
00145         
00146         [delegate parserFoundArrayStart:self];
00147     [stateStack addObject:state];
00148     self.state = [SBJsonStreamParserStateArrayStart sharedInstance];
00149 }
00150 
00151 - (void)handleArrayEnd: (sbjson_token_t) tok  {
00152     self.state = [stateStack lastObject];
00153     [stateStack removeLastObject];
00154     [state parser:self shouldTransitionTo:tok];
00155     [delegate parserFoundArrayEnd:self];
00156 }
00157 
00158 - (void) handleTokenNotExpectedHere: (sbjson_token_t) tok  {
00159     NSString *tokenName = [self tokenName:tok];
00160     NSString *stateName = [state name];
00161 
00162     self.error = [NSString stringWithFormat:@"Token '%@' not expected %@", tokenName, stateName];
00163     self.state = [SBJsonStreamParserStateError sharedInstance];
00164 }
00165 
00166 - (SBJsonStreamParserStatus)parse:(NSData *)data_ {
00167     @autoreleasepool {
00168         [tokeniser appendData:data_];
00169         
00170         for (;;) {
00171             
00172             if ([state isError])
00173                 return SBJsonStreamParserError;
00174             
00175             NSObject *token;
00176             sbjson_token_t tok = [tokeniser getToken:&token];
00177             switch (tok) {
00178                 case sbjson_token_eof:
00179                     return [state parserShouldReturn:self];
00180                     break;
00181                     
00182                 case sbjson_token_error:
00183                     self.state = [SBJsonStreamParserStateError sharedInstance];
00184                     self.error = tokeniser.error;
00185                     return SBJsonStreamParserError;
00186                     break;
00187                     
00188                 default:
00189                     
00190                     if (![state parser:self shouldAcceptToken:tok]) {
00191                         [self handleTokenNotExpectedHere: tok];
00192                         return SBJsonStreamParserError;
00193                     }
00194                     
00195                     switch (tok) {
00196                         case sbjson_token_object_start:
00197                             [self handleObjectStart];
00198                             break;
00199                             
00200                         case sbjson_token_object_end:
00201                             [self handleObjectEnd: tok];
00202                             break;
00203                             
00204                         case sbjson_token_array_start:
00205                             [self handleArrayStart];
00206                             break;
00207                             
00208                         case sbjson_token_array_end:
00209                             [self handleArrayEnd: tok];
00210                             break;
00211                             
00212                         case sbjson_token_separator:
00213                         case sbjson_token_keyval_separator:
00214                             [state parser:self shouldTransitionTo:tok];
00215                             break;
00216                             
00217                         case sbjson_token_true:
00218                             [delegate parser:self foundBoolean:YES];
00219                             [state parser:self shouldTransitionTo:tok];
00220                             break;
00221                             
00222                         case sbjson_token_false:
00223                             [delegate parser:self foundBoolean:NO];
00224                             [state parser:self shouldTransitionTo:tok];
00225                             break;
00226                             
00227                         case sbjson_token_null:
00228                             [delegate parserFoundNull:self];
00229                             [state parser:self shouldTransitionTo:tok];
00230                             break;
00231                             
00232                         case sbjson_token_number:
00233                             [delegate parser:self foundNumber:(NSNumber*)token];
00234                             [state parser:self shouldTransitionTo:tok];
00235                             break;
00236                             
00237                         case sbjson_token_string:
00238                             if ([state needKey])
00239                                 [delegate parser:self foundObjectKey:(NSString*)token];
00240                             else
00241                                 [delegate parser:self foundString:(NSString*)token];
00242                             [state parser:self shouldTransitionTo:tok];
00243                             break;
00244                             
00245                         default:
00246                             break;
00247                     }
00248                     break;
00249             }
00250         }
00251         return SBJsonStreamParserComplete;
00252     }
00253 }
00254 
00255 @end