/* 
 | 
 Copyright (c) 2010-2013, Stig Brautaset. 
 | 
 All rights reserved. 
 | 
  
 | 
 Redistribution and use in source and binary forms, with or without 
 | 
 modification, are permitted provided that the following conditions are 
 | 
 met: 
 | 
  
 | 
   Redistributions of source code must retain the above copyright 
 | 
   notice, this list of conditions and the following disclaimer. 
 | 
  
 | 
   Redistributions in binary form must reproduce the above copyright 
 | 
   notice, this list of conditions and the following disclaimer in the 
 | 
   documentation and/or other materials provided with the distribution. 
 | 
  
 | 
   Neither the name of the the author nor the names of its contributors 
 | 
   may be used to endorse or promote products derived from this software 
 | 
   without specific prior written permission. 
 | 
  
 | 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 | 
 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 | 
 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
 | 
 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 | 
 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 | 
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
 | 
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 | 
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 | 
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 | 
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 | 
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 | 
 */ 
 | 
  
 | 
#import <Foundation/Foundation.h> 
 | 
#import "CSSBJson4StreamParser.h" 
 | 
  
 | 
/** 
 | 
 Block called when the parser has parsed an item. This could be once 
 | 
 for each root document parsed, or once for each unwrapped root array element. 
 | 
  
 | 
 @param item contains the parsed item. 
 | 
 @param stop set to YES if you want the parser to stop 
 | 
 */ 
 | 
typedef void (^CSSBJson4ValueBlock)(id item, BOOL* stop); 
 | 
  
 | 
/** 
 | 
 Block called if an error occurs. 
 | 
 @param error the error. 
 | 
 */ 
 | 
typedef void (^CSSBJson4ErrorBlock)(NSError* error); 
 | 
  
 | 
/** 
 | 
 Block used to process parsed tokens as they are encountered. You can use this 
 | 
 to transform strings containing dates into NSDate, for example. 
 | 
 @param item the parsed token 
 | 
 @param path the JSON Path of the token 
 | 
 */ 
 | 
typedef id (^CSSBJson4ProcessBlock)(id item, NSString* path); 
 | 
  
 | 
  
 | 
/** 
 | 
 Parse one or more chunks of JSON data. 
 | 
  
 | 
 Using this class directly you can reduce the apparent latency for each 
 | 
 download/parse cycle of documents over a slow connection. You can start 
 | 
 parsing *and return chunks of the parsed document* before the entire 
 | 
 document is downloaded. 
 | 
  
 | 
 Using this class is also useful to parse huge documents on disk 
 | 
 bit by bit so you don't have to keep them all in memory. 
 | 
  
 | 
 JSON is mapped to Objective-C types in the following way: 
 | 
  
 | 
 - null    -> NSNull 
 | 
 - string  -> NSString 
 | 
 - array   -> NSMutableArray 
 | 
 - object  -> NSMutableDictionary 
 | 
 - true    -> NSNumber's -numberWithBool:YES 
 | 
 - false   -> NSNumber's -numberWithBool:NO 
 | 
 - number -> NSNumber 
 | 
  
 | 
 Since Objective-C doesn't have a dedicated class for boolean values, 
 | 
 these turns into NSNumber instances. However, since these are 
 | 
 initialised with the -initWithBool: method they round-trip back to JSON 
 | 
 properly. In other words, they won't silently suddenly become 0 or 1; 
 | 
 they'll be represented as 'true' and 'false' again. 
 | 
  
 | 
 Integers are parsed into either a `long long` or `unsigned long long` 
 | 
 type if they fit, else a `double` is used. All real & exponential numbers 
 | 
 are represented using a `double`. Previous versions of this library used 
 | 
 an NSDecimalNumber in some cases, but this is no longer the case. 
 | 
  
 | 
 The default behaviour is that your passed-in block is only called once the 
 | 
 entire input is parsed. If you set supportManyDocuments to YES and your input 
 | 
 contains multiple (whitespace limited) JSON documents your block will be called 
 | 
 for each document: 
 | 
  
 | 
    CSSBJson4ValueBlock block = ^(id v, BOOL *stop) { 
 | 
        BOOL isArray = [v isKindOfClass:[NSArray class]]; 
 | 
        NSLog(@"Found: %@", isArray ? @"Array" : @"Object"); 
 | 
    }; 
 | 
  
 | 
    CSSBJson4ErrorBlock eh = ^(NSError* err) { 
 | 
        NSLog(@"OOPS: %@", err); 
 | 
    }; 
 | 
  
 | 
    id parser = [CSCSSBJson4Parser multiRootParserWithBlock:block 
 | 
                                           errorHandler:eh]; 
 | 
  
 | 
    // Note that this input contains multiple top-level JSON documents 
 | 
    id data = [@"[]{}" dataWithEncoding:NSUTF8StringEncoding]; 
 | 
    [parser parse:data]; 
 | 
    [parser parse:data]; 
 | 
  
 | 
 The above example will print: 
 | 
  
 | 
 - Found: Array 
 | 
 - Found: Object 
 | 
 - Found: Array 
 | 
 - Found: Object 
 | 
  
 | 
 Often you won't have control over the input you're parsing, so can't make use 
 | 
 of this feature. But, all is not lost: if you are parsing a long array you can 
 | 
 get the same effect by setting  rootArrayItems to YES: 
 | 
  
 | 
    id parser = [CSCSSBJson4Parser unwrapRootArrayParserWithBlock:block 
 | 
                                                 errorHandler:eh]; 
 | 
  
 | 
    // Note that this input contains A SINGLE top-level document 
 | 
    id data = [@"[[],{},[],{}]" dataWithEncoding:NSUTF8StringEncoding]; 
 | 
    [parser parse:data]; 
 | 
  
 | 
 @note Stream based parsing does mean that you lose some of the correctness 
 | 
 verification you would have with a parser that considered the entire input 
 | 
 before returning an answer. It is technically possible to have some parts 
 | 
 of a document returned *as if they were correct* but then encounter an error 
 | 
 in a later part of the document. You should keep this in mind when 
 | 
 considering whether it would suit your application. 
 | 
  
 | 
  
 | 
*/ 
 | 
