Skip to content
This repository
Browse code

init commit

  • Loading branch information...
commit 6edfb04e0a44e9f23b8b3ff1c92a50137589f4da 0 parents
Alex Sudakov authored September 29, 2011

Showing 60 changed files with 3,575 additions and 0 deletions. Show diff stats Hide diff stats

  1. 31  Makefile
  2. 92  README.md
  3. 24  examples/callback.sql
  4. 23  expected/www_fdw.out
  5. 78  libjson-0.8/Makefile
  6. 72  libjson-0.8/README
  7. 5  libjson-0.8/debian/changelog
  8. 1  libjson-0.8/debian/compat
  9. 22  libjson-0.8/debian/control
  10. 26  libjson-0.8/debian/copyright
  11. 1  libjson-0.8/debian/docs
  12. 2  libjson-0.8/debian/libjson-dev.dirs
  13. 4  libjson-0.8/debian/libjson-dev.install
  14. 1  libjson-0.8/debian/libjson.dirs
  15. 1  libjson-0.8/debian/libjson.install
  16. 57  libjson-0.8/debian/rules
  17. 4  libjson-0.8/debian/watch
  18. 505  libjson-0.8/documentation
  19. 963  libjson-0.8/json.c
  20. 207  libjson-0.8/json.h
  21. 540  libjson-0.8/jsonlint.c
  22. 10  libjson-0.8/libjson.pc.in
  23. 0  libjson-0.8/tests/bad/empty.json
  24. 3  libjson-0.8/tests/bad/esc0.json
  25. 3  libjson-0.8/tests/bad/esc1.json
  26. 3  libjson-0.8/tests/bad/esc2.json
  27. 3  libjson-0.8/tests/bad/esc3.json
  28. 3  libjson-0.8/tests/bad/esc4.json
  29. 3  libjson-0.8/tests/bad/float0.json
  30. 3  libjson-0.8/tests/bad/float1.json
  31. 1  libjson-0.8/tests/bad/object0.json
  32. 3  libjson-0.8/tests/bad/object1.json
  33. 3  libjson-0.8/tests/bad/object2.json
  34. 5  libjson-0.8/tests/bad/object3.json
  35. 2  libjson-0.8/tests/good/1.json
  36. 3  libjson-0.8/tests/good/2.json
  37. 4  libjson-0.8/tests/good/2obj.json
  38. 3  libjson-0.8/tests/good/3.json
  39. 3  libjson-0.8/tests/good/4.json
  40. 5  libjson-0.8/tests/good/5.json
  41. 4  libjson-0.8/tests/good/6.json
  42. 7  libjson-0.8/tests/good/7.json
  43. 13  libjson-0.8/tests/good/c-comment.json
  44. 21  libjson-0.8/tests/good/complex0.json
  45. 3  libjson-0.8/tests/good/emptyobj.json
  46. 3  libjson-0.8/tests/good/esc0.json
  47. 3  libjson-0.8/tests/good/esc1.json
  48. 3  libjson-0.8/tests/good/esc2.json
  49. 3  libjson-0.8/tests/good/esc3.json
  50. 3  libjson-0.8/tests/good/esc4.json
  51. 3  libjson-0.8/tests/good/float0.json
  52. 3  libjson-0.8/tests/good/float1.json
  53. 3  libjson-0.8/tests/good/float2.json
  54. 13  libjson-0.8/tests/good/multiobj.json
  55. 10  libjson-0.8/tests/good/yaml-comment.json
  56. 27  libjson-0.8/tests/runtest
  57. 12  sql/www_fdw.sql
  58. 27  www_fdw--1.0.0.sql
  59. 687  www_fdw.c
  60. 5  www_fdw.control
31  Makefile
... ...
@@ -0,0 +1,31 @@
  1
+# contrib/www_fdw/Makefile
  2
+
  3
+LIBJSON = libjson-0.8
  4
+MODULE_big = www_fdw
  5
+OBJS	= www_fdw.o $(LIBJSON)/json.o
  6
+EXTENSION = www_fdw
  7
+DATA = www_fdw--1.0.0.sql
  8
+
  9
+REGRESS = www_fdw
  10
+SHLIB_LINK = -lcurl
  11
+
  12
+all:all-libjson
  13
+
  14
+all-libjson:
  15
+	$(MAKE) -C $(LIBJSON) all
  16
+
  17
+clean: clean-libjson
  18
+
  19
+clean-libjson:
  20
+	$(MAKE) -C $(LIBJSON) clean
  21
+
  22
+ifdef USE_PGXS
  23
+PG_CONFIG = pg_config
  24
+PGXS := $(shell $(PG_CONFIG) --pgxs)
  25
+include $(PGXS)
  26
+else
  27
+subdir = contrib/www_fdw
  28
+top_builddir = ../..
  29
+include $(top_builddir)/src/Makefile.global
  30
+include $(top_srcdir)/contrib/contrib-global.mk
  31
+endif
92  README.md
Source Rendered
... ...
@@ -0,0 +1,92 @@
  1
+twitter\_fdw
  2
+============
  3
+
  4
+This library contains a single PostgreSQL extension, a Foreign Data
  5
+Wrapper (FDW) handler of PostgreSQL which fetches text messages from
  6
+Twitter over the Internet and returns as a table. 
  7
+
  8
+Installation
  9
+------------
  10
+
  11
+    $ export USE_PGXS=1
  12
+    $ make && make install
  13
+    $ psql -c "CREATE EXTENSION www_fdw" db
  14
+
  15
+The CREATE EXTENSION statement creates not only FDW handlers but also
  16
+Data Wrapper, Foreign Server, User Mapping and twitter table.
  17
+
  18
+Usage
  19
+-----
  20
+
  21
+After installation, simply query from `twitter` table.
  22
+
  23
+    db=# SELECT from_user, created_at, text FROM twitter WHERE q = '#postgresql';
  24
+
  25
+The layout of `twitter` table is as below:
  26
+
  27
+                   Foreign table "public.twitter"
  28
+          Column       |            Type             | Modifiers 
  29
+    -------------------+-----------------------------+-----------
  30
+     id                | bigint                      | 
  31
+     text              | text                        | 
  32
+     from_user         | text                        | 
  33
+     from_user_id      | bigint                      | 
  34
+     to_user           | text                        | 
  35
+     to_user_id        | bigint                      | 
  36
+     iso_language_code | text                        | 
  37
+     source            | text                        | 
  38
+     profile_image_url | text                        | 
  39
+     created_at        | timestamp without time zone | 
  40
+     q                 | text                        | 
  41
+    Server: www_service
  42
+
  43
+The column `q` is a virtual column that is passed to API as a
  44
+query string if the column is used with `=` operator as
  45
+WHERE q = '#sometext'. You can put any text as defined in the API
  46
+parameter `q`. Note the query string is percent-encoded by the module.
  47
+The other columns are mapped to the corresponding property name of
  48
