Playlist Generator  1.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Properties Defines
SBJsonUTF8Stream.m
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2011, Stig Brautaset. All rights reserved.
00003  
00004  Redistribution and use in source and binary forms, with or without
00005  modification, are permitted provided that the following conditions are
00006  met:
00007  
00008  Redistributions of source code must retain the above copyright
00009  notice, this list of conditions and the following disclaimer.
00010  
00011  Redistributions in binary form must reproduce the above copyright
00012  notice, this list of conditions and the following disclaimer in the
00013  documentation and/or other materials provided with the distribution.
00014  
00015  Neither the name of the the author nor the names of its contributors
00016  may be used to endorse or promote products derived from this software
00017  without specific prior written permission.
00018  
00019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00020  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00021  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00022  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00023  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00024  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00025  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00029  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #import "SBJsonUTF8Stream.h"
00033 
00034 
00035 @implementation SBJsonUTF8Stream
00036 
00037 @synthesize index = _index;
00038 
00039 - (id)init {
00040     self = [super init];
00041     if (self) {
00042         _data = [[NSMutableData alloc] initWithCapacity:4096u];
00043     }
00044     return self;
00045 }
00046 
00047 
00048 - (void)appendData:(NSData *)data_ {
00049     
00050     if (_index) {
00051         // Discard data we've already parsed
00052                 [_data replaceBytesInRange:NSMakeRange(0, _index) withBytes:"" length:0];
00053         
00054         // Reset index to point to current position
00055                 _index = 0;
00056         }
00057     
00058     [_data appendData:data_];
00059     
00060     // This is an optimisation. 
00061     _bytes = (const char*)[_data bytes];
00062     _length = [_data length];
00063 }
00064 
00065 
00066 - (BOOL)getUnichar:(unichar*)ch {
00067     if (_index < _length) {
00068         *ch = (unichar)_bytes[_index];
00069         return YES;
00070     }
00071     return NO;
00072 }
00073 
00074 - (BOOL)getNextUnichar:(unichar*)ch {
00075     if (++_index < _length) {
00076         *ch = (unichar)_bytes[_index];
00077         return YES;
00078     }
00079     return NO;
00080 }
00081 
00082 - (BOOL)getRetainedStringFragment:(NSString **)string {
00083     NSUInteger start = _index;
00084     while (_index < _length) {
00085         switch (_bytes[_index]) {
00086             case '"':
00087             case '\\':
00088             case 0 ... 0x1f:
00089                 *string = [[NSString alloc] initWithBytes:(_bytes + start) length:(_index - start) encoding:NSUTF8StringEncoding];
00090                 return YES;
00091                 break;
00092             default:
00093                 _index++;
00094                 break;
00095         }
00096     }
00097     return NO;
00098 }
00099 
00100 - (void)skip {
00101     _index++;
00102 }
00103 
00104 - (void)skipWhitespace {
00105     while (_index < _length) {
00106         switch (_bytes[_index]) {
00107             case ' ':
00108             case '\t':
00109             case '\r':
00110             case '\n':
00111                 _index++;
00112                 break;
00113             default:
00114                 return;
00115                 break;
00116         }
00117     }
00118 }
00119 
00120 - (BOOL)haveRemainingCharacters:(NSUInteger)chars {
00121     return [_data length] - _index >= chars;
00122 }
00123 
00124 - (BOOL)skipCharacters:(const char *)chars length:(NSUInteger)len {
00125     const void *bytes = ((const char*)[_data bytes]) + _index;
00126     if (!memcmp(bytes, chars, len)) {
00127         _index += len;
00128         return YES;
00129     }
00130     return NO;
00131 }
00132 
00133 - (NSString*)stringWithRange:(NSRange)range {
00134     return [[NSString alloc] initWithBytes:_bytes + range.location length:range.length encoding:NSUTF8StringEncoding];
00135     
00136 }
00137 
00138 
00139 @end