@interface CSSBJson4Parser : NSObject 
 | 
  
 | 
/** 
 | 
 Create a JSON Parser. 
 | 
  
 | 
 This can be used to create a parser that accepts only one document, or one that parses 
 | 
 many documents any 
 | 
  
 | 
 @param block Called for each element. Set *stop to `YES` if you have seen 
 | 
 enough and would like to skip the rest of the elements. 
 | 
  
 | 
 @param allowMultiRoot Indicate that you are expecting multiple whitespace-separated 
 | 
 JSON documents, similar to what Twitter uses. 
 | 
  
 | 
 @param unwrapRootArray If set the parser will pretend an root array does not exist 
 | 
 and the enumerator block will be called once for each item in it. This option 
 | 
 does nothing if the the JSON has an object at its root. 
 | 
  
 | 
 @param eh Called if the parser encounters an error. 
 | 
  
 | 
 @see -unwrapRootArrayParserWithBlock:errorHandler: 
 | 
 @see -multiRootParserWithBlock:errorHandler: 
 | 
 @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler: 
 | 
  
 | 
 */ 
 | 
+ (id)parserWithBlock:(CSSBJson4ValueBlock)block 
 | 
       allowMultiRoot:(BOOL)allowMultiRoot 
 | 
      unwrapRootArray:(BOOL)unwrapRootArray 
 | 
         errorHandler:(CSSBJson4ErrorBlock)eh; 
 | 
  
 | 
  
 | 
/** 
 | 
 Create a JSON Parser that parses multiple whitespace separated documents. 
 | 
 This is useful for something like Twitter's feed, which gives you one JSON 
 | 
 document per line. 
 | 
  
 | 
 @param block Called for each element. Set *stop to `YES` if you have seen 
 | 
 enough and would like to skip the rest of the elements. 
 | 
  
 | 
 @param eh Called if the parser encounters an error. 
 | 
  
 | 
 @see +unwrapRootArrayParserWithBlock:errorHandler: 
 | 
 @see +parserWithBlock:allowMultiRoot:unwrapRootArray:errorHandler: 
 | 
 @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler: 
 | 
 */ 
 | 
+ (id)multiRootParserWithBlock:(CSSBJson4ValueBlock)block 
 | 
                  errorHandler:(CSSBJson4ErrorBlock)eh; 
 | 
  
 | 
/** 
 | 
 Create a JSON Parser that parses a huge array and calls for the value block for 
 | 
 each element in the outermost array. 
 | 
  
 | 
 @param block Called for each element. Set *stop to `YES` if you have seen 
 | 
 enough and would like to skip the rest of the elements. 
 | 
  
 | 
 @param eh Called if the parser encounters an error. 
 | 
  
 | 
 @see +multiRootParserWithBlock:errorHandler: 
 | 
 @see +parserWithBlock:allowMultiRoot:unwrapRootArray:errorHandler: 
 | 
 @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler: 
 | 
 */ 
 | 
+ (id)unwrapRootArrayParserWithBlock:(CSSBJson4ValueBlock)block 
 | 
                        errorHandler:(CSSBJson4ErrorBlock)eh; 
 | 
  
 | 
/** 
 | 
 Create a JSON Parser. 
 | 
  
 | 
 @param block Called for each element. Set *stop to `YES` if you have seen 
 | 
 enough and would like to skip the rest of the elements. 
 | 
  
 | 
 @param processBlock A block that allows you to process individual values before being 
 | 
 returned. 
 | 
  
 | 
 @param multiRoot Indicate that you are expecting multiple whitespace-separated 
 | 
 JSON documents, similar to what Twitter uses. 
 | 
  
 | 
 @param unwrapRootArray If set the parser will pretend an root array does not exist 
 | 
 and the enumerator block will be called once for each item in it. This option 
 | 
 does nothing if the the JSON has an object at its root. 
 | 
  
 | 
 @param maxDepth The max recursion depth of the parser. Defaults to 32. 
 | 
  
 | 
 @param eh Called if the parser encounters an error. 
 | 
  
 | 
 */ 
 | 
- (id)initWithBlock:(CSSBJson4ValueBlock)block 
 | 
       processBlock:(CSSBJson4ProcessBlock)processBlock 
 | 
          multiRoot:(BOOL)multiRoot 
 | 
    unwrapRootArray:(BOOL)unwrapRootArray 
 | 
           maxDepth:(NSUInteger)maxDepth 
 | 
       errorHandler:(CSSBJson4ErrorBlock)eh; 
 | 
  
 | 
/** 
 | 
 Parse some JSON 
 | 
  
 | 
 The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or a part of one. 
 | 
  
 | 
 @param data An NSData object containing the next chunk of JSON 
 | 
  
 | 
 @return 
 | 
 - CSCSSBJson4ParserComplete if a full document was found 
 | 
 - CSCSSBJson4ParserWaitingForData if a partial document was found and more data is required to complete it 
 | 
 - CSCSSBJson4ParserError if an error occurred. 
 | 
  
 | 
 */ 
 | 
- (CSSBJson4ParserStatus)parse:(NSData*)data; 
 | 
  
 | 
@end 
 |