+each tweet item in the API result. For more detail on these values,
  49
+see the API document.
  50
+
  51
+Depencency
  52
+----------
  53
+
  54
+This module depends on
  55
+
  56
+  * [libcurl](http://curl.haxx.se/libcurl/)
  57
+  * [libjson](http://projects.snarc.org/libjson/)
  58
+  * [Twitter API](http://apiwiki.twitter.com/w/page/22554679/Twitter-API-Documentation)
  59
+
  60
+The source of libjson is included this module package and linked as a
  61
+static library, wheares libcurl is assumed installed in the system.
  62
+You may need additional development package, as `libcurl-dev` in yum.
  63
+Consult your system and repository owner for more detail.
  64
+
  65
+Author
  66
+------
  67
+
  68
+Hitoshi Harada <umi.tanuki@gmail.com>
  69
+
  70
+Copyright and License
  71
+---------------------
  72
+
  73
+Copyright (c) Hitoshi Harada
  74
+
  75
+This module is free software; you can redistribute it and/or modify it under
  76
+the [PostgreSQL License](http://www.opensource.org/licenses/postgresql).
  77
+
  78
+Permission to use, copy, modify, and distribute this software and its
  79
+documentation for any purpose, without fee, and without a written agreement is
  80
+hereby granted, provided that the above copyright notice and this paragraph
  81
+and the following two paragraphs appear in all copies.
  82
+
  83
+In no event shall Hitoshi Harada be liable to any party for direct,
  84
+indirect, special, incidental, or consequential damages, including
  85
+lost profits, arising out of the use of this software and its documentation,
  86
+even if Hitoshi Harada has been advised of the possibility of such damage.
  87
+
  88
+Hitoshi Harada specifically disclaims any warranties,
  89
+including, but not limited to, the implied warranties of merchantability and
  90
+fitness for a particular purpose. The software provided hereunder is on an "as
  91
+is" basis, and Hitoshi Harada has no obligations to provide maintenance,
  92
+support, updates, enhancements, or modifications.
24  examples/callback.sql
... ...
@@ -0,0 +1,24 @@
  1
+CREATE OR REPLACE FUNCTION f(e anyelement, idx bigint) RETURNS g AS $$
  2
+DECLARE
  3
+	r	g;
  4
+BEGIN
  5
+	BEGIN
  6
+		IF idx > array_length(e.items, 1) THEN
  7
+			RETURN	NULL;
  8
+		END IF;
  9
+		r.title	:= e.items[idx].title;
  10
+		r.link	:= e.items[idx].link;
  11
+		r.snippet	:= e.items[idx].snippet;
  12
+	EXCEPTION
  13
+		WHEN OTHERS THEN
  14
+			RAISE EXCEPTION 'error occured, sqlstate: %', SQLSTATE;
  15
+	END;
  16
+	RETURN	r;
  17
+END; $$ LANGUAGE PLPGSQL;
  18
+
  19
+/*
  20
+select f( ROW( ARRAY[ ('TITLE','LINK','SNIPPET')::t_item, ('TITLE2','LINK2','SNIPPET2')::t_item ] )::t_answer, 1);
  21
+select f( ROW( ARRAY[ ('TITLE','LINK','SNIPPET')::t_item, ('TITLE2','LINK2','SNIPPET2')::t_item ] )::t_answer, 2);
  22
+select f( ROW( ARRAY[ ('TITLE','LINK','SNIPPET')::t_item, ('TITLE2','LINK2','SNIPPET2')::t_item ] )::t_answer, 3);
  23
+select f( 1, 1);
  24
+*/
23  expected/www_fdw.out
... ...
@@ -0,0 +1,23 @@
  1
+CREATE EXTENSION www_fdw;
  2
+SELECT count(*) FROM twitter;
  3
+ count 
  4
+-------
  5
+     0
  6
+(1 row)
  7
+
  8
+SELECT count(*) FROM twitter WHERE q = '#postgresql';
  9
+ count 
  10
+-------
  11
+    15
  12
+(1 row)
  13
+
  14
+CREATE TEMP TABLE twtest (id int, from_user text);
  15
+INSERT INTO twtest(from_user)
  16
+	SELECT from_user FROM twitter WHERE q = '#postgres' LIMIT 1;
  17
+SELECT true FROM twtest INNER JOIN
  18
+	twitter USING(from_user) WHERE q = '#postgres';
  19
+ bool 
  20
+------
  21
+ t
  22
+(1 row)
  23
+
78  libjson-0.8/Makefile
... ...
@@ -0,0 +1,78 @@
  1
+AR = ar
  2
+CC = gcc
  3
+CFLAGS ?= -Wall -Os -fPIC
  4
+LDFLAGS = -L.
  5
+SHLIB_CFLAGS = -shared
  6
+
  7
+INSTALL_EXEC = install -m 755 -o root -g root
  8
+INSTALL_DATA = install -m 644 -o root -g root
  9
+COPY_PRESERVELINKS = cp -d
  10
+INSTALL_SOLINKS = $(COPY_PRESERVELINKS)
  11
+
  12
+MAJOR = 0
  13
+MINOR = 8
  14
+MICRO = 0
  15
+
  16
+NAME = json
  17
+A_TARGETS = lib$(NAME).a
  18
+BIN_TARGETS = $(NAME)lint
  19
+PC_TARGET = lib$(NAME).pc
  20
+SO_LINKS = lib$(NAME).so lib$(NAME).so.$(MAJOR) lib$(NAME).so.$(MAJOR).$(MINOR)
  21
+SO_FILE = lib$(NAME).so.$(MAJOR).$(MINOR).$(MICRO)
  22
+HEADERS = $(NAME).h
  23
+
  24
+PREFIX ?= /usr
  25
+DESTDIR ?=
  26
+INSTALLDIR ?= $(DESTDIR)$(PREFIX)
  27
+
  28
+TARGETS = $(A_TARGETS) $(SO_FILE) $(SO_LINKS) $(BIN_TARGETS) $(PC_TARGET)
  29
+
  30
+all: $(TARGETS)
  31
+
  32
+lib$(NAME).a: $(NAME).o
  33
+	$(AR) rc $@ $+
  34
+
  35
+lib$(NAME).so: lib$(NAME).so.$(MAJOR)
  36
+	ln -sf $< $@
  37
+
  38
+lib$(NAME).so.$(MAJOR): lib$(NAME).so.$(MAJOR).$(MINOR)
  39
+	ln -sf $< $@
  40
+
  41
+lib$(NAME).so.$(MAJOR).$(MINOR): lib$(NAME).so.$(MAJOR).$(MINOR).$(MICRO)
  42
+	ln -sf $< $@
  43
+
  44
+lib$(NAME).so.$(MAJOR).$(MINOR).$(MICRO): $(NAME).o
  45
+	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,lib$(NAME).so.$(MAJOR).$(MINOR).$(MICRO) $(SHLIB_CFLAGS) -o $@ $^
  46
+
  47
+$(NAME)lint: $(NAME)lint.o $(NAME).o
  48
+	$(CC) $(CFLAGS) -o $@ $+
  49
+
  50
+%.o: %.c %.h
  51
+	$(CC) $(CFLAGS) -c -o $@ $<
  52
+
  53
+.PHONY: lib$(NAME).pc
  54
+lib$(NAME).pc: lib$(NAME).pc.in
  55
+	sed -e 's;@PREFIX@;$(PREFIX);' -e 's;@LIBJSON_VER_MAJOR@;$(MAJOR);' -e 's;@LIBJSON_VER_MINOR@;$(MINOR);' < $< > $@
  56
+
  57
+.PHONY: tests clean install install-bin install-lib
  58
+tests: $(NAME)lint
  59
+	(cd tests; ./runtest)
  60
+
  61
+install-lib: $(SO_TARGETS) $(A_TARGETS) $(PC_TARGET)
  62
+	mkdir -p $(INSTALLDIR)/lib/pkgconfig
  63
+	$(INSTALL_DATA) -t $(INSTALLDIR)/lib/pkgconfig $(PC_TARGET)
  64
+	mkdir -p $(INSTALLDIR)/include
  65
+	$(INSTALL_DATA) -t $(INSTALLDIR)/include $(HEADERS)
  66
+	mkdir -p $(INSTALLDIR)/lib
  67
+	$(INSTALL_EXEC) -t $(INSTALLDIR)/lib $(SO_FILE)
  68
+	$(INSTALL_DATA) -t $(INSTALLDIR)/lib $(A_TARGETS)
  69
+	$(INSTALL_SOLINKS) $(SO_LINKS) $(INSTALLDIR)/lib
  70
+
  71
+install-bin: $(BIN_TARGETS)
  72
+	mkdir -p $(INSTALLDIR)/bin
  73
+	$(INSTALL_EXEC) -t $(INSTALLDIR)/bin $(BIN_TARGETS)
  74
+
  75
+install: install-lib install-bin
  76
+
  77
+clean:
  78
+	rm -f *.o $(TARGETS)
72  libjson-0.8/README
... ...
@@ -0,0 +1,72 @@
  1
+= libjson README =
  2
+
  3
+libjson is a simple library without any dependancies to parse and pretty print
  4
+the json format (RFC4627). The JSON format is a concise and structured data
  5
+format.
  6
+
  7
+libjson parser is an interruptible handcoded state parse. the parser takes
  8
+character or string as input. Since it's interruptible, it's up to the
  9
+user to feed the stream to the parser, which permits complete flexibility
  10
+as to whether the data is coming from a pipe, a network socket, a file on disk,
  11
+a serial line, or crafted by the user.
  12
+
  13
+The parser doesn't create an object tree for you, but each time it comes up
  14
+with an element in this data, it just callback to the user with the type found and
  15
+for some type, the data associated with it. it can be compared to the SAX way of XML,
  16
+hence it's called SAJ (Simple API for JSon).
  17
+
  18
+The parser doesn't convert number to any native C format, but instead callback
  19
+with a string that is a valid JSon number. JSon number can be of any size,
  20
+so that's up to user to decide whetever or not, the number can map to native C type
  21
+int32_t, int64_t, or a complex integer type. As well the user has a choice to
  22
+refuse the integer at the callback stage if the length is not appropriate.
  23
+
  24
+The parser optionally allows YAML and/or C comments to be ignored if the config
  25
+structure is set accordingly, otherwise a JSON_ERROR_COMMENT_NOT_ALLOWED is returned.
  26
+
  27
+the parser API is really simple, totaling only 5 API calls:
  28
+
  29
+* json_parser_init
  30
+* json_parser_char
  31
+* json_parser_string
  32
+* json_parser_is_done
  33
+* json_parser_free
  34
+
  35
+json_parser_init initializes a new parser context from a parser config and
  36
+takes a callback + userdata. This callback function is used everything the
  37
+parser need to communicate a type and value to the client side of the library.
  38
+
  39
+json_parser_char take one character and inject it in the parser. on parsing
  40
+success it will return a 0 value, but on parsing error it returns a parsing
  41
+error that represents the type of the error encounters. see JSON_ERROR_*
  42
+for the full set of return values.
  43
+
  44
+json_parser_string is similar to json_parser_char except that it takes a string
  45
+and a length.  it also returns the number of character processed, which is
  46
+useful when an parser error happened in the stream to pinpoint where.
  47
+
  48
+json_parser_is_done permits to test whetever or not the parser is in a
  49
+terminated state. it involves not beeing into any structure.
  50
+
  51
+json_parser_free is the opposite of init, it just free the allocated structure.
  52
+
  53
+the printer API is simple too:
  54
+
  55
+* json_printer_init
  56
+* json_printer_free
  57
+* json_printer_pretty
  58
+* json_printer_raw
  59
+
  60
+json_printer_init initialise a printing context and takes a callback + userdata
  61
+that will be called for every character that the printer wants to output. the
  62
+caller can have the printer callback redirect to anything it wants.
  63
+
  64
+json_printer_free is the opposite of init
  65
+
  66
+json_printer_raw takes a json type and an optional data and length value
  67
+depending on the type. it's up to the caller to verify that the order of type
  68
+are JSON-compliant, otherwise the generated document won't be able to be parsed
  69
+again.
  70
+
  71
+json_printer_pretty works like json_printer_raw but is targetted for human
  72
+reading by appending newlines and spaces
5  libjson-0.8/debian/changelog
... ...
@@ -0,0 +1,5 @@
  1
+libjson (0.7-1) unstable; urgency=low
  2
+
  3
+  * Initial release.
  4
+
  5
+ -- William Dauchy <wdauchy@gmail.com>  Tue, 16 Mar 2010 15:45:59 +0100
1  libjson-0.8/debian/compat
... ...
@@ -0,0 +1 @@
  1
+7
22  libjson-0.8/debian/control
... ...
@@ -0,0 +1,22 @@
  1
+Source: libjson
  2
+Priority: extra
  3
+Maintainer: William Dauchy <wdauchy@gmail.com>
  4
+Build-Depends: debhelper (>= 7)
  5
+Standards-Version: 3.8.4
  6
+Section: libs
  7
+Homepage: http://projects.snarc.org/libjson/
  8
+
  9
+Package: libjson-dev
  10
+Section: libdevel
  11
+Architecture: any
  12
+Depends: libjson (= ${binary:Version})
  13
+Description: Development files for libjson
  14
+ This package contains the header files and static library needed to
  15
+ compile applications that use confuse.
  16
+
  17
+Package: libjson
  18
+Section: libs
  19
+Architecture: any
  20
+Depends: ${shlibs:Depends}, ${misc:Depends}
  21
+Description: Library to parse and pretty print the json format (RFC4627).
  22
+ The JSON format is a concise and structured data format.
26  libjson-0.8/debian/copyright
... ...
@@ -0,0 +1,26 @@
1  libjson-0.8/debian/docs
... ...
@@ -0,0 +1 @@
  1
+README
2  libjson-0.8/debian/libjson-dev.dirs
... ...
@@ -0,0 +1,2 @@
  1
+usr/lib
  2
+usr/include
4  libjson-0.8/debian/libjson-dev.install
... ...
@@ -0,0 +1,4 @@
  1
+usr/include/*
  2
+usr/lib/lib*.a
  3
+usr/lib/lib*.so
  4
+usr/lib/pkgconfig/*
1  libjson-0.8/debian/libjson.dirs
... ...
@@ -0,0 +1 @@
  1
+usr/lib
1  libjson-0.8/debian/libjson.install
... ...
@@ -0,0 +1 @@
  1
+usr/lib/lib*.so.*
57  libjson-0.8/debian/rules
... ...
@@ -0,0 +1,57 @@
  1
+#!/usr/bin/make -f
  2
+# Uncomment this to turn on verbose mode.
  3
+#export DH_VERBOSE=1
  4
+
  5
+CFLAGS = -Wall -Wno-unused -g -fPIC
  6
+
  7
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
  8
+	CFLAGS += -O0
  9
+else
  10
+	CFLAGS += -O2
  11
+endif
  12
+
  13
+build: build-stamp
  14
+
  15
+build-stamp:
  16
+	dh_testdir
  17
+	$(MAKE)
  18
+	touch build-stamp
  19
+
  20
+clean:
  21
+	dh_testdir
  22
+	dh_testroot
  23
+	dh_prep
  24
+	dh_clean
  25
+	rm -f build-stamp
  26
+	$(MAKE) clean
  27
+
  28
+install: build
  29
+	dh_testdir
  30
+	dh_testroot
  31
+	dh_prep
  32
+	dh_clean
  33
+	dh_installdirs
  34
+	$(MAKE) install DESTDIR=$(CURDIR)/debian/tmp PREFIX=/usr
  35
+	mv libjson.pc $(CURDIR)/debian/tmp/usr/lib/pkgconfig/
  36
+	dh_install --list-missing
  37
+
  38
+binary-indep: build install
  39
+
  40
+binary-arch: build install
  41
+	dh_testdir
  42
+	dh_testroot
  43
+	dh_installchangelogs
  44
+	dh_installdocs
  45
+	dh_link
  46
+	dh_strip
  47
+	dh_compress
  48
+	dh_fixperms
  49
+	dh_makeshlibs -V
  50
+	dh_installdeb
  51
+	dh_shlibdeps
  52
+	dh_gencontrol
  53
+	dh_md5sums
  54
+	dh_builddeb
  55
+
  56
+binary: binary-indep binary-arch
  57
+.PHONY: build clean binary-indep binary-arch binary install
4  libjson-0.8/debian/watch
... ...
@@ -0,0 +1,4 @@
  1
+# Compulsory line, this is a version 3 file
  2
+version=3
  3
+
  4
+http://projects.snarc.org/libjson/download/libjson-(.*)\.tar\.gz
505  libjson-0.8/documentation
... ...
@@ -0,0 +1,505 @@
  1
+= Introduction
  2
+
  3
+libjson is a small C library and small codebase that packs an efficient parser
  4
+and a configurable printer. libjson is covered by the LGPLv2 license, or at
  5
+your option the LGPLv3 license.
  6
+
  7
+Here's the feature of libjson:
  8
+
  9
+== Interruptible parser
  10
+
  11
+Get the JSON data to the parser any way you want; by appending char by char,
  12
+or string chunks, the input reading is completely left to the caller.
  13
+
  14
+== No object model integrated
  15
+
  16
+ easy integration with any model by the means of a simple callback.
  17
+
  18
+== Small codebase
  19
+
  20
+ handcoded parser and efficient factorisation make the code smalls.
  21
+
  22
+== Fast
  23
+
  24
+use efficient code, and small parsing tables to not do any extra work and
  25
+remains as fast and efficient as possible.
  26
+
  27
+== Full JSON support
  28
+
  29
+tested through a small and precise testsuite.
  30
+
  31
+== No native conversion
  32
+
  33
+callback only string of data and leave the actual representation of data to the caller
  34
+
  35
+== Security
  36
+
  37
+* Supports putting limits on nesting level. security against DoS over very deep data.
  38
+* Supports putting limits on data (string/int/float) size. security against DoS over very large data object.
  39
+
  40
+== Comments
  41
+
  42
+Optionally support YAML/python comments and C comments.
  43
+
  44
+== Allocation
  45
+
  46
+Supports projects-specific allocation functions to integrate completely with projects
  47
+
  48
+== Utility program
  49
+
  50
+jsonlint utility provided with the library to verify, or reformat json stream.
  51
+also useful as example on how to use the library.
  52
+
  53
+= Design
  54
+
  55
+== Interruptible
  56
+
  57
+the interruptible parser permits the user to incrementally parse data. each
  58
+time new data is passed to the parser, the parser potentially emits call back
  59
+to the caller to give a found value, and every time update its internal state
  60
+machine. this state machine will returns an error when the data passed doesn't
  61
+end up beeing a JSON compliant stream.
  62
+
  63
+Because of the interruptibility of the parser, the caller is in charge of
  64
+feeding data to the parser, which give the flexibility to the caller to channel
  65
+the data to the parser in its own ways. for example, embedded stream of json in
  66
+another stream, can dynamically and without extra allocation, be passed to the
  67
+parser. this effectively decoupled the parser from the stream of data.
  68
+
  69
+This also reduce the API related to parser's input to only one function,
  70
+instead of specific functions to parse a string in memory, a C FILE handler, a
  71
+unix file descriptor, etc.
  72
+
  73
+== No Object Model
  74
+
  75
+There's no object model embedded in the library. This way the object model is
  76
+left to the caller wants and needs. like a SAX API, the parser callback on
  77
+opening and closing structures, and also for every data values.
  78
+
  79
+The caller is free to represent a json object as a GLIB hashtable, an handmade
  80
+chained list, etc. The same is true for any JSON types. This cut down the usual
  81
+rewritting of the library object tree to the native object tree after parsing
  82
+that takes memory and cpu time.
  83
+
  84
+== Callback without native conversion
  85
+
  86
+Float and int are passed to the caller directly as a string. Since JSON integer
  87
+and float are not limited to a specific size, this is up to the caller to
  88
+specify how to read the string. for example one implementation can choose to
  89
+represent the json int as very big int (GMP), but some other implementation can
  90
+choose 64 bits int and truncate data.
  91
+
  92
+If the callback return a non null value, the parser will return failure, so
  93
+that you can stop the parsing.
  94
+
  95
+== Security aspects
  96
+
  97
+The design of the library is to emphasis security. the event based parser, the
  98
+carefully secure crafted code, and the optional limits in place means that the
  99
+parser can be put on the front line and will behave in front of DoS and huge
  100
+data.
  101
+
  102
+The parser supports maximum size in the data buffer for string/float/int and
  103
+supports a maximum nesting level.
  104
+
  105
+If the data limit is set to 0, the buffer will double when necessary.
  106
+
  107
+If the nestimg limit is set to 0, the stack will double when necessary.
  108
+
  109
+All string data are passed to the caller with an explicit size; NULL bytes can
  110
+be handled properly.
  111
+
  112
+= about the API
  113
+
  114
+The libjson API is very simple.
  115
+
  116
+== function returns
  117
+
  118
+every functions returns a int that is either 0 for success, or a json_error if different from 0.
  119
+
  120
+== Callbacks object
  121
+
  122
+all callback takes an optional void * to be able to pass a pointer to anything to the callback function.
  123
+
  124
+== No assumption
  125
+
  126
+There's no assumption about how a file is supposed to be read, or how we suppose to allocate memory.
  127
+
  128
+== libjson structure
  129
+
  130
+All libjson structure are fully available for the library user so that they can
  131
+also be allocated on the function stack for pratical purpose.
  132
+
  133
+= Parsing API
  134
+ 
  135
+== Parsing Context
  136
+
  137
+The first thing you need to parse a document is a parsing context. Every
  138
+parsing function take a context as a first argument, and this is to keep the
  139
+parsing state machine and the event callback mechanism. It also contains
  140
+optional user defined memory functions and the parser configuration (limits,
  141
+comments allowed).
  142
+
  143
+The following example initializes a new parser context:
  144
+
  145
+* a NULL config which means the default parser config.
  146
+* my_callback a function that will be called each time there's a JSON event.
  147
+* my_callback_data a void * value that will be passed to my_callback every times it's called.
  148
+
  149
+{{{!C
  150
+json_parser parser;
  151
+
  152
+if (json_parser_init(&parser, NULL, my_callback, my_callback_data)) {
  153
+	fprintf(stderr, "something wrong happened during init\n");
  154
+}
  155
+}}}
  156
+
  157
+Remember that's the parser need to allocate some data, so when the parser
  158
+context is not used anymore, it needs to free with the appropriate function:
  159
+
  160
+{{{!C
  161
+json_parser_free(&parser);
  162
+}}}
  163
+
  164
+== Parsing Data
  165
+
  166
+The only thing left is feeding data into the parser. This is done with the
  167
+json_parser_string function which takes a string data and a length, and an
  168
+optional offset pointer. This function is completly incremental, which means
  169
+you don't have to parse all your document at once.
  170
+
  171
+You're in charge of passing the data, from your file, your socket, your pipe,
  172
+your in-memory string to the parsing function.
  173
+
  174
+The following example take a in-memory string and pass it to json_parser_string
  175
+1 characters by 1 characters:
  176
+
  177
+{{{!C
  178
+char my_json_string[] = "{ \"key\": 123 }";
  179
+
  180
+for (i = 0; i < strlen(my_json_string); i += 1)  {
  181
+	ret = json_parser_string(&parser, my_json_string + i, 1, NULL);
  182
+	if (ret) {
  183
+		/* error happened : print a message or something */
  184
+		break;
  185
+	}
  186
+}}}
  187
