github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/MobileLibrary/iOS/PsiphonTunnel/PsiphonTunnel/json-framework/SBJson4Parser.h (about)

     1  /*
     2   Copyright (c) 2010-2013, Stig Brautaset.
     3   All rights reserved.
     4  
     5   Redistribution and use in source and binary forms, with or without
     6   modification, are permitted provided that the following conditions are
     7   met:
     8  
     9     Redistributions of source code must retain the above copyright
    10     notice, this list of conditions and the following disclaimer.
    11  
    12     Redistributions in binary form must reproduce the above copyright
    13     notice, this list of conditions and the following disclaimer in the
    14     documentation and/or other materials provided with the distribution.
    15  
    16     Neither the name of the the author nor the names of its contributors
    17     may be used to endorse or promote products derived from this software
    18     without specific prior written permission.
    19  
    20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    21   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    22   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    23   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    24   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    25   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    26   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    27   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    28   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    29   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    30   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31   */
    32  
    33  #import <Foundation/Foundation.h>
    34  #import "SBJson4StreamParser.h"
    35  
    36  /**
    37   Block called when the parser has parsed an item. This could be once
    38   for each root document parsed, or once for each unwrapped root array element.
    39  
    40   @param item contains the parsed item.
    41   @param stop set to YES if you want the parser to stop
    42   */
    43  typedef void (^SBJson4ValueBlock)(id item, BOOL* stop);
    44  
    45  /**
    46   Block called if an error occurs.
    47   @param error the error.
    48   */
    49  typedef void (^SBJson4ErrorBlock)(NSError* error);
    50  
    51  /**
    52   Block used to process parsed tokens as they are encountered. You can use this
    53   to transform strings containing dates into NSDate, for example.
    54   @param item the parsed token
    55   @param path the JSON Path of the token
    56   */
    57  typedef id (^SBJson4ProcessBlock)(id item, NSString* path);
    58  
    59  
    60  /**
    61   Parse one or more chunks of JSON data.
    62  
    63   Using this class directly you can reduce the apparent latency for each
    64   download/parse cycle of documents over a slow connection. You can start
    65   parsing *and return chunks of the parsed document* before the entire
    66   document is downloaded.
    67  
    68   Using this class is also useful to parse huge documents on disk
    69   bit by bit so you don't have to keep them all in memory.
    70  
    71   JSON is mapped to Objective-C types in the following way:
    72  
    73   - null    -> NSNull
    74   - string  -> NSString
    75   - array   -> NSMutableArray
    76   - object  -> NSMutableDictionary
    77   - true    -> NSNumber's -numberWithBool:YES
    78   - false   -> NSNumber's -numberWithBool:NO
    79   - number -> NSNumber
    80  
    81   Since Objective-C doesn't have a dedicated class for boolean values,
    82   these turns into NSNumber instances. However, since these are
    83   initialised with the -initWithBool: method they round-trip back to JSON
    84   properly. In other words, they won't silently suddenly become 0 or 1;
    85   they'll be represented as 'true' and 'false' again.
    86  
    87   Integers are parsed into either a `long long` or `unsigned long long`
    88   type if they fit, else a `double` is used. All real & exponential numbers
    89   are represented using a `double`. Previous versions of this library used
    90   an NSDecimalNumber in some cases, but this is no longer the case.
    91  
    92   The default behaviour is that your passed-in block is only called once the
    93   entire input is parsed. If you set supportManyDocuments to YES and your input
    94   contains multiple (whitespace limited) JSON documents your block will be called
    95   for each document:
    96  
    97      SBJson4ValueBlock block = ^(id v, BOOL *stop) {
    98          BOOL isArray = [v isKindOfClass:[NSArray class]];
    99          NSLog(@"Found: %@", isArray ? @"Array" : @"Object");
   100      };
   101  
   102      SBJson4ErrorBlock eh = ^(NSError* err) {
   103          NSLog(@"OOPS: %@", err);
   104      };
   105  
   106      id parser = [SBJson4Parser multiRootParserWithBlock:block
   107                                             errorHandler:eh];
   108  
   109      // Note that this input contains multiple top-level JSON documents
   110      id data = [@"[]{}" dataWithEncoding:NSUTF8StringEncoding];
   111      [parser parse:data];
   112      [parser parse:data];
   113  
   114   The above example will print:
   115  
   116   - Found: Array
   117   - Found: Object
   118   - Found: Array
   119   - Found: Object
   120  
   121   Often you won't have control over the input you're parsing, so can't make use
   122   of this feature. But, all is not lost: if you are parsing a long array you can
   123   get the same effect by setting  rootArrayItems to YES:
   124  
   125      id parser = [SBJson4Parser unwrapRootArrayParserWithBlock:block
   126                                                   errorHandler:eh];
   127  
   128      // Note that this input contains A SINGLE top-level document
   129      id data = [@"[[],{},[],{}]" dataWithEncoding:NSUTF8StringEncoding];
   130      [parser parse:data];
   131  
   132   @note Stream based parsing does mean that you lose some of the correctness
   133   verification you would have with a parser that considered the entire input
   134   before returning an answer. It is technically possible to have some parts
   135   of a document returned *as if they were correct* but then encounter an error
   136   in a later part of the document. You should keep this in mind when
   137   considering whether it would suit your application.
   138  
   139  
   140  */
   141  @interface SBJson4Parser : NSObject
   142  
   143  /**
   144   Create a JSON Parser.
   145  
   146   This can be used to create a parser that accepts only one document, or one that parses
   147   many documents any
   148  
   149   @param block Called for each element. Set *stop to `YES` if you have seen
   150   enough and would like to skip the rest of the elements.
   151  
   152   @param allowMultiRoot Indicate that you are expecting multiple whitespace-separated
   153   JSON documents, similar to what Twitter uses.
   154  
   155   @param unwrapRootArray If set the parser will pretend an root array does not exist
   156   and the enumerator block will be called once for each item in it. This option
   157   does nothing if the the JSON has an object at its root.
   158  
   159   @param eh Called if the parser encounters an error.
   160  
   161   @see -unwrapRootArrayParserWithBlock:errorHandler:
   162   @see -multiRootParserWithBlock:errorHandler:
   163   @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler:
   164  
   165   */
   166  + (id)parserWithBlock:(SBJson4ValueBlock)block
   167         allowMultiRoot:(BOOL)allowMultiRoot
   168        unwrapRootArray:(BOOL)unwrapRootArray
   169           errorHandler:(SBJson4ErrorBlock)eh;
   170  
   171  
   172  /**
   173   Create a JSON Parser that parses multiple whitespace separated documents.
   174   This is useful for something like Twitter's feed, which gives you one JSON
   175   document per line.
   176  
   177   @param block Called for each element. Set *stop to `YES` if you have seen
   178   enough and would like to skip the rest of the elements.
   179  
   180   @param eh Called if the parser encounters an error.
   181  
   182   @see +unwrapRootArrayParserWithBlock:errorHandler:
   183   @see +parserWithBlock:allowMultiRoot:unwrapRootArray:errorHandler:
   184   @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler:
   185   */
   186  + (id)multiRootParserWithBlock:(SBJson4ValueBlock)block
   187                    errorHandler:(SBJson4ErrorBlock)eh;
   188  
   189  /**
   190   Create a JSON Parser that parses a huge array and calls for the value block for
   191   each element in the outermost array.
   192  
   193   @param block Called for each element. Set *stop to `YES` if you have seen
   194   enough and would like to skip the rest of the elements.
   195  
   196   @param eh Called if the parser encounters an error.
   197  
   198   @see +multiRootParserWithBlock:errorHandler:
   199   @see +parserWithBlock:allowMultiRoot:unwrapRootArray:errorHandler:
   200   @see -initWithBlock:processBlock:multiRoot:unwrapRootArray:maxDepth:errorHandler:
   201   */
   202  + (id)unwrapRootArrayParserWithBlock:(SBJson4ValueBlock)block
   203                          errorHandler:(SBJson4ErrorBlock)eh;
   204  
   205  /**
   206   Create a JSON Parser.
   207  
   208   @param block Called for each element. Set *stop to `YES` if you have seen
   209   enough and would like to skip the rest of the elements.
   210  
   211   @param processBlock A block that allows you to process individual values before being
   212   returned.
   213  
   214   @param multiRoot Indicate that you are expecting multiple whitespace-separated
   215   JSON documents, similar to what Twitter uses.
   216  
   217   @param unwrapRootArray If set the parser will pretend an root array does not exist
   218   and the enumerator block will be called once for each item in it. This option
   219   does nothing if the the JSON has an object at its root.
   220  
   221   @param maxDepth The max recursion depth of the parser. Defaults to 32.
   222  
   223   @param eh Called if the parser encounters an error.
   224  
   225   */
   226  - (id)initWithBlock:(SBJson4ValueBlock)block
   227         processBlock:(SBJson4ProcessBlock)processBlock
   228            multiRoot:(BOOL)multiRoot
   229      unwrapRootArray:(BOOL)unwrapRootArray
   230             maxDepth:(NSUInteger)maxDepth
   231         errorHandler:(SBJson4ErrorBlock)eh;
   232  
   233  /**
   234   Parse some JSON
   235  
   236   The JSON is assumed to be UTF8 encoded. This can be a full JSON document, or a part of one.
   237  
   238   @param data An NSData object containing the next chunk of JSON
   239  
   240   @return
   241   - SBJson4ParserComplete if a full document was found
   242   - SBJson4ParserWaitingForData if a partial document was found and more data is required to complete it
   243   - SBJson4ParserError if an error occurred.
   244  
   245   */
   246  - (SBJson4ParserStatus)parse:(NSData*)data;
   247  
   248  @end