source: proto/JSON/json_prototype.py @ 698

Last change on this file since 698 was 698, checked in by ksherdy, 8 years ago

Add JSON string handling.

File size: 21.7 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# json_prototype.py
4#
5# Ken Herdy
6# Oct. 13, 2010
7#
8#----------------------------------------------------------------------------
9#
10# We use python's unlimited precision integers for unbounded bit streams.
11# This permits simple logical operations on the entire stream.
12# Assumption: bitstreams are little-endian (e.g., as on x86).
13#
14#----------------------------------------------------------------------------
15#
16
17import bitutil
18import byteclass
19import u8u16
20import math
21import sys
22
23debug = False
24filename = "json_prototype.py"
25
26# NOTE
27#
28# Spans - Do not include the final character.
29#
30
31
32# Globals
33#
34# Bitstream function defs input/output *only* bitstream type variables.
35# Global declarations allow debug blocks in bitstream defs. Do not shadow variables.
36u8data = ""
37lgth = 0
38
39def simd_const_4(hexdigit,EOF_mask):
40        r"""
41        IDISA library function.
42        """
43        lgth = bitutil.count_leading_zeroes(~EOF_mask)/4
44        return int(hexdigit*(lgth+1),16)&EOF_mask
45       
46def parse_escape(Lex, EOF_mask):
47        r"""
48        Marks escaped characters.
49        Does not mark escaped '\' characters.
50        '\' characters are either escaped and unmarked or the following character in an odd length run is marked.
51        """
52
53        odd = simd_const_4('a',EOF_mask)
54        even = simd_const_4('5',EOF_mask)
55       
56        start = Lex.RSolidus &~ bitutil.Advance(Lex.RSolidus)
57       
58        even_start = start & even
59        even_final = (even_start + Lex.RSolidus) & ~Lex.RSolidus
60        even_escape = even_final & odd
61       
62        odd_start = start & odd
63        odd_final = (odd_start + Lex.RSolidus) & ~Lex.RSolidus
64        odd_escape = (odd_final & even)
65
66        escape = (even_escape | odd_escape) 
67       
68        return escape
69       
70def demo_parse_escape(u8data):
71        global lgth
72        lgth = len(u8data)
73
74        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
75        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit)
76        (escape) = parse_escape(Lex,EOF_mask)
77
78        bitutil.print_aligned_streams([('Input Data', u8data), 
79                              ('Lex.RSolidus', bitutil.bitstream2string(Lex.RSolidus, lgth)),   
80                              ('escape', bitutil.bitstream2string(escape, lgth)),       
81                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1))])
82        return
83
84def parallel_prefix_parity(strm,lgth):
85        r"""
86        Translate to library function.
87       
88        x y  x XOR y
89        ------------
90        0 0   0
91        0 1   1
92        1 0   1
93        0 0   0
94
95        Let n = length(bitstream).
96
97        Define Pk,i as the parity of the bit range [k-(k+2^i),k] for bit positions n >= k >= 1.
98       
99        Base Case: Pk,0 = bitstream at position k, for all k, n >= k >= 0.
100        Inductive Step: Pk,i+1 = (Pk,i << 2^i) XOR Pk,i.
101       
102        Pk,ceil(log(n) denotes the parity of the bit position k, n >= k >= 0.
103       
104        bitstream[k] = 1 --> odd parity
105        bitstream[k] = 0 --> even parity
106        """
107        t1 = strm
108        for i in range(0,int(math.ceil(math.log(lgth,2)))):
109                t2 = t1 ^ (t1 << pow(2,i))
110                t1 = t2
111        return t2 
112
113def demo_parallel_prefix_parity(u8data):
114        r"""
115        >>> demo_parallel_prefix_parity('"data" "data""data" "data" "data')
116        Input Data: "data" "data""data" "data" "data
117        Lex.DQuote: 1____1_1____11____1_1____1_1____
118        Parity    : 11111__11111_11111__11111__11111
119        EOF_Mask  : 11111111111111111111111111111111_
120        <BLANKLINE>
121        """
122        global lgth
123        lgth = len(u8data)
124       
125        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
126        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit)
127        ParityMask = parallel_prefix_parity(Lex.DQuote,lgth)
128       
129        bitutil.print_aligned_streams([('Input Data', u8data), 
130                              ('Lex.DQuote', bitutil.bitstream2string(Lex.DQuote, lgth)),
131                              ('Parity', bitutil.bitstream2string(ParityMask, lgth)),   
132                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1))])
133        return
134
135def value_starts(Lex,StringMask,EscapeChars,lgth):
136        r"""
137        This function returns multi-cursor start positions for each JSON value type.
138        """
139        ValueStartsMask = (StringMask | EscapeChars)
140       
141        ObjectStarts = Lex.LCurlyBrace &~ ValueStartsMask
142        ArrayStarts = Lex.LSquareBracket &~ ValueStartsMask
143       
144        Comma = Lex.Comma &~ ValueStartsMask
145        Colon = Lex.Colon &~ ValueStartsMask
146       
147        NonStringSyncPoint = (ArrayStarts | Comma | Colon)
148        StringSyncPoint = (ObjectStarts | NonStringSyncPoint)
149       
150        StringSyncPointFollows = bitutil.Advance(StringSyncPoint)
151        StringStarts = (StringSyncPointFollows | bitutil.ScanThru(StringSyncPointFollows,Lex.WS)) & (Lex.DQuote &~ ValueStartsMask)
152
153        NonStringSyncPointFollows = bitutil.Advance(NonStringSyncPoint)
154        ValueCursors = (StringSyncPointFollows | bitutil.ScanThru(StringSyncPointFollows,Lex.WS))
155       
156        NumberStarts = ValueCursors & ((Lex.Minus|Lex.Digit0_9) &~ ValueStartsMask) 
157        TrueStarts = ValueCursors & (Lex.t &~ ValueStartsMask)
158        FalseStarts = ValueCursors & (Lex.f &~ ValueStartsMask)
159        NullStarts = ValueCursors & (Lex.n &~ ValueStartsMask)
160       
161        if debug:
162                bitutil.print_aligned_streams([('Input Data', u8data), 
163                              ('ValueStartsMask', bitutil.bitstream2string(ValueStartsMask, lgth)),
164                              ('Comma', bitutil.bitstream2string(Comma, lgth)),
165                              ('Colon', bitutil.bitstream2string(Colon, lgth)),
166                              ('Lex.DQuote &~ ValueStartsMask', bitutil.bitstream2string((Lex.DQuote &~ ValueStartsMask), lgth)),
167                              ('NonStringSyncPoint', bitutil.bitstream2string(NonStringSyncPoint, lgth)),
168                              ('StringSyncPoint', bitutil.bitstream2string(StringSyncPoint, lgth)),
169                              ('StringSyncPointFollows', bitutil.bitstream2string(StringSyncPointFollows, lgth)),
170                              ('StringStarts', bitutil.bitstream2string(StringStarts, lgth)),
171                              ('NonStringSyncPointFollows', bitutil.bitstream2string(NonStringSyncPointFollows, lgth)),
172                              ('ValueCursors', bitutil.bitstream2string(ValueCursors, lgth))])
173       
174        return (ObjectStarts, ArrayStarts, StringStarts, NumberStarts, TrueStarts, FalseStarts, NullStarts)
175
176
177def demo_value_starts(u8data):
178        global lgth
179        lgth = len(u8data)
180               
181        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
182        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit) 
183       
184        EscapeChars = parse_escape(Lex, EOF_mask)
185       
186        UnescapedDQuotes = (Lex.DQuote &~ EscapeChars)
187       
188        ParityMask = parallel_prefix_parity(UnescapedDQuotes, lgth) & EOF_mask # TODO - Solve EOF_mask problem
189        StringMask = ParityMask & bitutil.Advance(ParityMask)   
190       
191        (ObjectStarts, ArrayStarts, StringStarts, NumberStarts,TrueStarts, FalseStarts, NullStarts) = value_starts(Lex, StringMask,EscapeChars,lgth)
192        bitutil.print_aligned_streams([('Input Data', u8data), 
193                              ('ObjectStarts', bitutil.bitstream2string(ObjectStarts, lgth)),
194                              ('ArrayStarts', bitutil.bitstream2string(ArrayStarts, lgth)),
195                              ('StringStarts', bitutil.bitstream2string(StringStarts, lgth)),
196                              ('NumberStarts', bitutil.bitstream2string(NumberStarts, lgth)),
197                              ('TrueStarts', bitutil.bitstream2string(TrueStarts, lgth)),
198                              ('FalseStarts', bitutil.bitstream2string(FalseStarts, lgth)),
199                              ('NullStarts', bitutil.bitstream2string(NullStarts, lgth)),
200                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1))])       
201        return
202
203
204def validate_true_false_null(Lex, EOF_mask):
205        r"""
206        RFC 4627 - JavaScript Object Notation (JSON) 
207
208        true  = %x74.72.75.65      ; true
209        false = %x66.61.6c.73.65   ; false
210        null  = %x6e.75.6c.6c      ; null
211       
212        global lgth
213        lgth = len(u8data)
214        """
215        Errors = 0
216       
217        return Errors
218 
219def demo_true_false_null(u8date):
220        global lgth
221        lgth = len(u8data)
222               
223        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
224        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit) 
225        Errors = validate_true_false_null(Lex, EOF_mask)
226       
227        bitutil.print_aligned_streams([('Input Data', u8data), 
228                              ('Errors', bitutil.bitstream2string(Errors, lgth)),
229                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1))])       
230        return
231 
232
233def validate_number(Lex, EOF_mask):
234        r"""   
235        RFC 4627 - JavaScript Object Notation (JSON) 
236        RFC 5234 - Augmented BNF for Syntax Specifications: ABNF
237
238        number = [ minus ] int [ frac ] [ exp ]
239        decimal-point = %x2E       ; .
240        digit1-9 = %x31-39         ; 1-9
241        e = %x65 / %x45            ; e E
242        exp = e [ minus / plus ] 1*DIGIT
243        frac = decimal-point 1*DIGIT
244        int = zero / ( digit1-9 *DIGIT )
245        minus = %x2D               ; -
246        plus = %x2B                ; +
247        zero = %x30                ; 0 
248        """     
249        Errors = 0
250        M0 = 0                                                  # Initialize marker stream     
251       
252        # WARNING - A hack to set initial cursor positions.
253        ColonCommaLSquareBracket = 0 
254        ColonCommaLSquareBracket = Lex.Colon | Lex.Comma | Lex.LSquareBracket
255        AfterColonCommaLSquareBracket = bitutil.Advance(ColonCommaLSquareBracket)
256        M0 = bitutil.ScanThru(AfterColonCommaLSquareBracket, Lex.WS)
257       
258        M1 = bitutil.ScanThru(M0, Lex.Minus & M0)               # ? Optional character class [-]
259        E1 = M1 &~(Lex.Zero|Lex.Digit1_9)
260
261        M1a = M1 & Lex.Zero                                     # Split
262        M1b = M1 & Lex.Digit0_9                         
263        M2a = bitutil.Advance(M1a)
264        M2b = bitutil.Advance(M1b)
265        M3b = bitutil.ScanThru(M2b,Lex.Digit0_9)
266        M4 = M2a | M3b                                          # Join
267       
268        M4a = M4 &~(Lex.DecimalPoint)                           # Split
269        M4b = M4 & (Lex.DecimalPoint)
270        M5b = bitutil.Advance(M4b)
271        E5b = M5b &~(Lex.Digit0_9)                              # + [0-9]+
272        M6 = bitutil.ScanThru(M5b,Lex.Digit0_9)
273        M7 = M4a | M6                                           # Join
274       
275        M7a = M7 &~(Lex.Ee)                                     # Split
276        # NOTE - Number Follow Set logic is to be handled at a higher level     
277        E7a = M7a &~(Lex.NumberFollowSet)
278        M7b = M7 &(Lex.Ee)
279        M8b = bitutil.Advance(M7b)
280        M9b = bitutil.ScanThru(M8b, Lex.PlusMinus & M8b)        # ? Optional character class [+-]               
281        E9b  = M9b &~(Lex.Digit0_9)                             # + [0-9]+
282        M10b = bitutil.ScanThru(M9b,Lex.Digit0_9)
283        # NOTE - Number Follow Set logic is to be handled at a higher level
284        # E10b = M10b &~(Lex.NumberFollowSet)
285        M11 = M7a | M10b                                        # Join
286       
287        # NOTE - Number Follow Set logic is to be handled at a higher level
288        FollowSetErrors = M11 &~ Lex.NumberFollowSet
289       
290        Errors = E1 | E5b | E9b | FollowSetErrors # E7a | E10b
291       
292        if debug:
293                bitutil.print_aligned_streams([('Input Data', u8data), 
294                              ('M0', bitutil.bitstream2string(M0, lgth)),
295                              ('M1', bitutil.bitstream2string(M1, lgth)),
296                              ('E1', bitutil.bitstream2string(E1, lgth+1)),
297                              ('M1a', bitutil.bitstream2string(M1a, lgth)),
298                              ('M2a', bitutil.bitstream2string(M2a, lgth)),
299                              ('M2b', bitutil.bitstream2string(M2b, lgth)),
300                              ('M3b', bitutil.bitstream2string(M3b, lgth)),
301                              ('M4', bitutil.bitstream2string(M4, lgth)),
302                              ('M4a', bitutil.bitstream2string(M4a, lgth)),
303                              ('M4b', bitutil.bitstream2string(M4b, lgth)),
304                              ('M5b', bitutil.bitstream2string(M5b, lgth)),
305                              ('E5b', bitutil.bitstream2string(E5b, lgth+1)),         
306                              ('M6', bitutil.bitstream2string(M6, lgth)),
307                              ('M7', bitutil.bitstream2string(M7, lgth)),
308                              ('M7a', bitutil.bitstream2string(M7a, lgth)),
309                              #('E7a', bitutil.bitstream2string(E7a, lgth+1)),                                               
310                              ('M7b', bitutil.bitstream2string(M7b, lgth)),
311                              ('M8b', bitutil.bitstream2string(M8b, lgth)),
312                              ('M9b', bitutil.bitstream2string(M9b, lgth)),           
313                              ('E9b', bitutil.bitstream2string(E9b, lgth+1)),         
314                              ('M10b', bitutil.bitstream2string(M10b, lgth)),
315                              #('E10b', bitutil.bitstream2string(E10b, lgth)),
316                              ('M11', bitutil.bitstream2string(M11, lgth)),
317                              ('FollowSetErrors', bitutil.bitstream2string(FollowSetErrors, lgth+1)),                         
318                              ('Errors', bitutil.bitstream2string(Errors, lgth+1))])           
319        return Errors
320
321def demo_validate_number(u8data):
322        r"""
323        >>> demo_validate_number('[-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789]')
324        Input Data  : [-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789]
325        Minus       : _1_11_1_____1___1___1____1_______1_______1_________________________
326        Zero        : _________11__11__1___1____1___11___________1______1__1__1__________
327        Digit1_9    : __________________________________111_111____111____1____111111111_
328        Digit0_9    : _________11__11__1___1____1___11__111_111__1_111__1_11__1111111111_
329        DecimalPoint: __________________1___1____1_________1______1______________________
330        Ee          : _______________________1____1______________________1_______________
331        PlusMinus   : _1_11_1_____1___1___1____1_______1_______1______1_____1____________
332        EOF_Mask    : 1111111111111111111111111111111111111111111111111111111111111111111_
333        Errors      : __1_1__1__1___1____1___11___11_1_________1______1_____1__1__________
334        <BLANKLINE>
335
336        >>> demo_validate_number('[0.5,98.6,99.44,1066,1e1,0.1e1,1e-1,1e00,2e+00,2e-00,1234567890,-9876.543210,0.123456789e-12,1.234567890E+34,23456789012E66]')
337        Input Data  : [0.5,98.6,99.44,1066,1e1,0.1e1,1e-1,1e00,2e+00,2e-00,1234567890,-9876.543210,0.123456789e-12,1.234567890E+34,23456789012E66]
338        Minus       : _________________________________1_______________1______________1________________________1__________________________________
339        Zero        : _1_______________1_______1____________11____11____11__________1____________1_1_________________________1_____________1______
340        Digit1_9    : ___1_11_1_11_11_1_11_1_1___1_1_1__1_1____1_____1_____111111111___1111_11111____111111111__11_1_11111111___11_11111111_11_11_
341        Digit0_9    : _1_1_11_1_11_11_1111_1_1_1_1_1_1__1_1_11_1__11_1__11_1111111111__1111_111111_1_111111111__11_1_111111111__11_11111111111_11_
342        DecimalPoint: __1____1____1_____________1__________________________________________1________1_______________1_____________________________
343        Ee          : ______________________1_____1___1____1____1_____1_______________________________________1_______________1_______________1___
344        PlusMinus   : _________________________________1_________1_____1______________1________________________1_______________1__________________
345        EOF_Mask    : 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_
346        Errors      : _____________________________________________________________________________________________________________________________
347        <BLANKLINE>
348
349        >>> demo_validate_number('[012345,12345,0,00,-0,-00]')
350        Input Data  : [012345,12345,0,00,-0,-00]
351        Minus       : ___________________1__1___
352        Zero        : _1____________1_11__1__11_
353        Digit1_9    : __11111_11111_____________
354        Digit0_9    : _111111_11111_1_11__1__11_
355        DecimalPoint: __________________________
356        Ee          : __________________________
357        PlusMinus   : ___________________1__1___
358        EOF_Mask    : 11111111111111111111111111_
359        Errors      : __1______________1______1__
360        <BLANKLINE>
361        """ 
362        global lgth
363        lgth = len(u8data)
364
365        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
366        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit)
367        Errors = validate_number(Lex,EOF_mask)
368
369        bitutil.print_aligned_streams([('Input Data', u8data), 
370                              ('Minus', bitutil.bitstream2string(Lex.Minus, lgth)),
371                              ('Zero', bitutil.bitstream2string(Lex.Zero, lgth)),
372                              ('Digit1_9', bitutil.bitstream2string(Lex.Digit1_9, lgth)),
373                              ('Digit0_9', bitutil.bitstream2string(Lex.Digit0_9, lgth)),
374                              ('DecimalPoint', bitutil.bitstream2string(Lex.DecimalPoint, lgth)),
375                              ('Ee', bitutil.bitstream2string(Lex.Ee, lgth)),
376                              ('PlusMinus', bitutil.bitstream2string(Lex.PlusMinus, lgth)),
377                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1)),
378                              ('Errors', bitutil.bitstream2string(Errors, lgth+1))])
379
380def validate_string(StringStarts, Lex,Ctrl,StringMask,EscapeChars,UnescapedDQuotes, lgth):
381        r"""
382        RFC 4627 - JavaScript Object Notation (JSON) 
383
384        string = quotation-mark *char quotation-mark
385        char = unescaped /
386              escape (
387                  %x22 /          ; "    quotation mark  U+0022
388                  %x5C /          ; \    reverse solidus U+005C
389                  %x2F /          ; /    solidus         U+002F
390                  %x62 /          ; b    backspace       U+0008
391                  %x66 /          ; f    form feed       U+000C
392                  %x6E /          ; n    line feed       U+000A
393                  %x72 /          ; r    carriage return U+000D
394                  %x74 /          ; t    tab             U+0009
395                  %x75 4HEXDIG )  ; uXXXX                U+XXXX
396
397        escape = %x5C              ; \
398        quotation-mark = %x22      ; "
399        unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
400
401        JSON string validation requires both:
402        (1) validation of escape characters,
403        (2) validation of unescaped characters.
404        """
405       
406        # (1) Validate escape characters
407        StringEscapeChars = EscapeChars & StringMask
408        Errors = (StringEscapeChars &~ Lex.Escape)
409       
410        u = StringEscapeChars & Lex.u
411       
412        uScope1 = bitutil.Advance(u)
413        uScope2 = bitutil.Advance(uScope1)
414        uScope3 = bitutil.Advance(uScope2)
415        uScope4 = bitutil.Advance(uScope3)
416       
417        Errors |= uScope1 &~ Lex.HexDigit
418        Errors |= uScope2 &~ Lex.HexDigit
419        Errors |= uScope3 &~ Lex.HexDigit
420        Errors |= uScope4 &~ Lex.HexDigit
421       
422        # (2) Validation of unescaped characters
423        # (2.1) StringMask construction ensures all '"' are escaped.
424        # (2.2) '\' are either correctly escaped or the character following an odd length run is escaped.
425        # (2.3) validate_utf8(u8) ensures valid UTF8 encodings in the code point range U+0000 - U+01FFFF. TODO
426
427        StringNotEscapedChars = (~(EscapeChars | Lex.RSolidus)) & StringMask # TODO - Verify logic.
428        Errors |= (StringNotEscapedChars & Ctrl.x00_x1F)
429       
430        # (3) Validate all strings are terminated with an unescaped "
431        StringCursor = bitutil.Advance(StringStarts)
432        StringEnds = bitutil.ScanThru(StringCursor, StringMask)
433        Errors |= StringEnds &~ UnescapedDQuotes
434        StringSpans = StringEnds - StringStarts
435       
436        if debug:
437                bitutil.print_aligned_streams([('Input Data', u8data), 
438                              ('EscapeChars', bitutil.bitstream2string(EscapeChars, lgth)),
439                              ('StringEscapeChars', bitutil.bitstream2string(StringEscapeChars, lgth)),
440                              ('u', bitutil.bitstream2string(u, lgth)),
441                              ('uScope1', bitutil.bitstream2string(uScope1, lgth)),
442                              ('uScope2', bitutil.bitstream2string(uScope2, lgth)),
443                              ('uScope3', bitutil.bitstream2string(uScope3, lgth)),
444                              ('uScope4', bitutil.bitstream2string(uScope4, lgth)),
445                              ('StringNotEscapedChars', bitutil.bitstream2string(StringNotEscapedChars, lgth)),
446                              ('StringStarts', bitutil.bitstream2string(StringStarts, lgth)),
447                              ('StringEnds', bitutil.bitstream2string(StringEnds, lgth)),
448                              ('StringSpans', bitutil.bitstream2string(StringSpans, lgth)),
449                              ('Errors', bitutil.bitstream2string(Errors, lgth+1))])     
450        return (Errors, StringSpans)
451
452def demo_validate_string(u8data):
453        r"""
454        >>> demo_validate_string('{"\u abcd", "\u1___", "\u12__", "\u123_"}')
455        Input Data      : {"\u abcd", "\u1___", "\u12__", "\u123_"}
456        EscapeChars     : ___1__________1_________1_________1______
457        UnescapedDQuotes: _1_______1__1______1__1______1__1______1_
458        ParityMask      : _11111111___1111111___1111111___1111111__
459        StringMask      : __1111111____111111____111111____111111__
460        StringStarts    : _1__________1_________1_________1________
461        StringSpans     : _11111111___1111111___1111111___1111111__
462        EOF_Mask        : 11111111111111111111111111111111111111111_
463        Errors          : ____1___________111________11_________1___
464        <BLANKLINE>
465        """ 
466        global lgth
467        lgth = len(u8data)
468
469        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
470        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit)
471       
472        # Construct string interior mask (1),(2),(3)
473        # (1) Mark all escaped characters
474        EscapeChars = parse_escape(Lex, EOF_mask)
475       
476        # (2) Mark all unescaped "
477        UnescapedDQuotes = (Lex.DQuote &~ EscapeChars)
478       
479        # (3) Construct mask
480        ParityMask = parallel_prefix_parity(UnescapedDQuotes, lgth) & EOF_mask # TODO - Solve EOF_mask problem
481        StringMask = ParityMask & bitutil.Advance(ParityMask)
482                               
483        (ObjectStarts, ArrayStarts, StringStarts, NumberStarts, TrueStarts, FalseStarts, NullStarts) = value_starts(Lex, StringMask, EscapeChars,lgth)                         
484                               
485        (Errors, StringSpans) = validate_string(StringStarts, Lex,Ctrl,StringMask,EscapeChars,UnescapedDQuotes,lgth)
486       
487        bitutil.print_aligned_streams([('Input Data', u8data), 
488                              ('EscapeChars', bitutil.bitstream2string(EscapeChars, lgth)),
489                              ('UnescapedDQuotes', bitutil.bitstream2string(UnescapedDQuotes, lgth)),
490                              ('ParityMask', bitutil.bitstream2string(ParityMask, lgth)),
491                              ('StringMask', bitutil.bitstream2string(StringMask, lgth)),
492                              ('StringStarts', bitutil.bitstream2string(StringStarts, lgth)),
493                              ('StringSpans', bitutil.bitstream2string(StringSpans, lgth)),
494                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1)),
495                              ('Errors', bitutil.bitstream2string(Errors, lgth+1))])   
496                             
497        return
498
499def validate_json(u8data,lgth):
500               
501        Errors = 0       
502               
503        (bit, EOF_mask) = bitutil.transpose_streams(u8data)
504       
505        (u8, Lex, Ctrl) = byteclass.classify_bytes(bit) 
506       
507        EscapeChars = parse_escape(Lex, EOF_mask)
508       
509        UnescapedDQuotes = (Lex.DQuote &~ EscapeChars)
510       
511        ParityMask = parallel_prefix_parity(UnescapedDQuotes, lgth) & EOF_mask # TODO - Solve EOF_mask problem
512        StringMask = ParityMask & bitutil.Advance(ParityMask)   
513       
514        (ObjectStarts, ArrayStarts, StringStarts, NumberStarts, TrueStarts, FalseStarts, NullStarts) = value_starts(Lex, StringMask, EscapeChars,lgth)
515       
516        (StringErrors, StringSpans) = validate_string(StringStarts, Lex, Ctrl, StringMask, EscapeChars, UnescapedDQuotes, lgth)
517       
518        return (ObjectStarts, ArrayStarts, StringStarts, NumberStarts, TrueStarts, FalseStarts, NullStarts, StringErrors, StringSpans)
519 
520def demo_validate_json(u8data):
521 
522        global lgth
523        lgth = len(u8data)
524       
525        (ObjectStarts, ArrayStarts, StringStarts, NumberStarts,TrueStarts, FalseStarts, NullStarts, StringErrors, StringSpans) = validate_json(u8data,lgth)
526
527        bitutil.print_aligned_streams([('Input Data', u8data), 
528                              ('ObjectStarts', bitutil.bitstream2string(ObjectStarts, lgth)),
529                              ('ArrayStarts', bitutil.bitstream2string(ArrayStarts, lgth)),
530                              ('StringStarts', bitutil.bitstream2string(StringStarts, lgth)),
531                              ('NumberStarts', bitutil.bitstream2string(NumberStarts, lgth)),
532                              ('TrueStarts', bitutil.bitstream2string(TrueStarts, lgth)),
533                              ('FalseStarts', bitutil.bitstream2string(FalseStarts, lgth)),
534                              ('NullStarts', bitutil.bitstream2string(NullStarts, lgth)),
535                              ('StringErrors', bitutil.bitstream2string(StringErrors, lgth)),
536                              ('StringSpans', bitutil.bitstream2string(StringSpans, lgth))])
537
538        return
539
540if __name__ == "__main__":
541        import doctest
542        doctest.testmod()
543
544        if len(sys.argv) < 2:
545                sys.stderr.write("Usage: python " + filename + " <filename>" "\n")
546                sys.exit(2)
547
548        u8data = bitutil.readfile(sys.argv[1]) 
549#       demo_parse_escape(u8data)
550#       demo_parallel_prefix_parity(u8data)
551#       demo_value_starts(u8data)
552#       demo_validate_number(u8data)
553#       demo_validate_string(u8data)
554#       demo_validate_true_false_null(u8data)
555        demo_validate_json(u8data)
Note: See TracBrowser for help on using the repository browser.