+
  188
+or 4 characters by 4 characters:
  189
+
  190
+{{{!C
  191
+char my_json_string[] = "{ \"key\": 123 }";
  192
+
  193
+for (i = 0; i < strlen(my_json_string); i += 4)  {
  194
+	ret = json_parser_string(&parser, my_json_string + i, 4, NULL);
  195
+	if (ret) {
  196
+		/* error happened : print a message or something */
  197
+		break;
  198
+	}
  199
+}}}
  200
+
  201
+or from a file reading 1024-bytes blocks at the same time:
  202
+
  203
+{{{!
  204
+int fd, len, ret;
  205
+char block[1024];
  206
+
  207
+fd = open(file, ...);
  208
+while ((len = read(fd, block, 1024)) > 0) {
  209
+	ret = json_parser_string(&parser, block, len, NULL);
  210
+	if (ret) {
  211
+		/* error happened : print a message or something */
  212
+		break;
  213
+	}
  214
+}
  215
+}}}
  216
+
  217
+== Parsing events
  218
+
  219
+Each time the function json_parser_string function is called with data, the
  220
+callback registered at context init time might be called.
  221
+
  222
+There's a callback each time the parser has processed a JSON atom.
  223
+
  224
+a JSON atom can be:
  225
+
  226
+* JSON_OBJECT_BEGIN : opening a new object
  227
+* JSON_OBJECT_END : current object is closing
  228
+* JSON_ARRAY_BEGIN : opening a new array
  229
+* JSON_ARRAY_END : current array is closing
  230
+* JSON_INT : a JSON int has been parsed
  231
+* JSON_FLOAT : a JSON float has been parsed
  232
+* JSON_STRING : a JSON string has been parsed
  233
+* JSON_KEY : a JSON key has been parsed
  234
+* JSON_TRUE : a JSON true constant has been parsed
  235
+* JSON_FALSE : a JSON false constant has been parsed
  236
+* JSON_NULL : a JSON null constant has been parsed
  237
+
  238
+A callback prototype looks like the following:
  239
+
  240
+* userdata: is the callback object registered at context init time.
  241
+* type: is the type of the atom parsed.
  242
+* data: is a optional string that contained the data associated with this atom.
  243
+* length: is the length in byte of the data associated with the atom.
  244
+
  245
+{{{!C
  246
+int my_callback(void *userdata, int type, const char *data, uint32_t length)
  247
+}}}
  248
+
  249
+the following example is a full callback function that just print the atom received.
  250
+as a callback object it can support an optional FILE * to print to, otherwise it will
  251
+use stdout.
  252
+
  253
+{{{!C
  254
+int my_callback(void *userdata, int type, const char *data, uint32_t length)
  255
+{
  256
+	FILE *output = (userdata) ? userdata : stdout;
  257
+	switch (type) {
  258
+	case JSON_OBJECT_BEGIN:
  259
+	case JSON_ARRAY_BEGIN:
  260
+		fprintf(output, "entering %s\n", (type == JSON_ARRAY_BEGIN) ? "array" : "object");
  261
+		break;
  262
+	case JSON_OBJECT_END:
  263
+	case JSON_ARRAY_END:
  264
+		fprintf(output, "leaving %s\n", (type == JSON_ARRAY_END) ? "array" : "object");
  265
+		break;
  266
+	case JSON_KEY:
  267
+	case JSON_STRING:
  268
+	case JSON_INT:
  269
+	case JSON_FLOAT:
  270
+		fprintf(output, "value %*s\n", length, data);
  271
+		break;
  272
+	case JSON_NULL:
  273
+		fprintf(output, "constant null\n"); break;
  274
+	case JSON_TRUE:
  275
+		fprintf(output, "constant true\n"); break;
  276
+	case JSON_FALSE:
  277
+		fprintf(output, "constant false\n"); break;
  278
+	}
  279
+}
  280
+}}}
  281
+
  282
+== Parser configuration
  283
+
  284
+Parser configuration can be set when initializing the parsing context. this is done by
  285
+passing a non-NULL pointer to a valid json_config.
  286
+
  287
+The configuration structure support 7 differents variables, which can be group
  288
+in 3 categories:
  289
+
  290
+* user defined memory functions.
  291
+* security.
  292
+* optional extensions.
  293
+
  294
+=== User defined memory function
  295
+
  296
+The library user can choose to redefine its own allocation functions (realloc
  297
+and calloc), in this case the parser will allocate using those functions. this
  298
+is controlled by user_calloc and user_realloc.
  299
+
  300
+=== Security
  301
+
  302
+there's 2 security settings available: max_nesting and max_data.
  303
+
  304
+max_data control the size of data allowed, which control the maximum size of
  305
+int, string, float, and keys in bytes. this is directly connected to the
  306
+size of the data buffer. if set to 0, the buffer will try to grow each time
  307
+it's necessary.
  308
+
  309
+max_nesting controls the number of nested structures allowed by the parser.
  310
+each new nesting increases the parser memory use by 1 byte (for 4096 nested
  311
+structures, you need 4K of memory).
  312
+
  313
+For security purpose, if the parser is directly connected to a network stream,
  314
+setting those variables, is strongly recommended.
  315
+
  316
+=== Comments
  317
+
  318
+You can enable C comments and enable YAML comments arbitrarly from each other.
  319
+
  320
+allow_c_comment will enable C comment: starting at /*, and finishing at */
  321
+
  322
+allow_yaml_comment will enable YAML/python comment: starting at # and finishing
  323
+at the end of line.
  324
+
  325
+comments cannot be nested.
  326
+
  327
+{{{
  328
+{
  329
+	# this is a YAML comment
  330
+	"key": /* this is a C comment */ 123,
  331
+}
  332
+}}}
  333
+
  334
+= Printing API
  335
+
  336
+== Printing context
  337
+
  338
+first, the printing context is an object that is passed to all printing
  339
+functions. The main part of the printing context is the printing callback.
  340
+There's also some state about indentation level and pretty printing state.
  341
+
  342
+The following example initializes a new printing context:
  343
+
  344
+* a NULL config which means the default parser config.
  345
+* my_callback a function that will be called each time there's a JSON event.
  346
+* my_callback_data a void * value that will be passed to my_callback every times it's called.
  347
+
  348
+{{{!C
  349
+json_printer print;
  350
+
  351
+if (json_print_init(&print, my_callback, my_callback_data)) {
  352
+	fprintf(stderr, "something wrong happened during init\n");
  353
+}
  354
+}}}
  355
+
  356
+The printing context need to free after use using the following:
  357
+
  358
+{{{!C
  359
+json_print_free(&print);
  360
+}}}
  361
+
  362
+== Printing JSON
  363
+
  364
+You can choose between pretty printing and raw printing.
  365
+
  366
+raw printing is usually associated for transfering or storing JSON data: it's
  367
+terse for common human usage. the function json_print_raw is associated with
  368
+raw printing
  369
+
  370
+pretty printing is usually targeted for human processing and contains spaces
  371
+and line return. the function json_print_pretty is associated with pretty
  372
+printing
  373
+
  374
+Both functions can be interchanged as they have the same prototype.
  375
+
  376
+the following example print an object with one key "a" with a value of 2505:
  377
+
  378
+{{{!C
  379
+json_print_pretty(&print, JSON_OBJECT_BEGIN, NULL, 0);
  380
+json_print_pretty(&print, JSON_KEY, "a", 1);
  381
+json_print_pretty(&print, JSON_INT, "2505", 4);
  382
+json_print_pretty(&print, JSON_OBJECT_END, NULL, 0);
  383
+}}}
  384
+
  385
+== Printing data
  386
+
  387
+The printing API only transform a JSON atom into the equivalent string; the
  388
+callback is called one or multiples time at each atom, so that the user
  389
+can choose what to do with the marshalled data.
  390
+
  391
+The API is not in charged of allocating a in-memory string or store the
  392
+marshalled data in a file, however doing anything similar is very easy.
  393
+
  394
+The following example printing callback would write the previous structure to
  395
+disk. The file descriptor is passed through the callback object as void *, and
  396
+need to be valid.
  397
+
  398
+{{{!C
  399
+int my_printer_callback(void *userdata, const char *s, uint32_t length)
  400
+{
  401
+	int fd = (int) userdata;
  402
+
  403
+	write(fd, s, lenght);
  404
+	return 0;
  405
+}
  406
+}}}
  407
+
  408
+== Printing Multiple JSON atoms
  409
+
  410
+For conveniance, there's a json_print_args API function that takes multiples JSON atoms
  411
+and repeatly call the associated printing function (raw or pretty). the
  412
+function parameters need to be terminated by a -1 atom to indicate the end of arguments.
  413
+
  414
+Here's an example on how to print the same object as previous example but with one call:
  415
+
  416
+{{{!C
  417
+json_print_args(&print, json_print_pretty,
  418
+                JSON_OBJECT_BEGIN,
  419
+                    JSON_KEY, "a", 1,
  420
+                    JSON_INT, "2505", 4,
  421
+                JSON_OBJECT_END,
  422
+                -1);
  423
+}}}
  424
+
  425
+= DOM parsing helper
  426
+
  427
+For convenience, there's some helpers function that permits constructing JSON DOM tree.
  428
+they are built on top of the event based parsing API described earlier.
  429
+
  430
+== DOM parsing context
  431
+
  432
+a DOM parsing context hold the state of the DOM building. it also hold
  433
+3 differents callbacks to create the JSON values in the tree.
  434
+
  435
+the first callback, create_structure, is called when a new object or array
  436
+is suppose to be created. the callback can choose the representation of the data, but
  437
+need to returns a single void * to represent this new structure.
  438
+
  439
+the second callback, create_data, is called for each value that is not
  440
+an object or an array. it need returning a void * to represent this value.
  441
+
  442
+the last callback, append, is called each time we need to append a value to an
  443
+existing structure (array/object). if called with a non-NULL key, then the
  444
+first argument of the function represent an object, otherwise an array.
  445
+
  446
+the following example hook into a hypothetical framework with array and object
  447
+special method:
  448
+
  449
+{{{!C
  450
+void *tree_create_structure(int nesting, int is_object)
  451
+{
  452
+	if (is_object)
  453
+		return new_object();
  454
+	else
  455
+		return new_array();
  456
+}
  457
+
  458
+void *tree_create_data(int type, const char *data, uint32_t length)
  459
+{
  460
+	switch (type) {
  461
+	case JSON_STRING:
  462
+	case JSON_INT:
  463
+	case JSON_FLOAT:
  464
+		return new_json_value(type, data, length);
  465
+	case JSON_NULL:
  466
+	case JSON_TRUE:
  467
+	case JSON_FALSE:
  468
+		return new_json_const(type);
  469
+	}
  470
+}
  471
+
  472
+int tree_append(void *structure, char *key, uint32_t key_length, void *obj)
  473
+{
  474
+	if (key != NULL) {
  475
+		my_object *object = structure;
  476
+		append_object(object, key, key_length, obj);
  477
+	} else {
  478
+		my_array *array = structure;
  479
+		append_array(array, obj);
  480
+	}
  481
+}
  482
+
  483
+}}}
  484
+
  485
+== Hooking into the event parser
  486
+
  487
+the following example hooks the DOM helper parser into the event parser:
  488
+
  489
+{{{!C
  490
+json_parser_dom helper;
  491
+json_parser parser;
  492
+
  493
+json_parser_dom_init(&helper, create_structure, create_data, append);
  494
+json_parser_init(&parser, json_parser_dom_callback, &helper);
  495
+}}}
  496
+
  497
+= JSONlint utility
  498
+
  499
+JSONlint is a small utility using libjson. it's able to verify and reformat JSON file.
  500
+
  501
+the following will reformat input.json file and create a file output.json:
  502
+
  503
+{{{
  504
+jsonlint --format input.json -o output.json
  505
+}}}
963  libjson-0.8/json.c
... ...
@@ -0,0 +1,963 @@
  1
+/*
  2
+ * Copyright (C) 2009 Vincent Hanquez <vincent@snarc.org>
  3
+ *
  4
+ * This program is free software; you can redistribute it and/or modify
  5
+ * it under the terms of the GNU Lesser General Public License as published
  6
+ * by the Free Software Foundation; version 2.1 or version 3.0 only.
  7
+ *
  8
+ * This program is distributed in the hope that it will be useful,
  9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11
+ * GNU General Public License for more details.
  12
+ */
  13
+
  14
+/*
  15
+ * the class, states and state transition tables has been inspired by the JSON_parser.c
  16
+ * available at http://json.org, but are quite different on the way that the
  17
+ * parser handles its parse buffer and contains significant differences that affect
  18
+ * the JSON compliance.
  19
+ */
  20
+
  21
+#include <stdlib.h>
  22
+#include <string.h>
  23
+#include <stdarg.h>
  24
+#include "json.h"
  25
+
  26
+#ifdef TRACING_ENABLE
  27
+#include <stdio.h>
  28
+#define TRACING(fmt, ...)	fprintf(stderr, "tracing: " fmt, ##__VA_ARGS__)
  29
+#else
  30
+#define TRACING(fmt, ...)	((void) 0)
  31
+#endif
  32
+
  33
+enum classes {
  34
+	C_SPACE, /* space */
  35
+	C_NL,    /* newline */
  36
+	C_WHITE, /* tab, CR */
  37
+	C_LCURB, C_RCURB, /* object opening/closing */
  38
+	C_LSQRB, C_RSQRB, /* array opening/closing */
  39
+	/* syntax symbols */
  40
+	C_COLON,
  41
+	C_COMMA,
  42
+	C_QUOTE, /* " */
  43
+	C_BACKS, /* \ */
  44
+	C_SLASH, /* / */
  45
+	C_PLUS,
  46
+	C_MINUS,
  47
+	C_DOT,
  48
+	C_ZERO, C_DIGIT, /* digits */
  49
+	C_a, C_b, C_c, C_d, C_e, C_f, C_l, C_n, C_r, C_s, C_t, C_u, /* nocaps letters */
  50
+	C_ABCDF, C_E, /* caps letters */
  51
+	C_OTHER, /* all other */
  52
+	C_STAR, /* star in C style comment */
  53
+	C_HASH, /* # for YAML comment */
  54
+	C_ERROR = 0xfe,
  55
+};
  56
+
  57
+/* map from character < 128 to classes. from 128 to 256 all C_OTHER */
  58
+static uint8_t character_class[128] = {
  59
+	C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR,
  60
+	C_ERROR, C_WHITE, C_NL,    C_ERROR, C_ERROR, C_WHITE, C_ERROR, C_ERROR,
  61
+	C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR,
  62
+	C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR, C_ERROR,
  63
+
  64
+	C_SPACE, C_OTHER, C_QUOTE, C_HASH,  C_OTHER, C_OTHER, C_OTHER, C_OTHER,
  65
+	C_OTHER, C_OTHER, C_STAR,  C_PLUS,  C_COMMA, C_MINUS, C_DOT,   C_SLASH,
  66
+	C_ZERO,  C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT, C_DIGIT,
  67
+	C_DIGIT, C_DIGIT, C_COLON, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
  68
+
  69
+	C_OTHER, C_ABCDF, C_ABCDF, C_ABCDF, C_ABCDF, C_E,     C_ABCDF, C_OTHER,
  70
+	C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
  71
+	C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_OTHER,
  72
+	C_OTHER, C_OTHER, C_OTHER, C_LSQRB, C_BACKS, C_RSQRB, C_OTHER, C_OTHER,
  73
+
  74
+	C_OTHER, C_a,     C_b,     C_c,     C_d,     C_e,     C_f,     C_OTHER,
  75
+	C_OTHER, C_OTHER, C_OTHER, C_OTHER, C_l,     C_OTHER, C_n,     C_OTHER,
  76
+	C_OTHER, C_OTHER, C_r,     C_s,     C_t,     C_u,     C_OTHER, C_OTHER,
  77
+	C_OTHER, C_OTHER, C_OTHER, C_LCURB, C_OTHER, C_RCURB, C_OTHER, C_OTHER
  78
+};
  79
+
  80
+/* only the first 36 ascii characters need an escape */
  81
+static char *character_escape[36] = {
  82
+	"\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", /*  0-7  */
  83
+	"\\b"    ,     "\\t",     "\\n", "\\u000b",     "\\f",     "\\r", "\\u000e", "\\u000f", /*  8-f  */
  84
+	"\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", /* 10-17 */
  85
+	"\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", /* 18-1f */
  86
+	" "      , "!"      , "\\\""   , "#",
  87
+};
  88
+
  89
+/* define all states and actions that will be taken on each transition.
  90
+ *
  91
+ * states are defined first because of the fact they are use as index in the
  92
+ * transitions table. they usually contains either a number or a prefix _ 
  93
+ * for simple state like string, object, value ...
  94
+ *
  95
+ * actions are defined starting from 0x80. state error is defined as 0xff
  96
+ */
  97
+
  98
+enum states {
  99
+	STATE_GO, /* start  */
  100
+	STATE_OK, /* ok     */
  101
+	STATE__O, /* object */
  102
+	STATE__K, /* key    */
  103
+	STATE_CO, /* colon  */
  104
+	STATE__V, /* value  */
  105
+	STATE__A, /* array  */
  106
+	STATE__S, /* string */
  107
+	STATE_E0, /* escape */
  108
+	STATE_U1, STATE_U2, STATE_U3, STATE_U4, /* unicode states */
  109
+	STATE_M0, STATE_Z0, STATE_I0, /* number states */
  110
+	STATE_R1, STATE_R2, /* real states (after-dot digits) */
  111
+	STATE_X1, STATE_X2, STATE_X3, /* exponant states */
  112
+	STATE_T1, STATE_T2, STATE_T3, /* true constant states */
  113
+	STATE_F1, STATE_F2, STATE_F3, STATE_F4, /* false constant states */
  114
+	STATE_N1, STATE_N2, STATE_N3, /* null constant states */
  115
+	STATE_C1, STATE_C2, STATE_C3, /* C-comment states */
  116
+	STATE_Y1, /* YAML-comment state */
  117
+	STATE_D1, STATE_D2, /* multi unicode states */
  118
+};
  119
+
  120
+/* the following are actions that need to be taken */
  121
+enum actions {
  122
+	STATE_KS = 0x80, /* key separator */
  123
+	STATE_SP, /* comma separator */
  124
+	STATE_AB, /* array begin */
  125
+	STATE_AE, /* array ending */
  126
+	STATE_OB, /* object begin */
  127
+	STATE_OE, /* object end */
  128
+	STATE_CB, /* C-comment begin */
  129
+	STATE_YB, /* YAML-comment begin */
  130
+	STATE_CE, /* YAML/C comment end */
  131
+	STATE_FA, /* false */
  132
+	STATE_TR, /* true */
  133
+	STATE_NU, /* null */
  134
+	STATE_DE, /* double detected by exponent */
  135
+	STATE_DF, /* double detected by . */
  136
+	STATE_SE, /* string end */
  137
+	STATE_MX, /* integer detected by minus */
  138
+	STATE_ZX, /* integer detected by zero */
  139
+	STATE_IX, /* integer detected by 1-9 */
  140
+	STATE_UC, /* Unicode character read */
  141
+};
  142
+
  143
+/* error state */
  144
+#define STATE___ 	0xff
  145
+
  146
+#define NR_STATES 	(STATE_D2 + 1)
  147
+#define NR_CLASSES	(C_HASH + 1)
  148
+
  149
+#define IS_STATE_ACTION(s) ((s) & 0x80)
  150
+#define S(x) STATE_##x
  151
+#define PT_(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,a1,b1,c1,d1,e1,f1,g1,h1)	\
  152
+	{ S(a),S(b),S(c),S(d),S(e),S(f),S(g),S(h),S(i),S(j),S(k),S(l),S(m),S(n),		\
  153
+	  S(o),S(p),S(q),S(r),S(s),S(t),S(u),S(v),S(w),S(x),S(y),S(z),S(a1),S(b1),		\
  154
+	  S(c1),S(d1),S(e1),S(f1),S(g1),S(h1) }
  155
+
  156
+/* map from the (previous state+new character class) to the next parser transition */
  157
+static const uint8_t state_transition_table[NR_STATES][NR_CLASSES] = {
  158
+/*             white                                                                            ABCDF  other    */
  159
+/*         sp nl |  {  }  [  ]  :  ,  "  \  /  +  -  .  0  19 a  b  c  d  e  f  l  n  r  s  t  u  |  E  |  *  # */
  160
+/*GO*/ PT_(GO,GO,GO,OB,__,AB,__,__,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,YB),
  161
+/*OK*/ PT_(OK,OK,OK,__,OE,__,AE,__,SP,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,YB),
  162
+/*_O*/ PT_(_O,_O,_O,__,OE,__,__,__,__,_S,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,YB),
  163
+/*_K*/ PT_(_K,_K,_K,__,__,__,__,__,__,_S,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,YB),
  164
+/*CO*/ PT_(CO,CO,CO,__,__,__,__,KS,__,__,__,CB,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,YB),
  165
+/*_V*/ PT_(_V,_V,_V,OB,__,AB,__,__,__,_S,__,CB,__,MX,__,ZX,IX,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__,__,YB),
  166
+/*_A*/ PT_(_A,_A,_A,OB,__,AB,AE,__,__,_S,__,CB,__,MX,__,ZX,IX,__,__,__,__,__,F1,__,N1,__,__,T1,__,__,__,__,__,YB),
  167
+/****************************************************************************************************************/
  168
+/*_S*/ PT_(_S,__,__,_S,_S,_S,_S,_S,_S,SE,E0,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S,_S),
  169
+/*E0*/ PT_(__,__,__,__,__,__,__,__,__,_S,_S,_S,__,__,__,__,__,__,_S,__,__,__,_S,__,_S,_S,__,_S,U1,__,__,__,__,__),
  170
+/*U1*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U2,U2,U2,U2,U2,U2,U2,U2,__,__,__,__,__,__,U2,U2,__,__,__),
  171
+/*U2*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U3,U3,U3,U3,U3,U3,U3,U3,__,__,__,__,__,__,U3,U3,__,__,__),
  172
+/*U3*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,U4,U4,U4,U4,U4,U4,U4,U4,__,__,__,__,__,__,U4,U4,__,__,__),
  173
+/*U4*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,UC,UC,UC,UC,UC,UC,UC,UC,__,__,__,__,__,__,UC,UC,__,__,__),
  174
+/****************************************************************************************************************/
  175
+/*M0*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,Z0,I0,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__),
  176
+/*Z0*/ PT_(OK,OK,OK,__,OE,__,AE,__,SP,__,__,CB,__,__,DF,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,YB),
  177
+/*I0*/ PT_(OK,OK,OK,__,OE,__,AE,__,SP,__,__,CB,__,__,DF,I0,I0,__,__,__,__,DE,__,__,__,__,__,__,__,__,DE,__,__,YB),
  178
+/*R1*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,R2,R2,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__),
  179
+/*R2*/ PT_(OK,OK,OK,__,OE,__,AE,__,SP,__,__,CB,__,__,__,R2,R2,__,__,__,__,X1,__,__,__,__,__,__,__,__,X1,__,__,YB),
  180
+/*X1*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,X2,X2,__,X3,X3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__),
  181
+/*X2*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,X3,X3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__),
  182
+/*X3*/ PT_(OK,OK,OK,__,OE,__,AE,__,SP,__,__,__,__,__,__,X3,X3,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__),
  183
+/****************************************************************************************************************/
  184
+/*T1*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T2,__,__,__,__,__,__,__,__),
  185
+/*T2*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,T3,__,__,__,__,__),
  186
+/*T3*/ PT_(__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,TR,__,__,__,__,__,__,__,__,__,__,__,__),