factor/basis/json/reader/reader.factor

102 lines
2.9 KiB
Factor
Raw Normal View History

! Copyright (C) 2008 Peter Burns, 2009 Philipp Winkler
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2013-03-14 21:53:13 -04:00
USING: accessors arrays assocs combinators fry hashtables io
io.streams.string json kernel kernel.private make math
math.parser namespaces prettyprint sequences sequences.private
strings vectors ;
2007-09-20 18:09:08 -04:00
IN: json.reader
<PRIVATE
2013-03-14 21:53:13 -04:00
: value ( char stream -- num char )
[ 1string ] [ " \t\r\n,:}]" swap stream-read-until ] bi*
[ append string>number ] dip ;
DEFER: j-string%
2013-03-14 21:53:13 -04:00
: j-escape% ( stream -- )
dup stream-read1 {
{ CHAR: b [ 8 ] }
{ CHAR: f [ 12 ] }
{ CHAR: n [ CHAR: \n ] }
{ CHAR: r [ CHAR: \r ] }
{ CHAR: t [ CHAR: \t ] }
2013-03-14 21:53:13 -04:00
{ CHAR: u [ 4 over stream-read hex> ] }
[ ]
2013-03-14 21:53:13 -04:00
} case [ , j-string% ] [ drop ] if* ;
2013-03-14 21:53:13 -04:00
: j-string% ( stream -- )
"\\\"" over stream-read-until [ % ] dip
CHAR: \" = [ drop ] [ j-escape% ] if ;
2013-03-14 21:53:13 -04:00
: j-string ( stream -- str )
"\\\"" over stream-read-until CHAR: \" =
[ nip ] [ [ % j-escape% ] "" make ] if ;
2013-03-14 21:53:13 -04:00
: second-last-unsafe ( seq -- second-last )
[ length 2 - ] [ nth-unsafe ] bi ; inline
: pop-unsafe ( seq -- elt )
[ length 1 - ] keep [ nth-unsafe ] [ shorten ] 2bi ; inline
ERROR: json-error ;
2007-09-20 18:09:08 -04:00
: check-length ( seq n -- seq )
2013-03-14 21:53:13 -04:00
[ dup length ] [ >= ] bi* [ json-error ] unless
{ vector } declare ; inline
2007-09-20 18:09:08 -04:00
: v-over-push ( vec -- vec' )
2013-03-14 21:53:13 -04:00
2 check-length dup [ pop-unsafe ] [ last-unsafe ] bi
push ;
2007-09-20 18:09:08 -04:00
: v-pick-push ( vec -- vec' )
2013-03-14 21:53:13 -04:00
3 check-length dup [ pop-unsafe ] [ second-last-unsafe ] bi
push ;
: (close) ( accum -- accum' )
2013-03-14 21:53:13 -04:00
{ vector } declare
dup last V{ } = not [ v-over-push ] when ;
2007-09-20 18:09:08 -04:00
2009-06-06 23:49:44 -04:00
: (close-array) ( accum -- accum' )
2013-03-14 21:53:13 -04:00
{ vector } declare
2011-10-15 22:19:44 -04:00
(close) dup pop >array suffix! ;
2009-06-06 23:49:44 -04:00
: (close-hash) ( accum -- accum' )
2013-03-14 21:53:13 -04:00
{ vector } declare
(close) dup dup [ pop ] bi@ 2dup min-length <hashtable>
[ [ set-at ] curry 2each ] keep suffix! ;
2013-03-14 21:53:13 -04:00
: scan ( stream accum char -- stream accum )
! 2dup 1string swap . . ! Great for debug...
{
2013-03-14 21:53:13 -04:00
{ CHAR: \" [ over j-string suffix! ] }
2011-10-15 22:19:44 -04:00
{ CHAR: [ [ V{ } clone suffix! ] }
{ CHAR: , [ v-over-push ] }
{ CHAR: ] [ (close-array) ] }
2011-10-15 22:19:44 -04:00
{ CHAR: { [ 2 [ V{ } clone suffix! ] times ] }
{ CHAR: : [ v-pick-push ] }
{ CHAR: } [ (close-hash) ] }
{ CHAR: \s [ ] }
{ CHAR: \t [ ] }
{ CHAR: \r [ ] }
{ CHAR: \n [ ] }
2013-03-14 21:53:13 -04:00
{ CHAR: t [ 3 pick stream-read drop t suffix! ] }
{ CHAR: f [ 4 pick stream-read drop f suffix! ] }
{ CHAR: n [ 3 pick stream-read drop json-null suffix! ] }
[ pick value [ suffix! ] dip [ scan ] when* ]
} case ;
2008-11-15 04:09:57 -05:00
2013-03-14 21:53:13 -04:00
: stream-json-read ( stream -- objects )
V{ } clone over '[ _ stream-read1 dup ]
[ scan ] while drop nip ;
2008-11-15 04:09:57 -05:00
PRIVATE>
: read-jsons ( -- objects )
2013-03-14 21:53:13 -04:00
input-stream get stream-json-read ;
: json> ( string -- object )
[ read-jsons first ] with-string-reader ;