| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package FlashVideo::JSON; | 
| 2 |  |  |  |  |  |  | # Very simple JSON parser, loosely based on | 
| 3 |  |  |  |  |  |  | # http://code.google.com/p/json-sans-eval | 
| 4 |  |  |  |  |  |  | # Public domain. | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 1 |  |  | 1 |  | 22581 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 58 |  | 
| 7 | 1 |  |  | 1 |  | 6 | use base 'Exporter'; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 741 |  | 
| 8 |  |  |  |  |  |  | our @EXPORT = qw(from_json); | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | my $number = qr{(?:-?\b(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\b)}; | 
| 11 |  |  |  |  |  |  | my $oneChar = qr{(?:[^\0-\x08\x0a-\x1f\"\\]|\\(?:["/\\bfnrt]|u[0-9A-Fa-f]{4}))}; | 
| 12 |  |  |  |  |  |  | my $string = qr{(?:"$oneChar*")}; | 
| 13 |  |  |  |  |  |  | my $jsonToken = qr{(?:false|true|null|[\{\}\[\]]|$number|$string)}; | 
| 14 |  |  |  |  |  |  | my $escapeSequence = qr{\\(?:([^u])|u(.{4}))}; | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | my %escapes = ( | 
| 17 |  |  |  |  |  |  | '\\' => '\\', | 
| 18 |  |  |  |  |  |  | '"' => '"', | 
| 19 |  |  |  |  |  |  | '/' => '/', | 
| 20 |  |  |  |  |  |  | 'b' => "\b", | 
| 21 |  |  |  |  |  |  | 'f' => "\f", | 
| 22 |  |  |  |  |  |  | 'n' => "\xA", | 
| 23 |  |  |  |  |  |  | 'r' => "\xD", | 
| 24 |  |  |  |  |  |  | 't' => "\t" | 
| 25 |  |  |  |  |  |  | ); | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | sub from_json { | 
| 28 | 8 |  |  | 8 | 0 | 24 | my($in) = @_; | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 8 |  |  |  |  | 84 | my @tokens = $in =~ /$jsonToken/go; | 
| 31 | 8 | 100 |  |  |  | 23 | my $result = $tokens[0] eq '{' ? {} : []; | 
| 32 |  |  |  |  |  |  | # Handle something other than array/object at toplevel | 
| 33 | 8 | 100 |  |  |  | 25 | shift @tokens if $tokens[0] =~ /^[\[\{]/; | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 8 |  |  |  |  | 8 | my $key; # key to use for next value | 
| 36 | 8 |  |  |  |  | 13 | my @stack = $result; | 
| 37 | 8 |  |  |  |  | 13 | for my $t(@tokens) { | 
| 38 | 27 |  |  |  |  | 36 | my $ft = substr $t, 0, 1; | 
| 39 | 27 |  |  |  |  | 26 | my $cont = $stack[0]; | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 27 | 100 | 100 |  |  | 122 | if($ft eq '"') { | 
|  |  | 100 | 100 |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 42 | 9 |  |  |  |  | 16 | my $s = substr $t, 1, length($t) - 2; | 
| 43 | 9 | 50 |  |  |  | 21 | $s =~ s/$escapeSequence/$1 ? $escapes{$1} : chr hex $2/geo; | 
|  | 5 |  |  |  |  | 24 |  | 
| 44 | 9 | 100 |  |  |  | 14 | if(!defined $key) { | 
| 45 | 7 | 100 |  |  |  | 13 | if(ref $cont eq 'ARRAY') { | 
| 46 | 2 |  |  |  |  | 6 | $cont->[@$cont] = $s; | 
| 47 |  |  |  |  |  |  | } else { | 
| 48 | 5 |  |  |  |  | 5 | $key = $s; | 
| 49 | 5 |  |  |  |  | 9 | next; # need to save $key | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  | } else { | 
| 52 | 2 |  |  |  |  | 6 | $cont->{$key} = $s; | 
| 53 |  |  |  |  |  |  | } | 
| 54 |  |  |  |  |  |  | } elsif($ft eq '[' || $ft eq '{') { | 
| 55 | 2 | 50 |  |  |  | 11 | unshift @stack, | 
|  |  | 100 |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | (ref $cont eq 'ARRAY' ? $cont->[@$cont] : $cont->{$key}) = $ft eq '[' ? [] : {}; | 
| 57 |  |  |  |  |  |  | } elsif($ft eq ']' || $ft eq '}') { | 
| 58 | 5 |  |  |  |  | 7 | shift @stack; | 
| 59 |  |  |  |  |  |  | } else { | 
| 60 | 11 | 100 |  |  |  | 84 | (ref $cont eq 'ARRAY' ? $cont->[@$cont] : $cont->{$key}) = | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | $ft eq 'f' ? 0 # false | 
| 62 |  |  |  |  |  |  | : $ft eq 'n' ? undef # null | 
| 63 |  |  |  |  |  |  | : $ft eq 't' ? 1 # true | 
| 64 |  |  |  |  |  |  | : $t; # sign or digit | 
| 65 |  |  |  |  |  |  | } | 
| 66 | 22 |  |  |  |  | 40 | undef $key; | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 8 |  |  |  |  | 52 | return $result; | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | 1; |