├── .Rinstignore
├── inst
├── sampleData
│ ├── int.json
│ ├── intScalar.json
│ ├── array.json
│ ├── array2.json
│ ├── obj.json
│ ├── nestedArray.json
│ ├── array3.json
│ ├── obj2.json
│ ├── nestedObj.json
│ ├── obj3.json
│ ├── embedded.json
│ ├── obj1.json
│ ├── menu.json
│ ├── glossay.json
│ ├── widget.json
│ ├── keys.json
│ ├── menu1.json
│ └── web.json
└── doc
│ ├── overview.pdf
│ ├── timings.docx
│ ├── toJSONTimes.rda
│ ├── fromJSONTimes.rda
│ ├── overview.bib
│ ├── GNUmakefile
│ ├── biblio.xml
│ ├── overview.bbl
│ ├── performance.R
│ ├── missingValues.Rdb
│ └── missingValues.html
├── jsonText.rda
├── tests
├── newsUTF8.rda
├── exp.R
├── con2.R
├── s4.R
├── scalarCollapse.R
├── encoding.R
├── nested.json
├── flat.json
├── empty.R
├── prealloc.R
├── con1.R
├── serialize.R
├── keys.R
├── utf8.R
├── array.R
├── bigInt.R
├── charNULL.R
├── toJSON.R
├── simple.R
├── bigFile.R
├── dataframe.R
├── simplify.R
├── containers.R
├── stringFun.R
└── performance.R
├── configure.win
├── utfTest
├── GNUmakefile
├── raw.R
├── json.c
├── news.txt
├── news1.txt
└── news2.txt
├── LICENSE
├── src
├── libjson
│ ├── README
│ ├── copy
│ ├── Source
│ │ ├── JSONAllocator.cpp
│ │ ├── JSONSingleton.h
│ │ ├── JSONDefs
│ │ │ ├── Unknown_C.h
│ │ │ ├── Visual_C.h
│ │ │ ├── Strings_Defs.h
│ │ │ └── GNU_C.h
│ │ ├── JSONPreparse.h
│ │ ├── JSON_Base64.h
│ │ ├── JSONDebug.cpp
│ │ ├── JSONMemoryPool.h
│ │ ├── JSONValidator.h
│ │ ├── JSONDebug.h
│ │ ├── JSONAllocator.h
│ │ ├── JSONStream.h
│ │ ├── JSONWorker.h
│ │ ├── JSONStats.h
│ │ ├── JSONGlobals.h
│ │ ├── JSONChildren.cpp
│ │ ├── JSONStream.cpp
│ │ ├── JSONDefs.h
│ │ ├── JSONMemory.cpp
│ │ ├── JSONMemory.h
│ │ └── JSONNode_Mutex.cpp
│ ├── bdr
│ └── License.txt
├── Makevars.win
├── Makevars.in
├── Rlibjson.h
├── JSON_parser.h
├── ConvertUTF.h
└── rparser.c
├── README.libjson
├── Web
├── GNUmakefile
└── index.html.in
├── fail.R
├── cleanup.in
├── libjsonFixes
├── cp_libjson
├── leak.R
├── dataframe.R
├── testStream.R
├── GNUmakefile
├── NAMESPACE
├── .Rbuildignore
├── R
├── stream.R
├── isValid.R
├── simpleHandler.R
└── asVars.R
├── cleanup
├── purdy.R
├── libjsonNotes
├── tests.R
├── experiments
└── stream.R
├── Todo.xml
├── man
├── JSON_T_NULL.Rd
├── basicJSONHandler.Rd
├── isValidJSON.Rd
├── asJSVars.Rd
├── readJSONStream.Rd
└── toJSON.Rd
├── README.md
├── DESCRIPTION
├── streaming.R
├── configure.in
├── foo.html
└── Changes
/.Rinstignore:
--------------------------------------------------------------------------------
1 | overview.tex
2 |
--------------------------------------------------------------------------------
/inst/sampleData/int.json:
--------------------------------------------------------------------------------
1 | [1, 2, 3, 4]
--------------------------------------------------------------------------------
/inst/sampleData/intScalar.json:
--------------------------------------------------------------------------------
1 | 1
2 |
--------------------------------------------------------------------------------
/inst/sampleData/array.json:
--------------------------------------------------------------------------------
1 | [ 1, 2, 3, 4]
2 |
--------------------------------------------------------------------------------
/inst/sampleData/array2.json:
--------------------------------------------------------------------------------
1 | [ [1,2,3,4],
2 | [4, 5, 6]
3 | ]
--------------------------------------------------------------------------------
/inst/sampleData/obj.json:
--------------------------------------------------------------------------------
1 | {"a1" : "x",
2 | "a2" : "yz"
3 | }
--------------------------------------------------------------------------------
/jsonText.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duncantl/RJSONIO/HEAD/jsonText.rda
--------------------------------------------------------------------------------
/inst/sampleData/nestedArray.json:
--------------------------------------------------------------------------------
1 | [
2 | [1, 2],
3 | [3, 4]
4 | , [5, 6]
5 |
6 | ]
--------------------------------------------------------------------------------
/tests/newsUTF8.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duncantl/RJSONIO/HEAD/tests/newsUTF8.rda
--------------------------------------------------------------------------------
/configure.win:
--------------------------------------------------------------------------------
1 | cp src/libjson/Source/*.cpp src/
2 | cp src/libjson/JSONOptions.h src/
3 |
4 |
--------------------------------------------------------------------------------
/inst/doc/overview.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duncantl/RJSONIO/HEAD/inst/doc/overview.pdf
--------------------------------------------------------------------------------
/inst/doc/timings.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duncantl/RJSONIO/HEAD/inst/doc/timings.docx
--------------------------------------------------------------------------------
/inst/sampleData/array3.json:
--------------------------------------------------------------------------------
1 | [
2 | [ [1,2,3,4], [4, 5, 6, 7] ],
3 | [ "a", "b", "c" ]
4 | ]
--------------------------------------------------------------------------------
/inst/doc/toJSONTimes.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duncantl/RJSONIO/HEAD/inst/doc/toJSONTimes.rda
--------------------------------------------------------------------------------
/inst/doc/fromJSONTimes.rda:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duncantl/RJSONIO/HEAD/inst/doc/fromJSONTimes.rda
--------------------------------------------------------------------------------
/inst/sampleData/obj2.json:
--------------------------------------------------------------------------------
1 | /* JSON syntax error */
2 | {"a1" : "x",
3 | "a2" : "yz",
4 | [1, 2, 3]
5 | }
--------------------------------------------------------------------------------
/tests/exp.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | ans = fromJSON("[3.14e4, 3.14E4]")
3 | stopifnot(ans[[1]] == ans[[2]])
4 |
--------------------------------------------------------------------------------
/inst/sampleData/nestedObj.json:
--------------------------------------------------------------------------------
1 | {"a1" : "x",
2 | "a2" : "yz",
3 | "a3" : { "item": 1,
4 | "item": 2}
5 | }
--------------------------------------------------------------------------------
/inst/sampleData/obj3.json:
--------------------------------------------------------------------------------
1 | /* JSON syntax error */
2 | {"a1" : "x",
3 | "a2" : "yz",
4 | "logical" : true,
5 | "logicalArray" : [true, false]
6 | }
--------------------------------------------------------------------------------
/utfTest/GNUmakefile:
--------------------------------------------------------------------------------
1 |
2 | CPPFLAGS=-I../src -g
3 | CC=gcc
4 |
5 | json: json.o ../src/ConvertUTF.o ../src/JSON_parser.o
6 | $(CC) -o $@ $^
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2001-2014
2 | COPYRIGHT HOLDER: Duncan Temple Lang
3 | ORGANIZATION: R project & University of California at Davis
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/inst/sampleData/embedded.json:
--------------------------------------------------------------------------------
1 | This is text with JSON embedded in it.
2 | [
3 | [ 1, 2, 3],
4 | [ 4, 5]
5 | ]
6 | and then some more text following it.
--------------------------------------------------------------------------------
/tests/con2.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | con = textConnection("[1, 2, 3,\n4]"); fromJSON(con)
3 |
4 | try({con = textConnection("[1, 2, 3,]"); fromJSON(con)})
5 |
6 |
--------------------------------------------------------------------------------
/src/libjson/README:
--------------------------------------------------------------------------------
1 | Copy the .cpp files from libjson/Source/
2 | Leave the header files in that directory.
3 | Remove the documentation and any files in Objects/
4 |
--------------------------------------------------------------------------------
/tests/s4.R:
--------------------------------------------------------------------------------
1 | setClass("Foo",
2 | representation(a = "integer", b = "character"))
3 | setClass("Bar",
4 | representation(a = "integer", b = "character"))
5 |
--------------------------------------------------------------------------------
/inst/sampleData/obj1.json:
--------------------------------------------------------------------------------
1 | /* object with arrays and strings */
2 | {"a1" : ["x", "y"],
3 | "a2" : [1, 2, 3],
4 | "a3" : "a string",
5 | "a4" : true,
6 | "a 5" : [false, true]
7 | }
--------------------------------------------------------------------------------
/tests/scalarCollapse.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | ins = c("[1, 2, 3]",
4 | '[1, "2", 3]',
5 | '[true, 1, 3]',
6 | '[true, false, 3, "xyz"]')
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/libjson/copy:
--------------------------------------------------------------------------------
1 | SRC=/tmp/libjson
2 | cp $SRC/libjson.h $SRC/makefile .
3 |
4 | diff -qr Source $SRC/Source/ | grep 'Only in Source'
5 | # git rm files
6 |
7 | /bin/cp -fr $SRC/Source .
8 |
9 |
--------------------------------------------------------------------------------
/tests/encoding.R:
--------------------------------------------------------------------------------
1 | x = "Open Bar $300 \u5564\u9152\u3001\u6C23\u9152 \u4EFB\u98F2"
2 | print(x)
3 | Encoding(x)
4 | library(RJSONIO)
5 | fromJSON(paste('{"tweet":"', x, '"}', sep = ''))
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tests/nested.json:
--------------------------------------------------------------------------------
1 | [
2 | [ 1,
3 | [ 2, 3],
4 | [ 4, 6],
5 | 10, 20
6 | ]
7 | [ 100, 200, 300
8 | ]
9 | [ "a", "b", "c",
10 | ["wx", "yz"],
11 | true
12 | ]
13 | ]
14 |
--------------------------------------------------------------------------------
/README.libjson:
--------------------------------------------------------------------------------
1 | Install libjson with
2 |
3 | make SHARED=1 install
4 | or
5 | make SHARED=1
6 | make install SHARED=1
7 |
8 | (You need the SHARED=1 on the install as well as the build.)
9 |
10 |
--------------------------------------------------------------------------------
/tests/flat.json:
--------------------------------------------------------------------------------
1 | { "a" : 1,
2 | "b" : [true, false]
3 | }
4 |
5 | { "x" : 2,
6 | "y" : ["a", "b", "c"]
7 | }
8 |
9 | { "foo" : true,
10 | "bar" : [ [1, 2], [3, 4]],
11 | "foobar": "a string"
12 | }
13 |
--------------------------------------------------------------------------------
/tests/empty.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | str = "[ 1, {}, [1, 3, 5] ]"
4 | v = fromJSON(str)
5 | str1 = toJSON(v, collapse = " ")
6 |
7 | stopifnot( any( duplicated( gsub("[[:space:]]", "", c(str, str1)))))
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Web/GNUmakefile:
--------------------------------------------------------------------------------
1 | PACKAGE=RJSONIO
2 |
3 | ifndef ADMIN_TOOLS_DIR
4 | ADMIN_TOOLS_DIR=../../AdminTools
5 | endif
6 | include $(OMEGA_HOME)/R/Config/GNUmakefile.Web
7 |
8 | #include $(ADMIN_TOOLS_DIR)/GNUmakefile
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/prealloc.R:
--------------------------------------------------------------------------------
1 | f = "inst/sampleData/usaPolygons.as"
2 |
3 | # The idea here is to customize the reading by pre-allocating space.
4 | readArray =
5 | function(type, val) {
6 | # if(type)
7 | }
8 |
9 | # fromJSON(f, )
10 |
--------------------------------------------------------------------------------
/tests/con1.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | con = textConnection(c("[[1,2,3,4],", "[5, 6, 7, 8]]"))
4 | fromJSON(con)
5 |
6 | con = file(system.file("sampleData", "usaPolygons.as", package = "RJSONIO"))
7 | o = fromJSON(con)
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/fail.R:
--------------------------------------------------------------------------------
1 | toJSON(list(NA)) # change to make NA represent JSON null
2 |
3 | # now work:
4 | #roundtrip('["A","B","C"]')
5 | # roundtrip('["A",10,"C"]')
6 |
7 | # now work
8 | roundtrip('{"":10,"":13}')
9 | roundtrip('{"":10,"b":13}')
10 |
--------------------------------------------------------------------------------
/tests/serialize.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | setClass("A", representation(x = "integer", abc = "character"),
3 | prototype = list(x = 1:10, abc = c("Jan", "Feb", "Mar")))
4 | a = new("A")
5 |
6 | toJSON(a)
7 |
8 | toJSON(list(a, a))
9 |
10 |
--------------------------------------------------------------------------------
/src/Makevars.win:
--------------------------------------------------------------------------------
1 | PKG_CPPFLAGS=-I. -Ilibjson -Ilibjson/Source -DNDEBUG=1 -DJSON_VALIDATE -DJSON_LIBRARY=1 -DJSON_ISO_STRICT -DJSON_READ_PRIORITY=1
2 | # -DJSON_STREAM=1 already defined in JSONOPtions.h
3 | # -DJSON_READ_PRIORITY=1
4 | # -DJSON_NO_EXCEPTIONS=1
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tests/keys.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | ff = system.file("sampleData", "keys.json", package = "RJSONIO")
4 | print(ff)
5 | z = paste(readLines(ff), collapse = "\n")
6 |
7 | fromJSON(I(z))
8 |
9 | fromJSON(ff, function(type, val) { cat(names(type), "\n"); TRUE})
10 |
11 |
--------------------------------------------------------------------------------
/cleanup.in:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | CPP="@CPP_FILES@"
4 |
5 | if test -n "$CPP" ; then
6 | echo "Removing the CPP files copied from libjson into src: $CPP"
7 | (cd src ; rm $CPP)
8 | if test -e src/JSONOptions.h ; then
9 | rm src/JSONOptions.h
10 | fi
11 | fi
12 |
--------------------------------------------------------------------------------
/libjsonFixes:
--------------------------------------------------------------------------------
1 | libjson/Source/JSONDefs is not readable when installed
2 |
3 | cd libjson
4 | chmod a+rx Source
5 | chmod a+rx Source/JSONDefs
6 |
7 | The makefile doesn't work for SHARED=1 on OS X.
8 | -Wl,-soname,$(libname_shared_major_version)
9 |
10 | ldconfig
--------------------------------------------------------------------------------
/tests/utf8.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | if(!is.null(getOption('NYTimesAPI'))) {
3 | news = getForm('http://api.nytimes.com/svc/search/v1/article', 'api-key' = getOption('NYTimesAPI')["Article Search"], query = "climate change")
4 | } else
5 | load("newsUTF8.rda")
6 |
7 | fromJSON(news)
8 |
--------------------------------------------------------------------------------
/tests/array.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | a = array(1:(5*7*9), c(5, 7, 9))
3 | o = toJSON(a)
4 | isValidJSON(I(o))
5 | b = fromJSON(I(o))
6 |
7 | toJSON(table(1:3))
8 | toJSON(table(1:3, 1:3))
9 |
10 | #z = apply(a, 3, function(x, dim) toJSON(x))
11 | #toJSON(array(1:8,c(2,2,2)))
12 |
--------------------------------------------------------------------------------
/cp_libjson:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if test -z "${JSON_DIR}" ; then
4 | echo "You need to set JSON_DIR"
5 | exit 1;
6 | fi
7 |
8 | cp -r $JSON_DIR/Dependencies .
9 |
10 | cd src/libjson
11 | cp $JSON_DIR/libjson.h .
12 | cp $JSON_DIR/JSONOptions.h .
13 |
14 | cp -r $JSON_DIR/Source .
15 |
--------------------------------------------------------------------------------
/leak.R:
--------------------------------------------------------------------------------
1 | library("RJSONIO")
2 | f <- file("inst/sampleData/web.json")
3 | f.lines <- readLines(f)
4 | f.str <- paste(f.lines, collapse = "\n")
5 | ans = vector("list", 1000)
6 | for (x in seq_len(1000)) {
7 | foo <- fromJSON(I(f.str), asText = TRUE)
8 | # ans[[x]] = gc()
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/dataframe.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | DF <- head(cars)
3 | DF[1,1] <- NA
4 | cat(toJSON(DF))
5 |
6 | outDF = toJSON(DF)
7 | tmp <- fromJSON(content = outDF, asText = TRUE, simplify = TRUE, nullValue = NA)
8 | as.data.frame(tmp)
9 |
10 | #origDF <- as.data.frame(lapply(reconstruction, "unlist"))
11 |
--------------------------------------------------------------------------------
/tests/bigInt.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | i = fromJSON("[123]")[[1]]
3 | is.integer(i)
4 | i == 123L
5 |
6 |
7 | x = fromJSON("[12345678901]")[[1]]
8 | is.numeric(x[[1]])
9 | x == 12345678901
10 |
11 | x = fromJSON("[-12345678901]")[[1]]
12 | is.numeric(x[[1]])
13 | x == -12345678901
14 |
15 |
16 |
--------------------------------------------------------------------------------
/inst/doc/overview.bib:
--------------------------------------------------------------------------------
1 |
2 | @misc{bib:libjson,
3 | title = {libjson},
4 | author = {Wallace, Johnathan},
5 | url = {http://libjson.sourceforge.net},
6 | year = 2011
7 | }
8 |
9 | @misc{bib:rjson,
10 | title = {The rjson package},
11 | author = {Couture-Beil, Alex},
12 | year = "2011-6-26"
13 | }
14 |
--------------------------------------------------------------------------------
/testStream.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | cb =
4 | function(node)
5 | {
6 | cat("in cb", .Call("R_json_node_type", node), "\n")
7 |
8 | TRUE
9 | }
10 |
11 | txt = paste(readLines("inst/sampleData/nestedObj.json"), collapse = "\n")
12 | txt = "[1, 2, 3]"
13 | .Call("R_json_stream_parse", txt, cb)
14 |
--------------------------------------------------------------------------------
/inst/sampleData/menu.json:
--------------------------------------------------------------------------------
1 | {"menu": {
2 | "id": "file",
3 | "value": "File",
4 | "popup": {
5 | "menuitem": [
6 | {"value": "New", "onclick": "CreateNewDoc()"},
7 | {"value": "Open", "onclick": "OpenDoc()"},
8 | {"value": "Close", "onclick": "CloseDoc()"}
9 | ]
10 | }
11 | }}
12 |
--------------------------------------------------------------------------------
/src/Makevars.in:
--------------------------------------------------------------------------------
1 | PKG_CPPFLAGS=@LIBJSON_CFLAGS@ -DNDEBUG=1 -DJSON_VALIDATE -DJSON_STREAM=1 -DJSON_READ_PRIORITY=1 -DJSON_LIBRARY=1 -DJSON_ISO_STRICT -DJSON_STREAM -DJSON_DEBUG
2 | # -DJSON_STREAM=1 already defined in JSONOPtions.h
3 | # -DJSON_NO_EXCEPTIONS=1
4 | # -DJSON_READ_PRIORITY
5 | PKG_LIBS=@LIBJSON_LIBS@
6 |
--------------------------------------------------------------------------------
/GNUmakefile:
--------------------------------------------------------------------------------
1 | include $(OMEGA_HOME)/R/Config/GNUmakefile
2 |
3 | build: Changes.html Changes
4 | -rm src/*.o src/*.so
5 | (cd .. ; R CMD build RJSONIO)
6 |
7 | XSL_DIR=$(OMEGA_HOME)/Docs/XSL
8 | Changes.html: Changes.xml
9 | xsltproc -o $@ $(XSL_DIR)/html/ChangeLog.xsl $<
10 |
11 | Changes: Changes.xml
12 | xsltproc -o $@ $(XSL_DIR)/text/ChangeLog.xsl $<
13 |
--------------------------------------------------------------------------------
/inst/doc/GNUmakefile:
--------------------------------------------------------------------------------
1 | ifndef DYN_DOCS
2 | DYN_DOCS=$(HOME)/Classes/StatComputing/XDynDocs/inst
3 | endif
4 |
5 | TEX_XSL_ARGS=--stringparam doc.class '[article]{jss}' --stringparam bibliog.file $*
6 | DB2JSS_XSL=$(DYN_DOCS)/XSL/OmegahatXSL/latex/myRawJSS.xsl
7 | LATEX_STYLE=$(DB2JSS_XSL)
8 |
9 | overview.tex: overview.bib
10 |
11 | include $(DYN_DOCS)/Make/Makefile
12 |
--------------------------------------------------------------------------------
/tests/charNULL.R:
--------------------------------------------------------------------------------
1 | # issue spotted by Alexandre Sieira
2 | # and his example code.
3 | library(RJSONIO)
4 |
5 | fromJSON("[ 1, null, 4 ]", asText = TRUE, simplify = TRUE)
6 | fromJSON('[ "a", null, "d" ]', asText = TRUE, simplify = TRUE)
7 |
8 | fromJSON("[ 1, null, 4 ]", asText = TRUE, simplify = TRUE, nullValue = -999L)
9 | fromJSON('[ "a", null, "d" ]', asText = TRUE, simplify = TRUE, nullValue = "999")
10 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONAllocator.cpp:
--------------------------------------------------------------------------------
1 | #include "JSONAllocator.h"
2 |
3 | #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
4 | #include "JSONMemory.h"
5 |
6 | void * JSONAllocatorRelayer::alloc(size_t bytes) json_nothrow {
7 | return JSONMemory::json_malloc(bytes);
8 | }
9 |
10 | void JSONAllocatorRelayer::dealloc(void * ptr) json_nothrow {
11 | JSONMemory::json_free(ptr);
12 | }
13 | #endif
14 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | useDynLib(RJSONIO)
2 | import("methods")
3 |
4 | export(toJSON)
5 | exportMethods(toJSON)
6 |
7 | export(emptyNamedList)
8 |
9 | export(fromJSON)
10 | exportMethods(fromJSON)
11 | exportPattern("^JSON_T")
12 | export(asJSVars)
13 |
14 | export(basicJSONHandler)
15 |
16 | export(isValidJSON)
17 | exportMethods(isValidJSON)
18 |
19 | export(Strict, StrictNumeric, StrictCharacter, StrictLogical)
20 |
21 | export(readJSONStream)
22 |
--------------------------------------------------------------------------------
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | GNUmakefile
2 | .*/autom4te.*
3 | config.log
4 | config.status
5 | Objects.*
6 | purdy.R
7 | .*.bbl
8 | .*.blg
9 | .*.aux
10 | .*.out
11 | .*.log
12 | roebuck.R
13 | json-asIS-withlevel
14 | src/Makevars$
15 | Changes.xml
16 | intName.R
17 | streaming.R
18 | fail.R
19 | tests.R
20 | testStream.R
21 | dataframe.R
22 | leak.R
23 | jsonText.rda
24 | foo.html
25 | Web
26 | bigFile.R
27 | experiments
28 | utfTest.*
29 | ivan
30 | json-asIS-withlevel
31 |
--------------------------------------------------------------------------------
/utfTest/raw.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | x = paste(readLines("utf/news.txt"), collapse = "\n")
4 | r = charToRaw(x)
5 | .Call("R_readFromJSON", r, 20L, TRUE, function(x, ...){}, NULL, c(0L, 5619L))
6 |
7 | a = readBin("utf/news.txt", "raw", file.info("utf/news.txt")[1, "size"])
8 | .Call("R_readFromJSON", a, 20L, TRUE, function(x, ...){}, NULL, c(0L, 5619L))
9 |
10 | i = as.integer(charToRaw(x))
11 | .Call("R_readFromJSON", i, 20L, TRUE, function(x, ...){}, NULL, c(0L, 5619L))
12 |
--------------------------------------------------------------------------------
/tests/toJSON.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | toJSON(list(1, 2, list(1, NA)))
4 |
5 | toJSON(list(1, 2, list(NA))) # collapses the sub-list into the main vector.
6 |
7 |
8 | e = new.env(); e$a = 1:10; e$bc = letters[1:3]
9 | cat(toJSON(e, pretty = TRUE))
10 |
11 |
12 | a = list(x=1, y=character(0))
13 | fromJSON( toJSON( a ) )
14 | a = list(x=1, y=character(0), b = 1)
15 | fromJSON( toJSON( a ) )
16 |
17 |
18 | a = list(x = vector(), y = 123, z = "allo")
19 | fromJSON(toJSON(a))
20 |
21 |
22 |
--------------------------------------------------------------------------------
/tests/simple.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | x = "[1, 3, 10, 19]"
3 | fromJSON(I(x))
4 |
5 | h = RJSONIO:::basicJSONHandler()
6 | fromJSON(x, h$update)
7 |
8 | if(!(fromJSON(I("[3.1415]")) == 3.1415))
9 | stop("Failed for doubles")
10 |
11 |
12 | # From couchdb
13 |
14 | x = '{"total_rows":3,"offset":0,"rows":[{"id":"abc","key":"xyz","value":{"rev":"1-3980939464"}},{"id":"x123","key":"x123","value":{"rev":"1-1794908527"}}]}\n'
15 |
16 | fromJSON(x)
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/R/stream.R:
--------------------------------------------------------------------------------
1 | readJSONStream =
2 | function(con, cb = NULL,
3 | simplify = Strict, nullValue = NULL, simplifyWithNames = TRUE)
4 | {
5 | if(is(con, "connection"))
6 | # e = substitute(readLines(con, n = 1), list(con = con))
7 | e = substitute(readChar(con, 1024), list(con = con))
8 | else # Expect an expression or the name of a file
9 | e = con
10 |
11 | .Call("R_json_parser_init_from_con", e, cb,
12 | as.integer(simplify), nullValue, as.logical(simplifyWithNames))
13 | }
14 |
--------------------------------------------------------------------------------
/cleanup:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | CPP="JSONAllocator.cpp
4 | JSONChildren.cpp
5 | JSONDebug.cpp
6 | JSONIterators.cpp
7 | JSONMemory.cpp
8 | JSONNode.cpp
9 | JSONNode_Mutex.cpp
10 | JSONPreparse.cpp
11 | JSONStream.cpp
12 | JSONValidator.cpp
13 | JSONWorker.cpp
14 | JSONWriter.cpp
15 | internalJSONNode.cpp
16 | libjson.cpp"
17 |
18 | if test -n "$CPP" ; then
19 | echo "Removing the CPP files copied from libjson into src: $CPP"
20 | (cd src ; rm $CPP)
21 | if test -e src/JSONOptions.h ; then
22 | rm src/JSONOptions.h
23 | fi
24 | fi
25 |
--------------------------------------------------------------------------------
/purdy.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | x0 = list(sub1 = list(a = 1:10, b = 100, c = 1000), sub2 = list(animal1 = "ape", animal2 = "bear", animal3 = "cat"))
4 | y0 = list(sub1 = list(a = 1:10, b = 100L, c = 1000L), sub2 = list(animal1 = "ape", animal2 = "bear", animal3 = "cat"))
5 | z0 = list(sub1 = list(a = 10, b = 100, c = 1000), sub2 = list(animal1 = "ape", animal2 = "bear", animal3 = "cat"))
6 |
7 |
8 | j0 = toJSON(x0)
9 | x1 = fromJSON(j0, simplify = FALSE)
10 | x2 = fromJSON(j0, simplify = TRUE)
11 | x3 = fromJSON(j0, simplify = Strict)
12 |
--------------------------------------------------------------------------------
/libjsonNotes:
--------------------------------------------------------------------------------
1 | Modified
2 | in Source/
3 | JSONChildren.h - use namespace std; - see BDR's note.
4 | libjson.cpp - change ../../libjson.h to "libjson/libjson.h"
5 |
6 | JSONStats.h - change "../../JSONOptions.h" to "JSONOptions.h". This may not be necessary after changes to configure.in and copying files to src/
7 |
8 | Then copy to the R package source:
9 |
10 | cd src/libjson
11 | cp -f ~/Downloads/libjson/_internal/Source/[A-Za-z]* Source
12 | cp -f ~/Downloads/libjson/_internal/Source/JSONDefs/* Source/JSONDefs
13 |
14 | configure copies src/libjson/JSONOptions.h to src/ now.
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONSingleton.h:
--------------------------------------------------------------------------------
1 | #ifndef JSONSINGLETON_H
2 | #define JSONSINGLETON_H
3 |
4 | template class JSONSingleton {
5 | public:
6 | static inline T get(void){
7 | return get_singleton() -> ptr;
8 | }
9 | static inline void set(T p){
10 | get_singleton() -> ptr = p;
11 | }
12 | private:
13 | inline JSONSingleton() : ptr(NULL) { }
14 | JSONSingleton(const JSONSingleton &);
15 | JSONSingleton operator = (const JSONSingleton &);
16 | static inline JSONSingleton * get_singleton(void){
17 | static JSONSingleton instance;
18 | return &instance;
19 | }
20 | T ptr;
21 | };
22 |
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/libjson/bdr:
--------------------------------------------------------------------------------
1 | Someone is writing C in C++ in libjson, and not declaring it correctly.
2 |
3 | Can you please add
4 |
5 | using namespace std;
6 |
7 | to the top of RJSONIO/src/libjson/Source/JSONChildren.h
8 |
9 | to get memmove etc into scope.
10 |
11 | The remaining problem,
12 |
13 | "libjson/Source/NumberToString.h", line 130: Error: The function "snprintf" must have a prototype.
14 |
15 | is trickier as snprintf is not a C++ and not a C90 function, and indeed the Solaris C++ headers seem to have vsnprintf but not snprintf. So that file needs to have
16 |
17 | #ifdef __SUNPRO_CC
18 | #include
19 | #else
20 | #include
21 | #endif
22 |
--------------------------------------------------------------------------------
/tests.R:
--------------------------------------------------------------------------------
1 | str = "[ 1, {}, [1, 3, 5] ]"
2 | fromJSON(str)
3 |
4 | fromJSON('[ "abc", "def"]')
5 |
6 | fromJSON('[ 1, 2, null]', nullValue = 123)
7 |
8 | fromJSON('[ true, false]')
9 | fromJSON('[ true, false, 1]')
10 |
11 | fromJSON('[ 1, 2, true]')
12 | fromJSON('[ 1, 2, 3.4, false]')
13 |
14 | fromJSON('[ 1, 2, 3.4, 1, null]')
15 |
16 |
17 |
18 | fromJSON('{ "a" : 1, "b" : "duncan", "f": [ 1, 2]}')
19 |
20 | toJSON(list(1, 2, list(NA)), .na = -9999)
21 |
22 |
23 |
24 | x = '[ 1, 2, {"a": [ 10, [3, 4] ], "bcd": {"xy": [1, 2], "wy": {"hij": true, "wsd": [true, false]}}}]'
25 | fromJSON(x)
26 |
27 |
28 | toJSON(list(a = pi, b = matrix(c(1:3, pi), 2, 2)), digits = 10)
29 |
30 |
--------------------------------------------------------------------------------
/inst/sampleData/glossay.json:
--------------------------------------------------------------------------------
1 | {
2 | "glossary": {
3 | "title": "example glossary",
4 | "GlossDiv": {
5 | "title": "S",
6 | "GlossList": {
7 | "GlossEntry": {
8 | "ID": "SGML",
9 | "SortAs": "SGML",
10 | "GlossTerm": "Standard Generalized Markup Language",
11 | "Acronym": "SGML",
12 | "Abbrev": "ISO 8879:1986",
13 | "GlossDef": {
14 | "para": "A meta-markup language, used to create markup languages such as DocBook.",
15 | "GlossSeeAlso": ["GML", "XML"]
16 | },
17 | "GlossSee": "markup"
18 | }
19 | }
20 | }
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDefs/Unknown_C.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_UNKNOWN_C_HEADER
2 | #define JSON_UNKNOWN_C_HEADER
3 |
4 | #if !defined(__GNUC__) && !defined(_MSC_VER)
5 |
6 | #define json_deprecated(method, warning) method
7 |
8 | #define json_nothrow
9 | #define json_throws(x)
10 | #define json_pure json_nothrow
11 | #define json_read_priority
12 | #define json_write_priority
13 | #define json_malloc_attr json_nothrow
14 | #define json_hot
15 | #define json_cold
16 | #define json_likely(x) x
17 | #define json_unlikely(x) x
18 |
19 | #ifdef JSON_LESS_MEMORY
20 | #define PACKED(x) :x
21 | #define BITS(x) :x
22 | #endif
23 |
24 | #endif
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDefs/Visual_C.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_VISUAL_C_HEADER
2 | #define JSON_VISUAL_C_HEADER
3 |
4 | #ifdef _MSC_VER
5 |
6 | #define json_deprecated(method, warning) __declspec(deprecated(warning)) method
7 |
8 | #define json_nothrow
9 | #define json_throws(x)
10 | #define json_pure json_nothrow
11 | #define json_read_priority
12 | #define json_write_priority
13 | #define json_malloc_attr json_nothrow
14 | #define json_hot
15 | #define json_cold
16 | #define json_likely(x) x
17 | #define json_unlikely(x) x
18 |
19 | #ifdef JSON_LESS_MEMORY
20 | #define PACKED(x) :x
21 | #define BITS(x) :x
22 | #endif
23 |
24 | #endif
25 |
26 | #endif
27 |
--------------------------------------------------------------------------------
/inst/sampleData/widget.json:
--------------------------------------------------------------------------------
1 | {"widget": {
2 | "debug": "on",
3 | "window": {
4 | "title": "Sample Konfabulator Widget",
5 | "name": "main_window",
6 | "width": 500,
7 | "height": 500
8 | },
9 | "image": {
10 | "src": "Images/Sun.png",
11 | "name": "sun1",
12 | "hOffset": 250,
13 | "vOffset": 250,
14 | "alignment": "center"
15 | },
16 | "text": {
17 | "data": "Click Here",
18 | "size": 36,
19 | "style": "bold",
20 | "name": "text1",
21 | "hOffset": 250,
22 | "vOffset": 100,
23 | "alignment": "center",
24 | "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
25 | }
26 | }}
27 |
--------------------------------------------------------------------------------
/inst/doc/biblio.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | libjson
11 | Johnathan Wallace
12 |
13 |
14 |
15 |
16 | The rjson package
17 | Alex Couture-Beil
18 | 2011-6-26
19 |
20 |
21 |
--------------------------------------------------------------------------------
/inst/doc/overview.bbl:
--------------------------------------------------------------------------------
1 | \begin{thebibliography}{2}
2 | \newcommand{\enquote}[1]{``#1''}
3 | \providecommand{\natexlab}[1]{#1}
4 | \providecommand{\url}[1]{\texttt{#1}}
5 | \providecommand{\urlprefix}{URL }
6 | \expandafter\ifx\csname urlstyle\endcsname\relax
7 | \providecommand{\doi}[1]{doi:\discretionary{}{}{}#1}\else
8 | \providecommand{\doi}{doi:\discretionary{}{}{}\begingroup
9 | \urlstyle{rm}\Url}\fi
10 | \providecommand{\eprint}[2][]{\url{#2}}
11 |
12 | \bibitem[{Couture-Beil(2011-6-26)}]{bib:rjson}
13 | Couture-Beil A (2011-6-26).
14 | \newblock \enquote{The rjson package.}
15 |
16 | \bibitem[{Wallace(2011)}]{bib:libjson}
17 | Wallace J (2011).
18 | \newblock \enquote{libjson.}
19 | \newblock \urlprefix\url{http://libjson.sourceforge.net}.
20 |
21 | \end{thebibliography}
22 |
--------------------------------------------------------------------------------
/tests/bigFile.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | checkValidity <- function(N, parse = FALSE, short = FALSE) {
4 | l = if(short)
5 | lapply(1:N, function(x) sample(10L, 10, replace = TRUE))
6 | else
7 | lapply(1:10, function(x) sample(10L, N, replace = TRUE))
8 | # names(l) <- letters[1:10]
9 |
10 | a <- toJSON(l)
11 |
12 | message("JSON document of size: ", nchar(a))
13 | if(parse)
14 | fromJSON(a, asText = TRUE)
15 | else
16 | isValidJSON(a, asText = TRUE)
17 | }
18 |
19 |
20 |
21 | if(FALSE) {
22 | checkValidity(1e3L)
23 |
24 | #JSON document of size:31049
25 |
26 | #[1] TRUE
27 |
28 | checkValidity(1e6L)
29 |
30 | #JSON document of size:31002696
31 |
32 | #[1] TRUE
33 |
34 | checkValidity(2e6L)
35 |
36 | #JSON document of size:61999858
37 | #[1] FALSE
38 | }
39 |
--------------------------------------------------------------------------------
/tests/dataframe.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | empty = data.frame(a = integer(), b = numeric())
4 | r = data.frame(fromJSON(toJSON(empty)))
5 | identical(dim(r), dim(empty))
6 | identical(names(r), names(empty))
7 |
8 | # The columns are of different types as the fromJSON version
9 | # are just list()
10 |
11 | oneRow = data.frame(a = integer(1), b = numeric(1))
12 | r = data.frame(fromJSON(toJSON(oneRow)))
13 | stopifnot(identical(dim(r), dim(oneRow)))
14 | stopifnot(identical(names(r), names(oneRow)))
15 |
16 |
17 | twoRows = data.frame(a = 1:2, b = as.numeric(1:2))
18 | r = data.frame(fromJSON(toJSON(twoRows)))
19 | stopifnot(all.equal(r, twoRows))
20 |
21 |
22 | j = toJSON(twoRows, byrow = TRUE)
23 | r = data.frame(do.call(rbind, fromJSON(j)))
24 |
25 | j = toJSON(twoRows, byrow = TRUE, colNames = TRUE)
26 | r = data.frame(do.call(rbind, fromJSON(j)))
27 | all.equal(twoRows, r)
28 |
--------------------------------------------------------------------------------
/experiments/stream.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | if(FALSE) {
3 | jtxt = "[1,\n 2,\n 3,\n 4]"
4 | con = textConnection(jtxt)
5 | } else {
6 | # con = file("inst/sampleData/array2.json", "r")
7 | f = "inst/sampleData/web.json"
8 | # f = "inst/sampleData/widget.json"
9 |
10 | con = file(f, "r")
11 | }
12 |
13 | streamJSON =
14 | function(con, cb =function(obj) { cat("Called cb\n"); print(obj)})
15 | {
16 | getData = function() {
17 | x = readLines(con, n = 1)
18 | cat("R: ", sQuote(x), "\n", sep = "")
19 | if(length(x))
20 | sprintf("%s\n", x)
21 | else
22 | character()
23 | }
24 | # conCall = substitute({x = readLines(con, n = 1); cat(x, "\n"); if(length(x)) sprintf("%s\n", x) else character()}, list(con = con))
25 | cbCall = substitute(foo(val), list(foo = cb))
26 |
27 | .Call("R_json_parser_init_from_con", getData, cbCall)
28 | }
29 |
30 | streamJSON(con)
31 |
--------------------------------------------------------------------------------
/Todo.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | -
9 | Swap in the latest version of libjson (e.g. 7.0)
10 |
11 | We should allow the package to be built against
12 | an existing installed libjson.
13 |
14 |
15 | -
16 | Perhaps allow objects with homogeneous elements to be converted
17 | to named vectors, e.g. servlet-mapping in web.json
18 |
19 |
20 | -
21 |
22 | fromJSON("inst/sampleData/menu.json")
23 |
24 | takes the elements in menuitem and condenses them into a matrix
25 | and discards the names.
26 |
27 | Put in a check on names in condense
28 |
29 |
30 | -
31 | Put in a pure C routine to read the content.
32 | Mimic the R basicJSONHandler$update function.
33 |
34 |
--------------------------------------------------------------------------------
/src/Rlibjson.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | typedef enum { NATIVE_STR_ROUTINE, SEXP_STR_ROUTINE, R_FUNCTION, GARBAGE} StringFunctionType;
6 |
7 | typedef SEXP (*SEXPStringRoutine)(const char *, cetype_t encoding);
8 | typedef char * (*StringRoutine)(const char *);
9 |
10 | SEXP processJSONNode(JSONNODE *node, int parentType, int simplify, SEXP nullValue,
11 | int simplifyWithNames, cetype_t, SEXP strFun, StringFunctionType str_fun_type);
12 |
13 |
14 | typedef enum {NONE, ALL, STRICT_LOGICAL = 2, STRICT_NUMERIC = 4, STRICT_CHARACTER = 8, STRICT = 14} SimplifyStyle;
15 |
16 |
17 |
18 |
19 |
20 | #ifndef PROBLEM
21 |
22 | #define R_PROBLEM_BUFSIZE 4096
23 | #define PROBLEM {char R_problem_buf[R_PROBLEM_BUFSIZE];(snprintf)(R_problem_buf, R_PROBLEM_BUFSIZE,
24 | #define ERROR ),Rf_error(R_problem_buf);}
25 | #define WARNING(x) ),Rf_warning(R_problem_buf);}
26 | #define WARN WARNING(NULL)
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/inst/sampleData/keys.json:
--------------------------------------------------------------------------------
1 | {"menu": {
2 | "header": "SVG Viewer",
3 | "items": [
4 | {"id": "Open"},
5 | {"id": "OpenNew", "label": "Open New"},
6 | null,
7 | {"id": "ZoomIn", "label": "Zoom In"},
8 | {"id": "ZoomOut", "label": "Zoom Out"},
9 | {"id": "OriginalView", "label": "Original View"},
10 | null,
11 | {"id": "Quality"},
12 | {"id": "Pause"},
13 | {"id": "Mute"},
14 | null,
15 | {"id": "Find", "label": "Find..."},
16 | {"id": "FindAgain", "label": "Find Again"},
17 | {"id": "Copy"},
18 | {"id": "CopyAgain", "label": "Copy Again"},
19 | {"id": "CopySVG", "label": "Copy SVG"},
20 | {"id": "ViewSVG", "label": "View SVG"},
21 | {"id": "ViewSource", "label": "View Source"},
22 | {"id": "SaveAs", "label": "Save As"},
23 | null,
24 | {"id": "Help"},
25 | {"id": "About", "label": "About Adobe CVG Viewer..."}
26 | ]
27 | }}
28 |
--------------------------------------------------------------------------------
/inst/sampleData/menu1.json:
--------------------------------------------------------------------------------
1 | {"menu": {
2 | "header": "SVG Viewer",
3 | "items": [
4 | {"id": "Open"},
5 | {"id": "OpenNew", "label": "Open New"},
6 | null,
7 | {"id": "ZoomIn", "label": "Zoom In"},
8 | {"id": "ZoomOut", "label": "Zoom Out"},
9 | {"id": "OriginalView", "label": "Original View"},
10 | null,
11 | {"id": "Quality"},
12 | {"id": "Pause"},
13 | {"id": "Mute"},
14 | null,
15 | {"id": "Find", "label": "Find..."},
16 | {"id": "FindAgain", "label": "Find Again"},
17 | {"id": "Copy"},
18 | {"id": "CopyAgain", "label": "Copy Again"},
19 | {"id": "CopySVG", "label": "Copy SVG"},
20 | {"id": "ViewSVG", "label": "View SVG"},
21 | {"id": "ViewSource", "label": "View Source"},
22 | {"id": "SaveAs", "label": "Save As"},
23 | null,
24 | {"id": "Help"},
25 | {"id": "About", "label": "About Adobe CVG Viewer..."}
26 | ]
27 | }}
28 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDefs/Strings_Defs.h:
--------------------------------------------------------------------------------
1 | #ifndef STRINGS_DEFS_HEADER
2 | #define STRINGS_DEFS_HEADER
3 |
4 | #include "../../../JSONOptions.h"
5 |
6 | #ifdef JSON_UNICODE
7 | #define json_char wchar_t
8 | #define json_uchar wchar_t
9 | #ifdef __cplusplus
10 | #include /* need wide characters */
11 | #ifndef JSON_STRING_HEADER
12 | #include
13 | #endif
14 | #else
15 | #include /* need wide characters */
16 | #endif
17 | #define JSON_TEXT(s) L ## s
18 | #define json_strlen wcslen
19 | #define json_strcmp wcscmp
20 | #else
21 | #define json_char char
22 | #define json_uchar unsigned char
23 | #ifdef __cplusplus
24 | #ifndef JSON_STRING_HEADER
25 | #include
26 | #endif
27 | #else
28 | #include /* still need it for strlen and such */
29 | #endif
30 | #define JSON_TEXT(s) s
31 | #define json_strlen strlen
32 | #define json_strcmp strcmp
33 | #endif
34 |
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/R/isValid.R:
--------------------------------------------------------------------------------
1 | setGeneric("isValidJSON",
2 | function(content, asText = inherits(content, "AsIs"), ...)
3 | standardGeneric("isValidJSON"))
4 |
5 | setMethod("isValidJSON", "AsIs",
6 | function(content, asText = inherits(content, "AsIs"), ...) {
7 | .Call("R_isValidJSON", as.character(content))
8 | })
9 |
10 | setMethod("isValidJSON", "character",
11 | function(content, asText = inherits(content, "AsIs"), ...) {
12 |
13 | if(!asText) {
14 | content = I(suppressWarnings(paste(readLines(content), collapse = "\n")))
15 | } else
16 | content = I(content)
17 |
18 | isValidJSON(content, asText = TRUE)
19 | })
20 |
21 | setMethod("isValidJSON", "connection",
22 | function(content, asText = inherits(content, "AsIs"), ...) {
23 | content = I(suppressWarnings(paste(readLines(content), collapse = "\n")))
24 | isValidJSON(content, asText = TRUE)
25 | })
26 |
--------------------------------------------------------------------------------
/man/JSON_T_NULL.Rd:
--------------------------------------------------------------------------------
1 | \name{Bob}
2 | %\Rdversion{1.1}
3 | \alias{JSON_T_ARRAY_BEGIN}
4 | \alias{JSON_T_ARRAY_END}
5 | \alias{JSON_T_FALSE}
6 | \alias{JSON_T_FLOAT}
7 | \alias{JSON_T_INTEGER}
8 | \alias{JSON_T_KEY}
9 | \alias{JSON_T_MAX}
10 | \alias{JSON_T_NONE}
11 | \alias{JSON_T_NULL}
12 | \alias{JSON_T_OBJECT_BEGIN}
13 | \alias{JSON_T_OBJECT_END}
14 | \alias{JSON_T_STRING}
15 | \alias{JSON_T_TRUE}
16 | \docType{data}
17 | \title{
18 | Symbolic constants identifying the type of a JSON value.
19 | }
20 | \description{
21 | These constants are used by handler functions that
22 | are called when a JSON value is encountered by the
23 | JSON parser. These identify the type of the JSON value.
24 | The values will already have been converted, but
25 | the start and end array and object events won't have
26 | a type.
27 | }
28 | %\usage{}
29 | \format{
30 | A collection of integer values.
31 | }
32 | \source{
33 | \code{JSON_parser.h} code from \url{http://www.json.org}.
34 | }
35 | \references{
36 | \url{http://www.json.org}.
37 | }
38 | %\examples{}
39 | \keyword{datasets}
40 |
--------------------------------------------------------------------------------
/tests/simplify.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | stopifnot(is.list(fromJSON('[1, "2.3", "abc"]', simplify = Strict)))
4 |
5 | stopifnot(is.character(fromJSON('[1, "2.3", "abc"]', simplify = TRUE)))
6 |
7 | stopifnot(is.character(fromJSON('[1, true, "2.3", "abc"]', simplify = TRUE)))
8 |
9 | stopifnot(is.list(fromJSON('[1, true, "2.3", "abc"]', simplify = Strict)))
10 |
11 | stopifnot(is.list(fromJSON('[1, true]', simplify = Strict)))
12 | stopifnot(is.numeric(fromJSON('[1, true]', simplify = TRUE)))
13 |
14 | stopifnot(is.character(fromJSON('["1", true]', simplify = TRUE)))
15 |
16 |
17 | stopifnot(is.character(fromJSON('{ "a": "1", "b": true}', simplify = TRUE)))
18 | stopifnot(is.list(fromJSON('{ "a": "1", "b": true}', simplify = Strict)))
19 |
20 | stopifnot(is.character(fromJSON('{ "a": "1", "b": "true"}', simplify = Strict)))
21 |
22 | stopifnot(is.numeric(fromJSON('{ "a": 1, "b": 2}', simplify = Strict)))
23 |
24 | stopifnot(is.list(fromJSON('{ "a": 1, "b": 2}', simplify = FALSE)))
25 |
26 |
27 | is.na(fromJSON(toJSON( c("a", NA, "b", "c")), nullValue = NA, simplify = TRUE))
28 | is.na(fromJSON(toJSON( c(1, NA, 3, 4)), nullValue = NA, simplify = TRUE))
29 |
30 | is.na(fromJSON(toJSON( c(TRUE, NA, FALSE, TRUE)), nullValue = NA, simplify = TRUE))
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This RJSONIO package uses the libjson C library from
2 | libjson.sourceforge.net. A version of that C++ code is included in
3 | this package and can be used. Alternatively, one can use a different
4 | version of libjson, e.g. a more recent version. To do this,
5 | you install that version of libjson with
6 | ```
7 | make SHARED=1 install
8 | ```
9 | The key thing is to make this a shared library so we can link against
10 | it as position independent code (PIC).
11 |
12 | By default, this will be installed in /usr/local.
13 | You can control this with
14 | ```
15 | make SHARED=1 install prefix="/my/directory"
16 | ```
17 |
18 | The configuration script will attempt to find libjson on your system,
19 | looking in /usr/local. If this is not the location you installed
20 | libjson to, you can specify the prefix via the --with-prefix=/my/directory,
21 | e.g.
22 | ```
23 | R CMD INSTALL --configure-args="--with-prefix=/my/directory" RJSONIO
24 | ```
25 |
26 | If you want to force using the version of libjson contained in this package,
27 | you can use
28 | ```
29 | R CMD INSTALL --configure-args="--with-local-libjson=yes" RJSONIO
30 | ```
31 |
32 | If you do use a version of libjson installed into a non-standard place,
33 | you will probably need to modify your LD_LIBRARY_PATH (or DYLD_LIBRARY_PATH on OS X)
34 | environment variable.
35 |
36 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONPreparse.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBJSON_GUARD_PREPARSE_H
2 | #define LIBJSON_GUARD_PREPARSE_H
3 |
4 | #include "JSONDebug.h"
5 | #include "JSONNode.h"
6 |
7 | #if (defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY))
8 |
9 | #ifdef JSON_COMMENTS
10 | #define COMMENT_PARAM(name) ,const json_string & name
11 | #else
12 | #define COMMENT_PARAM(name)
13 | #endif
14 |
15 | class JSONPreparse {
16 | public:
17 | static JSONNode isValidNumber(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
18 | static JSONNode isValidMember(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
19 | static json_string isValidString(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
20 | static void isValidNamedObject(json_string::const_iterator & ptr, json_string::const_iterator & end, JSONNode & parent COMMENT_PARAM(comment)) json_read_priority;
21 | static JSONNode isValidObject(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
22 | static JSONNode isValidArray(json_string::const_iterator & ptr, json_string::const_iterator & end) json_read_priority;
23 | static JSONNode isValidRoot(const json_string & json) json_throws(std::invalid_argument) json_read_priority;
24 | };
25 |
26 | #endif
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSON_Base64.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBJSON_GUARD_BASE64_H
2 | #define LIBJSON_GUARD_BASE64_H
3 |
4 | #include "JSONDebug.h"
5 | #if defined(JSON_BINARY) || defined(JSON_EXPOSE_BASE64) //if this is not needed, don't waste space compiling it
6 |
7 | #include "../Dependencies/libbase64++/libbase64++.h"
8 |
9 | class JSONBase64 {
10 | public:
11 | inline static json_string json_encode64(const unsigned char * binary, size_t bytes) json_nothrow json_cold;
12 | inline static std::string json_decode64(const json_string & encoded) json_nothrow json_cold;
13 | private:
14 | JSONBase64(void);
15 | };
16 |
17 | json_string JSONBase64::json_encode64(const unsigned char * binary, size_t bytes) json_nothrow {
18 | #if defined JSON_DEBUG || defined JSON_SAFE
19 | return libbase64::encode(binary, bytes);
20 | #else
21 | return libbase64::encode(binary, bytes);
22 | #endif
23 | }
24 |
25 | std::string JSONBase64::json_decode64(const json_string & encoded) json_nothrow {
26 | #if defined JSON_DEBUG || defined JSON_SAFE
27 | return libbase64::decode(encoded);
28 | #else
29 | return libbase64::decode(encoded);
30 | #endif
31 | }
32 |
33 |
34 | #endif
35 | #endif
36 |
--------------------------------------------------------------------------------
/man/basicJSONHandler.Rd:
--------------------------------------------------------------------------------
1 | \name{basicJSONHandler}
2 | \alias{basicJSONHandler}
3 | \title{Create handler for processing JSON elements from a parser}
4 | \description{
5 | This function creates a handler object that is used to
6 | consume tokens/elements from a JSON parser and combine
7 | them into R objects.
8 |
9 | This is slow relative to using C code because this is done
10 | in R and also we don't know the length of each object until
11 | we have consumed all its elements.
12 | }
13 | \usage{
14 | basicJSONHandler(default.size = 100, simplify = FALSE)
15 | }
16 | \arguments{
17 | \item{default.size}{the best guess as to the sizes of the different elements. This is used
18 | for preallocating space for elements}
19 | \item{simplify}{a logical value indicating whether to simplify arrays
20 | from lists to vectors if the elements are of compatible types.}
21 | }
22 | \value{
23 | \item{update}{a function called with a JSON element and used to process that element and add it to the relevant R object}
24 | \item{value}{a function to retrieve the result after processing the JSON}
25 | }
26 | %\references{}
27 | \author{
28 | Duncan Temple Lang
29 | }
30 |
31 | \seealso{
32 | \code{\link{fromJSON}} and the handler argument.
33 | }
34 | \examples{
35 | h = basicJSONHandler()
36 | x = fromJSON("[1, 2, 3]", h)
37 | x
38 | h$value()
39 | }
40 | \keyword{IO}
41 | \keyword{programming}
42 |
--------------------------------------------------------------------------------
/tests/containers.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 |
3 | roundTrip =
4 | # compare can be all.equal
5 | function(x, y = x, simplify = TRUE, asIs = NA, compare = identical) {
6 | ans <- fromJSON(toJSON(x, asIs = asIs), simplify = simplify)
7 | compare(ans, y)
8 | }
9 |
10 | stopifnot(roundTrip(c(TRUE, FALSE)))
11 | stopifnot(roundTrip(TRUE))
12 | try(stopifnot(roundTrip(1L))) # fails since 1L becomes a numeric
13 | stopifnot(roundTrip(1))
14 | stopifnot(roundTrip("xyz"))
15 |
16 | stopifnot(roundTrip(c(TRUE, FALSE)))
17 | stopifnot(roundTrip(1:2, as.numeric(1:2)))
18 | stopifnot(roundTrip(c(1, 2, 3)))
19 | stopifnot(roundTrip(c("abc", "xyz")))
20 |
21 | # with names
22 | stopifnot(roundTrip(c(a = TRUE)))
23 | stopifnot(roundTrip(c(a = 1)))
24 | stopifnot(roundTrip(c(a = "xyz")))
25 | stopifnot(roundTrip(c(a = 1L), c(a = 1)))
26 |
27 |
28 | # lists
29 |
30 | stopifnot(roundTrip(list(1L), asIs = FALSE, simplify = FALSE, list(1)))
31 |
32 | #
33 | stopifnot(roundTrip(list(1, 2), asIs = FALSE, simplify = FALSE, list(1, 2)))
34 | stopifnot(roundTrip(list(1, 2), asIs = TRUE, simplify = FALSE, list(list(1), list(2))))
35 |
36 | stopifnot(roundTrip(list(a= 1, b = 2), asIs = TRUE, simplify = FALSE, list(a = list(1), b = list(2))))
37 |
38 |
39 | #
40 | tmp = list(a = 1, b = c(1, 2), c = list(1:3, x = c(TRUE, FALSE, FALSE), list(c("a", "b", "c", "d"))))
41 | tmp1 = fromJSON(toJSON(tmp))
42 | all.equal(tmp, tmp1)
43 |
44 | roundTrip(tmp, compare = all.equal)
45 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDebug.cpp:
--------------------------------------------------------------------------------
1 | #include "JSONDebug.h"
2 | #ifdef JSON_DEBUG
3 |
4 | #ifdef JSON_STDERROR
5 | #include //need std::cerr
6 | #else
7 | #include "JSONSingleton.h"
8 | //otherwise, use a callback to tell the end user what happened
9 | json_error_callback_t JSONDebug::register_callback(json_error_callback_t callback) json_nothrow {
10 | json_error_callback_t res = JSONSingleton::get();
11 | JSONSingleton::set(callback);
12 | return res;
13 | }
14 | #endif
15 |
16 | //Something went wrong or an assert failed
17 | void JSONDebug::_JSON_FAIL(const json_string & msg) json_nothrow {
18 | #ifdef JSON_STDERROR //no callback, just use stderror
19 | #ifndef JSON_UNICODE
20 | std::cerr << msg << std::endl;
21 | #else
22 | std::cerr << std::string(msg.begin(), msg.end()) << std::endl;
23 | #endif
24 | #else
25 | if (json_error_callback_t ErrorCallback = JSONSingleton::get()){ //only do anything if the callback is registered
26 | #ifdef JSON_LIBRARY
27 | ErrorCallback(msg.c_str());
28 | #else
29 | ErrorCallback(msg);
30 | #endif
31 | }
32 | #endif
33 | }
34 |
35 | //asserts that condition is true, more useful than cassert because it lets you keep going
36 | void JSONDebug::_JSON_ASSERT(bool condition, const json_string & msg) json_nothrow {
37 | if (json_unlikely(!condition)){
38 | _JSON_FAIL(msg);
39 | }
40 | }
41 | #endif
42 |
43 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONMemoryPool.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBJSON_GUARD_MEMORY_POOL_H
2 | #define LIBJSON_GUARD_MEMORY_POOL_H
3 |
4 | #ifdef JSON_MEMORY_POOL
5 |
6 | #include "../Dependencies/mempool++/mempool.h"
7 |
8 | //this macro expands to the number of bytes a pool gets based on block size and number of 32s of the total pool it gets
9 | #define jsonPoolPart(bytes_per_block, thirty_seconds_of_mem) bytes_per_block, ((thirty_seconds_of_mem * JSON_MEMORY_POOL / 32) / bytes_per_block)
10 |
11 | #ifdef JSON_PREPARSE
12 | #define NODEPOOL jsonPoolPart(sizeof(JSONNode), 1)
13 | #define INTERNALNODEPOOL jsonPoolPart(sizeof(internalJSONNode), 3)
14 | #define MEMPOOL_1 jsonPoolPart(8, 2)
15 | #define MEMPOOL_2 jsonPoolPart(16, 2)
16 | #define MEMPOOL_3 jsonPoolPart(32, 2)
17 | #define MEMPOOL_4 jsonPoolPart(64, 2)
18 | #define MEMPOOL_5 jsonPoolPart(128, 3)
19 | #define MEMPOOL_6 jsonPoolPart(256, 4)
20 | #define MEMPOOL_7 jsonPoolPart(512, 5)
21 | #define MEMPOOL_8 jsonPoolPart(4096, 8)
22 | #else
23 | #define NODEPOOL jsonPoolPart(sizeof(JSONNode), 2)
24 | #define INTERNALNODEPOOL jsonPoolPart(sizeof(internalJSONNode), 7)
25 | #define MEMPOOL_1 jsonPoolPart(8, 1)
26 | #define MEMPOOL_2 jsonPoolPart(16, 1)
27 | #define MEMPOOL_3 jsonPoolPart(32, 1)
28 | #define MEMPOOL_4 jsonPoolPart(64, 1)
29 | #define MEMPOOL_5 jsonPoolPart(128, 3)
30 | #define MEMPOOL_6 jsonPoolPart(256, 3)
31 | #define MEMPOOL_7 jsonPoolPart(512, 5)
32 | #define MEMPOOL_8 jsonPoolPart(4096, 8)
33 | #endif
34 |
35 | #endif
36 |
37 | #endif
38 |
39 |
--------------------------------------------------------------------------------
/R/simpleHandler.R:
--------------------------------------------------------------------------------
1 | simpleJSONHandler =
2 | #
3 | # A handler to read generic JSON content
4 | #
5 | function()
6 | {
7 | stack = NULL
8 | cur = NULL
9 | curKey = character()
10 |
11 | update = function(type, val) {
12 |
13 | if(type == JSON_T_KEY) {
14 | # a key for a hash table.
15 | curKey <<- c(val, curKey)
16 | } else if(type == JSON_T_ARRAY_BEGIN || type == JSON_T_OBJECT_BEGIN) {
17 | stack <<- list(cur, stack)
18 | cur <<- list()
19 | } else if(type == JSON_T_ARRAY_END || type == JSON_T_OBJECT_END) {
20 | obj = if(type == JSON_T_ARRAY_END) condense(cur) else cur
21 | if(type == JSON_T_OBJECT_END) {
22 | i = seq(along = obj)
23 | names(obj) = rev(curKey[i])
24 | curKey <<- curKey[-i]
25 | }
26 |
27 | cur <<- stack[[1]]
28 | if(length(stack) > 1)
29 | stack <<- stack[[2]]
30 |
31 | cur[[ length(cur) + 1 ]] <<- obj
32 | } else if(type > JSON_T_OBJECT_END && type < JSON_T_KEY) {
33 | # The actual atomic values
34 | cur[[length(cur) + 1]] <<- val
35 | }
36 |
37 | TRUE
38 | }
39 |
40 | getValue =
41 | function(simplify = TRUE) {
42 | if(simplify && length(cur) == 1)
43 | cur[[1]]
44 | else
45 | cur
46 | }
47 |
48 | structure(list(update = update,
49 | value = getValue),
50 | class = "JSONParserHandler")
51 | }
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONValidator.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_VALIDATOR_H
2 | #define JSON_VALIDATOR_H
3 |
4 | #include "JSONDebug.h"
5 |
6 | #ifdef JSON_VALIDATE
7 |
8 | #ifdef JSON_SECURITY_MAX_NEST_LEVEL
9 | #define DEPTH_PARAM ,size_t depth_param
10 | #define DEPTH_ARG(arg) ,arg
11 | #define INC_DEPTH()\
12 | if (++depth_param > JSON_SECURITY_MAX_NEST_LEVEL){\
13 | JSON_FAIL(JSON_TEXT("Exceeded JSON_SECURITY_MAX_NEST_LEVEL"));\
14 | return false;\
15 | }
16 | #else
17 | #define DEPTH_PARAM
18 | #define DEPTH_ARG(arg)
19 | #define INC_DEPTH() (void)0
20 | #endif
21 |
22 | class JSONValidator {
23 | public:
24 | static bool isValidNumber(const json_char * & ptr) json_nothrow json_read_priority;
25 | static bool isValidMember(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
26 | static bool isValidString(const json_char * & ptr) json_nothrow json_read_priority;
27 | static bool isValidNamedObject(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
28 | static bool isValidObject(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
29 | static bool isValidArray(const json_char * & ptr DEPTH_PARAM) json_nothrow json_read_priority;
30 | static bool isValidRoot(const json_char * json) json_nothrow json_read_priority;
31 | #ifdef JSON_STREAM
32 | static bool isValidPartialRoot(const json_char * json) json_nothrow json_read_priority;
33 | #endif
34 | private:
35 | JSONValidator(void);
36 | };
37 |
38 | #endif
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/src/libjson/License.txt:
--------------------------------------------------------------------------------
1 | This license is also available in Documentation.pdf
2 |
3 | Copyright 2010 Jonathan Wallace. All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10 |
11 | THIS SOFTWARE IS PROVIDED BY JONATHAN WALLACE ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JONATHAN WALLACE OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 |
13 | The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Jonathan Wallace.
--------------------------------------------------------------------------------
/man/isValidJSON.Rd:
--------------------------------------------------------------------------------
1 | \name{isValidJSON}
2 | \alias{isValidJSON}
3 | \alias{isValidJSON,AsIs-method}
4 | \alias{isValidJSON,character-method}
5 | \alias{isValidJSON,connection-method}
6 | \title{Test if JSON content is valid}
7 | \description{
8 | This function and its methods allows the caller to verify if the
9 | JSON content is strictly valid. Even if the content is invalid,
10 | the parser may still be able to make sense of it or at least
11 | get it partially correct and yield a result.
12 | So this function allows the caller to verify that the input is
13 | legitimate and not just rely on the parser not failing.
14 | }
15 | \usage{
16 | isValidJSON(content, asText = inherits(content, "AsIs"), ...)
17 | }
18 | %- maybe also 'usage' for other objects documented here.
19 | \arguments{
20 | \item{content}{the JSON input either as a string, the name of a file
21 | or URL, or a connection object.}
22 | \item{asText}{a logical value that specifies whether the value in
23 | \code{content} is actually the JSON content or the name of a file}
24 | \item{\dots}{additional parameters for the methods}
25 | }
26 | \value{
27 | A logical value indicating whether the content is valid JSON
28 | (\code{TRUE}) or invalid (\code{FALSE}).
29 | }
30 | \references{
31 | libjson
32 | }
33 | \author{
34 | Duncan Temple Lang.
35 | Functionality suggested by Jeroen Ooms.
36 | }
37 |
38 | \seealso{
39 | \code{\link{fromJSON}}
40 | }
41 | \examples{
42 | isValidJSON(I('{"foo" : "bar"}'))
43 |
44 | isValidJSON(I('{foo : "bar"}'))
45 | isValidJSON('{foo : "bar"}', TRUE)
46 | }
47 | \keyword{programming}
48 | \keyword{IO}
49 |
50 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDebug.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBJSON_GUARD_DEBUG_H
2 | #define LIBJSON_GUARD_DEBUG_H
3 |
4 | #include "JSONDefs.h"
5 | #include "JSONStats.h"
6 |
7 | #ifdef JSON_DEBUG
8 | #ifdef JSON_SAFE
9 | #define JSON_ASSERT_SAFE(condition, msg, code)\
10 | {\
11 | if (json_unlikely(!(condition))){\
12 | JSON_FAIL(msg);\
13 | code\
14 | }\
15 | }
16 | #define JSON_FAIL_SAFE(msg, code)\
17 | {\
18 | JSON_FAIL(msg);\
19 | code\
20 | }
21 | #else
22 | #define JSON_ASSERT_SAFE(condition, msg, code) JSON_ASSERT(condition, msg)
23 | #define JSON_FAIL_SAFE(msg, code) JSON_FAIL(msg)
24 | #endif
25 |
26 | #define JSON_FAIL(msg) JSONDebug::_JSON_FAIL(msg)
27 | #define JSON_ASSERT(bo, msg) JSONDebug::_JSON_ASSERT(bo, msg)
28 |
29 | class JSONDebug {
30 | public:
31 | #ifndef JSON_STDERROR
32 | static json_error_callback_t register_callback(json_error_callback_t callback) json_nothrow json_cold;
33 | #endif
34 | static void _JSON_FAIL(const json_string & msg) json_nothrow json_cold;
35 | static void _JSON_ASSERT(bool condition, const json_string & msg) json_nothrow json_cold;
36 | };
37 | #else
38 | #ifdef JSON_SAFE
39 | #define JSON_ASSERT_SAFE(condition, msg, code)\
40 | {\
41 | if (json_unlikely(!(condition))){\
42 | code\
43 | }\
44 | }
45 | #define JSON_FAIL_SAFE(msg, code)\
46 | {\
47 | code\
48 | }
49 | #else
50 | #define JSON_ASSERT_SAFE(condition, msg, code)
51 | #define JSON_FAIL_SAFE(msg, code)
52 | #endif
53 |
54 | #define JSON_ASSERT(condition, msg)
55 | #define JSON_FAIL(msg)
56 | #endif
57 |
58 | #endif
59 |
60 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: RJSONIO
2 | Version: 1.3-2
3 | Title: Serialize R objects to JSON, JavaScript Object Notation
4 | Description: This is a package that allows conversion to and from
5 | data in Javascript object notation (JSON) format.
6 | This allows R objects to be inserted into Javascript/ECMAScript/ActionScript code
7 | and allows R programmers to read and convert JSON content to R objects.
8 | This is an alternative to rjson package. Originally, that was too slow for converting large R objects to JSON
9 | and was not extensible. rjson's performance is now similar to this package, and perhaps slightly faster in some cases.
10 | This package uses methods and is readily extensible by defining methods for different classes,
11 | vectorized operations, and C code and callbacks to R functions for deserializing JSON objects to R.
12 | The two packages intentionally share the same basic interface. This package (RJSONIO) has many additional
13 | options to allow customizing the generation and processing of JSON content.
14 | This package uses libjson rather than implementing yet another JSON parser. The aim is to support
15 | other general projects by building on their work, providing feedback and benefit from their ongoing development.
16 | Note: The C code for parsing JSON comes from www.json.org and is licensed under essentially the BSD license.
17 | See the notice in src/JSON_parser.c
18 | The libjson code is on sourceforge.net, but does not yet have a license.
19 | libjson was written and is maintained and developed by Johnathan Wallace.
20 | Note: See http://www.json.org/JSON_checker/test.zip for tests.
21 | We now use code from the libjson project (http://libjson.sourceforge.net).
22 | License: BSD_3_clause + file LICENSE
23 | Imports: methods
24 | Author: Duncan Temple Lang
25 | Maintainer: Duncan Temple Lang
26 | Collate: readJSON.R asVars.R isValid.R json.R simpleHandler.R stream.R
27 | Biarch: true
28 |
29 |
30 |
--------------------------------------------------------------------------------
/R/asVars.R:
--------------------------------------------------------------------------------
1 | asJSVars =
2 | #
3 | # For action script, we often want to declare the variables
4 | # as public/protected and also to put the variables
5 | #
6 | function(..., .vars = list(...),
7 | qualifier = character(), types = character())
8 | {
9 | # Add in suitable indentation
10 | vals = paste(sapply(.vars, toJSON), ";")
11 |
12 | if(length(types)) {
13 | if(is.logical(types))
14 | if(types)
15 | types = sapply(.vars, jsType)
16 | else # Should never happen. Caller should leave the default!
17 | types = character()
18 |
19 | if(length(types))
20 | ids = paste(names(.vars), types, sep = " : ")
21 | else
22 | ids = names(.vars)
23 | } else
24 | ids = names(.vars)
25 |
26 | if(length(qualifier))
27 | ids = paste(qualifier, ids)
28 |
29 | # Indent the object initialization with the number of characters involved in the
30 | # variable declaration.
31 | len = nchar(ids)
32 | vals = sapply(seq(along = ids),
33 | function(i) {
34 | gsub("\\\n", paste("\\\n", paste(rep(" ", len[i] + 3), collapse = ""), sep = ""), vals[i])
35 | })
36 |
37 | invisible(paste(ids, vals, sep = " = ", collapse = "\n\n"))
38 | }
39 |
40 | setGeneric("jsType", function(x, ...) standardGeneric("jsType"))
41 |
42 | setMethod("jsType", "matrix",
43 | function(x){
44 | "Array"
45 | })
46 |
47 | jsTypes = c("integer" = "int",
48 | "numeric" = "Number",
49 | "logical" = "Boolean",
50 | "character" = "String"
51 | )
52 |
53 | setMethod("jsType", "vector",
54 | function(x){
55 | if(length(x) == 1 && is.atomic(x) && length(names(x)) == 0) {
56 | jsTypes[typeof(x)]
57 | } else {
58 | if(length(names(x)))
59 | "Object"
60 | else
61 | "Array"
62 | }
63 | })
64 |
65 |
--------------------------------------------------------------------------------
/man/asJSVars.Rd:
--------------------------------------------------------------------------------
1 | \name{asJSVars}
2 | \alias{asJSVars}
3 | \title{Serialize R objects as Javsscript/ActionScript variables}
4 | \description{
5 | This function takes R objects and serializes them as
6 | Javascript/ActionScript values.
7 | It uses the specified names in the R call as
8 | Javascript variable names. One can also specify
9 | qualifiers (\sQuote{public}, \sQuote{protected}, \sQuote{private})
10 | and also types. These are optional, but useful, in ActionScript.
11 | }
12 | \usage{
13 | asJSVars(..., .vars = list(...), qualifier = character(), types = character())
14 | }
15 | %- maybe also 'usage' for other objects documented here.
16 | \arguments{
17 | \item{\dots}{\code{name = value} pairs where the \code{value} is an R object
18 | that is converted to JSON format and \code{name} is the name of the corresponding
19 | Javascript variable.}
20 | \item{.vars}{this is an alternative to \dots as a way to specify a collection of
21 | \code{name = value} pairs that is already in a list.}
22 | \item{qualifier}{a character vector (recycled as necessary) which is
23 | used as qualifiers for the individual ActionScript variables.
24 | The values should be public, protected or private.
25 | }
26 | \item{types}{either a logical value or a character vector (which is
27 | recycled if necessary). If this is \code{TRUE}, then we compute the
28 | Javascript type for each of the R objects (using the non-exported
29 | function \code{jsType})}
30 | }
31 | \value{
32 | A character vector of length 1 giving the variable declarations and
33 | initializations.
34 | }
35 | \author{Duncan Temple Lang }
36 |
37 | \seealso{
38 | \code{\link{toJSON}}
39 | }
40 | \examples{
41 | cat(asJSVars( a = 1:10, myMatrix = matrix(1:15, 3, 5)))
42 | cat(asJSVars( a = 1:10, myMatrix = matrix(1:15, 3, 5), types = TRUE))
43 | cat(asJSVars( a = 1:10, myMatrix = matrix(1:15, 3, 5),
44 | qualifier = "protected", types = TRUE))
45 | }
46 | \keyword{IO}
47 | \keyword{programming}
48 |
49 |
--------------------------------------------------------------------------------
/tests/stringFun.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO)
2 | jtxt = '[ 1, "abc", "xyz"]'
3 | jdate = '[ 1, "/Date(1335746208)/", "xyz"]'
4 | jnewdate = '[ 1, "/new Date(1335746208)/", "xyz"]'
5 |
6 |
7 |
8 | a = fromJSON(jtxt, stringFun = I(getNativeSymbolInfo("dummyStringOperation")$address))
9 | b = fromJSON(jtxt, stringFun = I(getNativeSymbolInfo("dummyStringOperation")))
10 | c = fromJSON(jtxt, stringFun = I("dummyStringOperation"))
11 | d = fromJSON(jtxt, stringFun = structure("dummyStringOperation", class = "NativeStringRoutine"))
12 |
13 | e = fromJSON(jtxt, stringFun = I("dummyStringOperation"), simplify = TRUE)
14 |
15 |
16 | ans = fromJSON(jtxt, stringFun = structure("R_json_dateStringOp", class = "SEXPRoutine"))
17 | sapply(ans, class) == c("numeric", "character", "character")
18 | ans = fromJSON(jtxt, stringFun = "R_json_dateStringOp")
19 |
20 | ans = fromJSON(jtxt, stringFun = structure("R_json_dateStringOp", class = "SEXPRoutine"), simplify = TRUE)
21 |
22 | # process jdate
23 | ans = fromJSON(jdate, stringFun = structure("R_json_dateStringOp", class = "SEXPRoutine"))
24 | ans = fromJSON(jdate, stringFun = "R_json_dateStringOp")
25 |
26 |
27 | # process strings by just returning them.
28 | fromJSON(jtxt, stringFun = function(val) val)
29 |
30 | # process strings by prefixing them with xxx_
31 | fromJSON(jtxt, stringFun = function(val) sprintf("xxx_%s", val))
32 |
33 | jtxt = '[ "1", "2.3", "3.1415"]' # all numeric but in ""
34 | ans = fromJSON(jtxt)
35 | stopifnot(is.character(ans))
36 |
37 | # convert all of the strings to numeric!
38 | ans = fromJSON(jtxt, stringFun = function(val) as.numeric(val))
39 | stopifnot(is.numeric(ans))
40 |
41 | # Now convert them all to TRUE as logicals
42 | ans = fromJSON(jtxt, stringFun = function(val) TRUE)
43 | stopifnot(is.logical(ans))
44 |
45 |
46 | #
47 | jtxt = '[ 1, "/new Date(12312313)", "/Date(12312313)"]'
48 | ans = fromJSON(jtxt)
49 |
50 | ans = fromJSON(jtxt, stringFun = "R_json_dateStringOp", simplify = FALSE)
51 | stopifnot(all(mapply(is, ans, c("numeric", "POSIXct", "POSIXct"))))
52 |
53 |
54 |
--------------------------------------------------------------------------------
/inst/doc/performance.R:
--------------------------------------------------------------------------------
1 | n = seq(1000, 100000, by = 5000)
2 | new.times = sapply(n, function(n) system.time(invisible(toJSON(rpois(n, 4)))))
3 |
4 | library(rjson)
5 | new.times = sapply(n, function(n) system.time(invisible(toJSON(rpois(n, 4)))))
6 |
7 | ###################
8 |
9 | json = sapply(n, function(n) toJSON(rpois(n, 2)))
10 | fromJSON.new.times = sapply(json, function(v) system.time(fromJSON(v, asText = TRUE)))
11 |
12 | fromJSON.new.times.10000 = sapply(json, function(v) system.time(fromJSON(v, default.size = 10000, asText = TRUE)))
13 |
14 |
15 | library(rjson)
16 | fromJSON.old.times = sapply(json, function(v) system.time(fromJSON(v)))
17 |
18 | colnames(fromJSON.old.times) = colnames(fromJSON.new.times) = n
19 | save(fromJSON.new.times, fromJSON.new.times.10000, fromJSON.old.times, n, file = "inst/doc/fromJSONTimes.rda")
20 |
21 |
22 | ###############################
23 |
24 | n = seq(1000, by = 1000, 10000)
25 | v = sapply(n, function(n) toJSON(rpois(n, 4)))
26 |
27 | a = sapply(v, function(x) system.time(fromJSON(x)), USE.NAMES = FALSE)
28 |
29 | b = sapply(v, function(x) system.time(fromJSON(x, RJSONIO:::simpleJSONHandler())), USE.NAMES = FALSE)
30 |
31 | f = get("fromJSON", "package:rjson")
32 |
33 | c = sapply(v, function(x) system.time(f(x)), USE.NAMES = FALSE)
34 |
35 | d = sapply(v, function(x) {
36 | system.time({
37 | buf = rep(as.integer(NA), 100000)
38 | fromJSON(v,getNativeSymbolInfo("R_json_IntegerArrayCallback", PACKAGE = "RJSONIO"),
39 | data = buf)
40 | buf[!is.na(buf)]
41 | })
42 | }, USE.NAMES = FALSE)
43 |
44 | matplot(n, cbind(a[3,], b[3,], c[3,], d[3,]), type = "l")
45 |
46 | D = data.frame(n = rep(n, 4),
47 | elapsed = c(a[3,], b[3,], c[3,], d[3,]),
48 | type = rep(c("default", "simple", "rjson", "C"), each = ncol(a)))
49 |
50 | xyplot(elapsed ~ n, D, group = type, type = "l", auto.key = list(columns = length(levels(D$type))))
51 |
52 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDefs/GNU_C.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_GNU_C_HEADER
2 | #define JSON_GNU_C_HEADER
3 |
4 | #ifdef __GNUC__
5 |
6 | #define json_deprecated(method, warning) method __attribute__((deprecated))
7 |
8 | #if (__GNUC__ >= 3)
9 | #define JSON_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
10 | #else
11 | #define JSON_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
12 | #endif
13 |
14 | #if (JSON_GCC_VERSION >= 40300)
15 | #define json_hot __attribute__ ((hot))
16 | #define json_cold __attribute__ ((cold))
17 | #define json_pure json_nothrow __attribute__ ((pure, hot))
18 | #define json_malloc_attr json_nothrow __attribute__ ((malloc, hot))
19 |
20 | /* Can do priorities */
21 | #if (JSON_WRITE_PRIORITY == HIGH)
22 | #define json_write_priority __attribute__ ((hot))
23 | #elif (JSON_WRITE_PRIORITY == LOW)
24 | #define json_write_priority __attribute__ ((cold))
25 | #else
26 | #define json_write_priority
27 | #endif
28 |
29 | #if (JSON_READ_PRIORITY == HIGH)
30 | #define json_read_priority __attribute__ ((hot))
31 | #elif (JSON_READ_PRIORITY == LOW)
32 | #define json_read_priority __attribute__ ((cold))
33 | #else
34 | #define json_read_priority
35 | #endif
36 |
37 | #define json_likely(x) __builtin_expect((long)((bool)(x)),1)
38 | #define json_unlikely(x) __builtin_expect((long)((bool)(x)),0)
39 | #else
40 | #if (JSON_GCC_VERSION >= 29600)
41 | #define json_pure json_nothrow __attribute__ ((pure))
42 | #define json_likely(x) __builtin_expect((long)((bool)(x)),1)
43 | #define json_unlikely(x) __builtin_expect((long)((bool)(x)),0)
44 | #else
45 | #define json_pure json_nothrow
46 | #define json_likely(x) x
47 | #define json_unlikely(x) x
48 | #endif
49 |
50 | #define json_malloc_attr json_nothrow __attribute__ ((malloc))
51 | #define json_write_priority
52 | #define json_read_priority
53 | #define json_hot
54 | #define json_cold
55 | #endif
56 |
57 | #define json_nothrow throw()
58 | #define json_throws(x) throw(x)
59 |
60 | #ifdef JSON_LESS_MEMORY
61 | #define PACKED(x) :x __attribute__ ((packed))
62 | #define BITS(x) :x
63 | #endif
64 |
65 | #endif
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/Web/index.html.in:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @PKG_NAME@
5 |
6 |
7 |
8 | The @PKG_NAME@ Package
9 | Last Release:
10 | @VERSION@ (@DATE@ )
11 |
12 |
13 | This package provides facilities for reading and writing
14 | data in JSON - Javascript Object
15 | Notation - format.
16 | This allows us to read data in this format, e.g. from Web service
17 | applications,
18 | and also to export objects from R for use in
19 | Javascript/ECMAScript/ActionScript code.
20 | This is useful when generating dynamic plots with SVG (Scalable Vector
21 | Graphics), or Flash and ActionScript.
22 |
23 |
24 |
25 |
26 | The primary functions in the package are
27 |
28 | fromJSON
29 | toJSON
30 | asJSVars
31 |
32 |
33 |
34 |
35 | The package is extensible, allowing others to
36 | define S4 methods for toJSON
37 | for different R classes/types.
38 | Similarly, the fromJSON function allows
39 | the caller to specify a different callback handler
40 | which is invoked each time an element (e.g. number,
41 | string, key, start or end of an array or object) is found
42 | in the JSON content.
43 |
44 |
45 | This package was motivated by the need to export R objects for use
46 | in creating dynamic graphics for the Web via SVG and Flash/FLEX.
47 | Since then, JSON has become a prominent format with many uses.
48 | Alex Couture-Beil's rjson
50 | package is another mechanism in R for reading and writing JSON
51 | content. However, that does not use S4/S3 methods and so is not
52 | readily extensible, but still useful.
53 |
54 |
55 | Documentation
56 |
57 |
61 |
62 |
63 |
64 |
65 | Duncan Temple Lang
66 | <duncan@r-project.org>
67 |
68 | Last modified: Mon May 19 09:26:38 PDT 2014
69 |
70 |
71 |
--------------------------------------------------------------------------------
/streaming.R:
--------------------------------------------------------------------------------
1 | library(RJSONIO); f= "inst/sampleData/web.json"; .Call("R_json_parser_test_stream", f)
2 |
3 | library(RJSONIO); f= "inst/sampleData/web.json"; .Call("R_json_parser_test_stream_str", '[1,2, 3]{"a": [true, false]}')
4 |
5 | library(RJSONIO); f= "inst/sampleData/web.json"; .Call("R_json_parser_test_stream_str", paste(readLines("inst/sampleData/web.json"), collapse = "\n"))
6 |
7 |
8 | library(RJSONIO)
9 | val = list(a = 1:100, b = 100:1, c = rnorm(1000))
10 | xx = toJSON(val, digits = 16)
11 | ans = .Call("R_json_parser_test_stream_str", xx)
12 |
13 | # in chunks
14 | ans = .Call("R_json_parser_test_stream_chunk", xx)
15 | all.equal(val, ans)
16 |
17 | z = replicate(400, {ans = .Call("R_json_parser_test_stream_chunk", xx); all.equal(val, ans)})
18 |
19 |
20 |
21 |
22 | library(RJSONIO)
23 | val = list(a = 1:100, b = 100:1, c = rnorm(1000))
24 | xx = toJSON(val, digits = 16)
25 |
26 | con = textConnection(xx)
27 | getData = function() readLines(con, n = 1)
28 |
29 | ans = .Call("R_json_parser_test_stream_chunk_con", quote(getData()))
30 | all.equal(ans, val)
31 |
32 |
33 |
34 |
35 | library(RJSONIO)
36 | val = list(a = 1:100, b = 100:1, c = rnorm(1000))
37 | xx = toJSON(val, digits = 16)
38 |
39 | con = textConnection(xx)
40 | e = substitute(readLines(con, n = 1), list(con = con))
41 |
42 | ans = .Call("R_json_parser_test_stream_chunk_con", e)
43 | all.equal(ans, val)
44 |
45 |
46 | ####################
47 |
48 | library(RJSONIO)
49 | val = list(a = 1:100, b = 100:1, c = rnorm(1000))
50 | xx = toJSON(val, digits = 16)
51 |
52 | z = replicate(40, {
53 | con = textConnection(xx)
54 | e = substitute(readLines(con, n = 1), list(con = con))
55 | ans = .Call("R_json_parser_init_from_con", e, NULL, 14L, NULL, TRUE)
56 | all.equal(ans, val)
57 | })
58 |
59 | table(z)
60 |
61 | # With a callback
62 | library(RJSONIO)
63 | val = list(a = 1:100, b = 100:1, c = rnorm(1000))
64 | xx = toJSON(val, digits = 16)
65 |
66 | con = textConnection(xx)
67 | e = substitute(readLines(con, n = 1), list(con = con))
68 |
69 | f = function(x)
70 | print(x)
71 |
72 | ans = .Call("R_json_parser_init_from_con", e, f, 14L, NULL, TRUE)
73 | all.equal(ans, val)
74 |
75 |
76 | library(RJSONIO)
77 | xx = '[1,2, 3]{"a": [true, false]}'
78 | con = textConnection(xx)
79 | e = substitute(readLines(con, n = 1), list(con = con))
80 |
81 | f = function(x)
82 | print(sum(unlist(x)))
83 |
84 | ans = .Call("R_json_parser_init_from_con", e, f)
85 |
86 |
--------------------------------------------------------------------------------
/tests/performance.R:
--------------------------------------------------------------------------------
1 | if(FALSE) { # This works but takes a lot of time. So leave this out
2 | # for default runs.
3 | library(RJSONIO)
4 |
5 | v = rpois(100000, 4)
6 | x = toJSON(v)
7 |
8 | # 0.054 seconds
9 | system.time({ val = fromJSON(x, getNativeSymbolInfo("R_json_IntegerArrayCallback"),
10 | data = rep(as.integer(NA), 100000))})
11 |
12 | all(v == val)
13 |
14 | # 89.981 So a factor of 1666
15 | system.time({v1 = fromJSON(x)})
16 |
17 |
18 | # Now if we preallocate a vector with the size of the result
19 | # and fill it with an R callback, we get 1.050.
20 | # This is a factor of 20 relative to the specialized C code.
21 | gen =
22 | function(n = 100000, ans = integer(n))
23 | {
24 | pos = 1
25 | update =
26 | function(type, val) {
27 | if(type == JSON_T_INTEGER) {
28 | ans[pos] <<- val
29 | pos <<- pos + 1
30 | }
31 | TRUE
32 | }
33 | list(update = update, value = function() ans)
34 | }
35 | h = gen()
36 | system.time({v1 = fromJSON(x, h$update)})
37 |
38 |
39 | # Now let's use the generic list
40 | # We get 1.130
41 |
42 | gen.list =
43 | function(n = 100000, ans = vector("list", n))
44 | {
45 | pos = 1
46 | update =
47 | function(type, val) {
48 | if(type == JSON_T_INTEGER) {
49 | ans[pos] <<- val
50 | pos <<- pos + 1
51 | }
52 | TRUE
53 | }
54 | structure(list(update = update, value = function() unlist(ans[1:pos])),
55 | class = "JSONParserHandler")
56 | }
57 | h = gen.list()
58 | system.time({v1 = fromJSON(x, h)})
59 |
60 |
61 | #
62 | gen.list =
63 | function(n = 100000, ans = vector("list", n))
64 | {
65 | pos = 1
66 | update =
67 | function(type, val) {
68 | if(type == JSON_T_INTEGER) {
69 | if(length(ans) == pos)
70 | length(ans) <<- 2*pos
71 | ans[pos] <<- val
72 | pos <<- pos + 1
73 | }
74 | TRUE
75 | }
76 | structure(list(update = update, value = function() unlist(ans[1:pos])),
77 | class = "JSONParserHandler")
78 | }
79 | h = gen.list()
80 | system.time({v1 = fromJSON(x, h)})
81 |
82 |
83 |
84 | ############################################
85 |
86 | v = rpois(100000, 4)
87 | x = toJSON(v)
88 |
89 | h = RJSONIO:::simpleJSONHandler()
90 | system.time({a = fromJSON(x, h)})
91 | # user system elapsed
92 | # 59.470 21.693 91.442
93 | system.time({a = fromJSON(x)})
94 | # user system elapsed
95 | # 3.899 0.117 4.415
96 | system.time({a = fromJSON(x, default.size = 10000)})
97 | # user system elapsed
98 | # 3.957 0.116 4.465
99 | system.time({a = fromJSON(x, default.size = 100000)})
100 | }
101 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONAllocator.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_ALLOCATOR_H
2 | #define JSON_ALLOCATOR_H
3 |
4 | #include "JSONStats.h"
5 | #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
6 |
7 | #include
8 |
9 | //need these for the json_nothrow
10 | #include "JSONDefs/Visual_C.h"
11 | #include "JSONDefs/GNU_C.h"
12 | #include "JSONDefs/Unknown_C.h"
13 |
14 | class JSONAllocatorRelayer {
15 | public:
16 | static void * alloc(size_t bytes) json_nothrow json_hot;
17 | static void dealloc(void * ptr) json_nothrow json_hot;
18 | };
19 |
20 | template class json_allocator;
21 |
22 | // specialize for void:
23 | template <> class json_allocator {
24 | public:
25 | typedef void* pointer;
26 | typedef const void* const_pointer;
27 | // reference to void members are impossible.
28 | typedef void value_type;
29 | template struct rebind { typedef json_allocator other; };
30 | };
31 |
32 | template class json_allocator {
33 | public:
34 | typedef size_t size_type;
35 | typedef ptrdiff_t difference_type;
36 | typedef T* pointer;
37 | typedef const T* const_pointer;
38 | typedef T& reference;
39 | typedef const T& const_reference;
40 | typedef T value_type;
41 | template struct rebind { typedef json_allocator other; };
42 |
43 | //LIBJSON_OBJECT(json_allocator);
44 |
45 | inline json_allocator() json_nothrow {
46 | //LIBJSON_CTOR;
47 | }
48 | inline json_allocator(const json_allocator&) json_nothrow {
49 | //LIBJSON_COPY_CTOR;
50 | }
51 | template inline json_allocator(const json_allocator&) json_nothrow {
52 | //LIBJSON_COPY_CTOR;
53 | }
54 | inline ~json_allocator() json_nothrow {
55 | //LIBJSON_DTOR;
56 | }
57 |
58 | inline pointer address(reference x) const { return &x; }
59 | inline const_pointer address(const_reference x) const { return &x; }
60 |
61 | inline pointer allocate(size_type n, json_allocator::const_pointer = 0) json_hot {
62 | return (pointer)JSONAllocatorRelayer::alloc(n * sizeof(T));
63 | }
64 | inline void deallocate(pointer p, size_type) json_hot {
65 | JSONAllocatorRelayer::dealloc(p);
66 | }
67 |
68 | inline size_type max_size() const json_nothrow { return 0xEFFFFFFF; }
69 |
70 | inline void construct(pointer p, const T& val){
71 | new(p)T(val);
72 | };
73 | inline void destroy(pointer p){
74 | ((T*)p) -> ~T();
75 | }
76 | };
77 |
78 | template inline bool operator==(const json_allocator&, const json_allocator&) json_nothrow { return true; }
79 | template inline bool operator!=(const json_allocator&, const json_allocator&) json_nothrow { return false; }
80 |
81 | #endif
82 | #endif
83 |
--------------------------------------------------------------------------------
/man/readJSONStream.Rd:
--------------------------------------------------------------------------------
1 | \name{readJSONStream}
2 | \alias{readJSONStream}
3 | \title{Read JSON from a Connection/Stream}
4 | \description{
5 | This function is capable of reading and processing
6 | JSON content from a "stream". This is most likely
7 | to be from an R connection, but can be an arbitrary
8 | source of JSON content.
9 | The idea is that the parser will pull partial data from the
10 | source and process it immediately, and then return to
11 | retrieve more data. This allows the parser to work on
12 | the JSON content without it all being in memory at one
13 | time. This can save a significant amount of memory
14 | and make some computations feasible which would not
15 | be if we had to first read all of the JSON and then
16 | process it.
17 | }
18 | \usage{
19 | readJSONStream(con, cb = NULL, simplify = Strict, nullValue = NULL,
20 | simplifyWithNames = TRUE)
21 | }
22 | \arguments{
23 | \item{con}{a connection object from which we will read the JSON
24 | content. This can also be any R expression that returns
25 | a string. This allows a caller to get content from any source,
26 | not just a connection.
27 | }
28 | \item{cb}{
29 | an optional callback function that is invoked
30 | for each top-level JSON object in the stream. Typically there
31 | will only be one such top-level object and so the callback
32 | is not really needed as the default is to return that top-level
33 | object from \code{readJSONStream}.
34 | However, if there are multiple top-level JSON objects in the stream,
35 | this callback function can process them, e.g. merge them, collapse
36 | the contents.
37 | }
38 | \item{simplify}{same as for \code{\link{fromJSON}}.}
39 | \item{nullValue}{same as for \code{\link{fromJSON}}.}
40 | \item{simplifyWithNames}{same as for \code{\link{fromJSON}}.}
41 | }
42 | \value{
43 | By default, this returns the top-level JSON object in the stream.
44 | }
45 | \references{
46 | libjson and the \code{JSONSTREAM} facilities.
47 | }
48 | \author{Duncan Temple Lang}
49 |
50 | \seealso{
51 | \code{\link{fromJSON}} and its methods,
52 | specifically the method for a connection.
53 | }
54 | \examples{
55 | \dontrun{
56 | xx = '[1,2, 3]{"a": [true, false]}'
57 | con = textConnection(xx)
58 |
59 | f = function(x)
60 | print(sum(unlist(x)))
61 |
62 | readJSONStream(con, f)
63 |
64 | # The callback function can be anonymous
65 | con = textConnection(xx)
66 | readJSONStream(con, function(x)
67 | print(sum(unlist(x))))
68 |
69 |
70 |
71 | gen =
72 | function() {
73 | ans <- 0
74 | list(update = function(x) ans <<- ans + sum(unlist(x)),
75 | value = function() ans)
76 | }
77 | g = gen()
78 | con = textConnection(xx)
79 | readJSONStream(con, g$update)
80 | }
81 | }
82 | \keyword{IO}
83 |
84 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONStream.h:
--------------------------------------------------------------------------------
1 | #ifndef LIBJSON_GUARD_STREAM_H
2 | #define LIBJSON_GUARD_STREAM_H
3 |
4 | #include "JSONDebug.h"
5 |
6 | #ifdef JSON_STREAM
7 |
8 | #ifdef JSON_LESS_MEMORY
9 | #ifdef __GNUC__
10 | #pragma pack(push, 1)
11 | #elif _MSC_VER
12 | #pragma pack(push, JSONStream_pack, 1)
13 | #endif
14 | #endif
15 |
16 | #ifdef JSON_MEMORY_CALLBACKS
17 | #include "JSONMemory.h"
18 | #endif
19 |
20 | #ifndef JSON_LIBRARY
21 | class JSONNode; //foreward declaration
22 | typedef void (*json_stream_callback_t)(JSONNode &, void *);
23 | #endif
24 |
25 | class JSONStream {
26 | public:
27 | LIBJSON_OBJECT(JSONStream);
28 | JSONStream(json_stream_callback_t call_p, json_stream_e_callback_t call_e = NULL, void * callbackIdentifier = JSONSTREAM_SELF) json_nothrow;
29 | JSONStream(const JSONStream & orig) json_nothrow;
30 | JSONStream & operator =(const JSONStream & orig) json_nothrow;
31 | ~JSONStream(void) json_nothrow { LIBJSON_DTOR; }
32 | #ifdef JSON_LIBRARY
33 | JSONStream & operator << (const json_char * str) json_nothrow;
34 | #else
35 | JSONStream & operator << (const json_string & str) json_nothrow;
36 | #endif
37 |
38 | static void deleteJSONStream(JSONStream * stream) json_nothrow {
39 | #ifdef JSON_MEMORY_CALLBACKS
40 | stream -> ~JSONStream();
41 | libjson_free(stream);
42 | #else
43 | delete stream;
44 | #endif
45 | }
46 |
47 | static JSONStream * newJSONStream(json_stream_callback_t callback, json_stream_e_callback_t call_e, void * callbackIdentifier) json_nothrow {
48 | #ifdef JSON_MEMORY_CALLBACKS
49 | return new(json_malloc(1)) JSONStream(callback, call_e, callbackIdentifier);
50 | #else
51 | return new JSONStream(callback, call_e, callbackIdentifier);
52 | #endif
53 | }
54 |
55 | inline void reset() json_nothrow {
56 | state = true;
57 | buffer.clear();
58 | }
59 | JSON_PRIVATE
60 | inline void * getIdentifier(void) json_nothrow {
61 | if (callback_identifier == JSONSTREAM_SELF){
62 | return (void*)this;
63 | }
64 | return callback_identifier;
65 | }
66 |
67 | #if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
68 | template
69 | static size_t FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
70 | #else
71 | static size_t FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
72 | #endif
73 |
74 | void parse(void) json_nothrow;
75 | json_string buffer;
76 | json_stream_callback_t call;
77 | json_stream_e_callback_t err_call;
78 | void * callback_identifier;
79 | bool state BITS(1);
80 | };
81 |
82 | #ifdef JSON_LESS_MEMORY
83 | #ifdef __GNUC__
84 | #pragma pack(pop)
85 | #elif _MSC_VER
86 | #pragma pack(pop, JSONStream_pack)
87 | #endif
88 | #endif
89 |
90 | #endif
91 |
92 | #endif
93 |
94 |
--------------------------------------------------------------------------------
/configure.in:
--------------------------------------------------------------------------------
1 | AC_INIT(src/rlibjson.c)
2 |
3 | AC_ARG_WITH(local-libjson, [use the libjson code that comes with this package rather than
4 | looking for an installed version on the system],
5 | USE_LOCAL=$withval)
6 |
7 | AC_ARG_WITH(prefix, [the name of the directory into which the libjson include files and library were installed],
8 | [ LIBJSON_PREFIX=$withval; if test -z "$USE_LOCAL" ; then USE_LOCAL="never" ; fi],
9 | [ LIBJSON_PREFIX="/usr/local" ;
10 | ])
11 |
12 | ORIG_USE_LOCAL="$USE_LOCAL"
13 |
14 | if test -z "$USE_LOCAL" || test "$USE_LOCAL" = "no" ; then
15 | echo "Trying to find libjson.h header file"
16 | CPPFLAGS="$CPPFLAGS -I$LIBJSON_PREFIX/include"
17 | AC_TRY_COMPILE(
18 | [#include ],
19 | [JSONNODE *ptr = json_parse("[1, 3]");],
20 | [USE_LOCAL=1; echo "Found system libjson header file libjson.h"], []
21 | )
22 |
23 |
24 | if test -n "$USE_LOCAL" && ! test "$USE_LOCAL" = "no"; then
25 | echo "Trying to link against libjson"
26 | LIBS="$LIBS -L$LIBJSON_PREFIX/lib -ljson"
27 | AC_TRY_LINK(
28 | [#include ],
29 | [JSONNODE *ptr = json_parse("[1, 3]");],
30 | [USE_LOCAL=1; echo "linked against libjson"],
31 | [USE_LOCAL=""; echo "Failed to link against system libjson"]
32 | )
33 | fi
34 |
35 | fi
36 |
37 | echo "USE_LOCAL = \"$USE_LOCAL\""
38 |
39 |
40 | if test -n "$USE_LOCAL" && ! test "$USE_LOCAL" = "" && ! test "$USE_LOCAL" = "yes" && test -n "$LIBJSON_PREFIX" ; then
41 | LIBJSON_CFLAGS="-I${LIBJSON_PREFIX}/include -I." # -I${LIBJSON_PREFIX}/Source
42 | LIBJSON_LIBS="-L${LIBJSON_PREFIX}/lib -ljson"
43 | CPP_FILES=""
44 | else
45 | if test "$ORIG_USE_LOCAL" = "never" ; then
46 | echo " ****************"
47 | echo "Couldn't find libjson on system so would use the local version of libjson in this package but you asked not to"
48 | echo " ****************"
49 | exit 1;
50 | fi
51 | if test -z "${LIBJSON_SRC}" ; then
52 | LIBJSON_SRC="src/libjson/Source"
53 | LIBJSON_CFLAGS="-I. -Ilibjson -Ilibjson/Source"
54 | else
55 | LIBJSON_CFLAGS="-I${LIBJSON_SRC}/.. -I${LIBJSON_SRC}"
56 | fi
57 | MINOR_VERSION=`grep 'define __LIBJSON_MINOR__' $LIBJSON_SRC/JSONDefs.h | sed -e 's/.* __LIBJSON_MINOR__ //'`
58 | if test "$MINOR_VERSION" = "0" ; then
59 | LIBJSON_CFLAGS="${LIBJSON_CFLAGS} -DJSON_NO_EXCEPTIONS=1"
60 | else
61 | LIBJSON_CFLAGS="${LIBJSON_CFLAGS} -DNEW_JSON_NEW_STREAM"
62 | fi
63 | echo "Minor Version: $MINOR_VERSION"
64 | echo "Using local libjson code. Copying files from ${LIBJSON_SRC}"
65 | echo "`pwd`"
66 | CPP_FILES="`(cd ${LIBJSON_SRC}; ls *.cpp)`"
67 | echo "$CPP_FILES"
68 | cp ${LIBJSON_SRC}/*.cpp src/
69 | cp src/libjson/JSONOptions.h src/
70 | fi
71 |
72 | AC_SUBST(CPP_FILES)
73 | AC_SUBST(LIBJSON_CFLAGS)
74 | AC_SUBST(LIBJSON_LIBS)
75 |
76 | AC_OUTPUT(src/Makevars cleanup)
77 | chmod +x cleanup
78 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONWorker.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_WORKER_H
2 | #define JSON_WORKER_H
3 |
4 | #include "JSONNode.h"
5 | #include "JSONSharedString.h"
6 |
7 | class JSONWorker {
8 | public:
9 | static json_string RemoveWhiteSpaceAndComments(const json_string & value_t, bool escapeQuotes) json_nothrow json_read_priority;
10 | static json_char * RemoveWhiteSpaceAndCommentsC(const json_string & value_t, bool escapeQuotes) json_nothrow json_read_priority;
11 |
12 | #ifdef JSON_READ_PRIORITY
13 | static JSONNode parse(const json_string & json) json_throws(std::invalid_argument) json_read_priority;
14 | static JSONNode parse_unformatted(const json_string & json) json_throws(std::invalid_argument) json_read_priority;
15 |
16 | static JSONNode _parse_unformatted(const json_char * json, const json_char * const end) json_throws(std::invalid_argument) json_read_priority;
17 |
18 | static json_char * RemoveWhiteSpace(const json_string & value_t, size_t & len, bool escapeQuotes) json_nothrow json_read_priority;
19 |
20 | static void DoArray(const internalJSONNode * parent, const json_string & value_t) json_nothrow json_read_priority;
21 | static void DoNode(const internalJSONNode * parent, const json_string & value_t) json_nothrow json_read_priority;
22 |
23 | #ifdef JSON_LESS_MEMORY
24 | #define NAME_ENCODED this, true
25 | #define STRING_ENCODED this, false
26 | static json_string FixString(const json_string & value_t, const internalJSONNode * flag, bool which) json_nothrow json_read_priority;
27 | #else
28 | #define NAME_ENCODED _name_encoded
29 | #define STRING_ENCODED _string_encoded
30 | static json_string FixString(const json_string & value_t, bool & flag) json_nothrow json_read_priority;
31 | #endif
32 | #endif
33 |
34 | #if defined(JSON_READ_PRIORITY) || defined(JSON_STREAM)
35 | #if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
36 | template
37 | static size_t FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
38 | #else
39 | static size_t FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow json_read_priority;
40 | #endif
41 | #endif
42 | static void UnfixString(const json_string & value_t, bool flag, json_string & res) json_nothrow;
43 | JSON_PRIVATE
44 | #ifdef JSON_READ_PRIORITY
45 | static json_char Hex(const json_char * & pos) json_nothrow;
46 | static json_uchar UTF8(const json_char * & pos, const json_char * const end) json_nothrow;
47 | #endif
48 | #ifdef JSON_ESCAPE_WRITES
49 | static json_string toUTF8(json_uchar p) json_nothrow;
50 | #endif
51 | #ifdef JSON_UNICODE
52 | static void UTF(const json_char * & pos, json_string & result, const json_char * const end) json_nothrow;
53 | #ifdef JSON_ESCAPE_WRITES
54 | static json_string toSurrogatePair(json_uchar pos) json_nothrow;
55 | #endif
56 | #endif
57 | #ifdef JSON_READ_PRIORITY
58 | static void SpecialChar(const json_char * & pos, const json_char * const end, json_string & res) json_nothrow;
59 | static void NewNode(const internalJSONNode * parent, const json_string & name, const json_string & value, bool array) json_nothrow;
60 | #endif
61 | private:
62 | JSONWorker(void);
63 | };
64 |
65 | #endif
66 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONStats.h:
--------------------------------------------------------------------------------
1 | #ifndef TestSuite_JSONStats_h
2 | #define TestSuite_JSONStats_h
3 |
4 | #include "../../JSONOptions.h"
5 |
6 | #if defined(JSON_UNIT_TEST) || defined(JSON_DEBUG)
7 | #define LIBJSON_OBJECT(name)\
8 | static size_t & getCtorCounter(void){\
9 | static size_t count = 0;\
10 | static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
11 | return count;\
12 | }\
13 | static size_t & getCopyCtorCounter(void){\
14 | static size_t count = 0;\
15 | static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
16 | return count;\
17 | }\
18 | static size_t & getAssignmentCounter(void){\
19 | static size_t count = 0;\
20 | static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
21 | return count;\
22 | }\
23 | static size_t & getDtorCounter(void){\
24 | static size_t count = 0;\
25 | static int i = JSONStats::setCallbacks(getCtorCounter, getCopyCtorCounter, getAssignmentCounter, getDtorCounter, #name);\
26 | return count;\
27 | }
28 | #define LIBJSON_CTOR getCtorCounter() += 1
29 | #define LIBJSON_COPY_CTOR getCopyCtorCounter() += 1
30 | #define LIBJSON_ASSIGNMENT getAssignmentCounter() += 1
31 | #define LIBJSON_DTOR getDtorCounter() += 1
32 |
33 | #include
34 | #include
35 | #include
36 | #include
37 | class JSONStats {
38 | public:
39 | ~JSONStats(void){
40 | std::map & mymap = getMapper();
41 | std::map::iterator b = mymap.begin();
42 | std::map::iterator e = mymap.end();
43 | std::cout << "Counters for libjson:" << std::endl;
44 | for(; b != e; ++b){
45 | std::cout << " " << b -> second -> _name << std::endl;
46 | std::cout << " Constructor: " << b -> second -> _cTor() << std::endl;
47 | std::cout << " Copy Constructor: " << b -> second -> _ccTor() << std::endl;
48 | std::cout << " Assignment: " << b -> second -> _assign() << std::endl;
49 | std::cout << " Destructor: " << b -> second -> _dTor() << std::endl;
50 | delete b -> second;
51 | }
52 | }
53 |
54 | typedef size_t & (*getCounter_m)(void);
55 | struct objectStructure {
56 | objectStructure(getCounter_m cTor, getCounter_m ccTor, getCounter_m assign, getCounter_m dTor, const std::string & name):
57 | _cTor(cTor), _ccTor(ccTor), _assign(assign), _dTor(dTor), _name(name){}
58 | std::string _name;
59 | getCounter_m _cTor;
60 | getCounter_m _ccTor;
61 | getCounter_m _assign;
62 | getCounter_m _dTor;
63 | };
64 | static int setCallbacks(getCounter_m cTor, getCounter_m ccTor, getCounter_m assign, getCounter_m dtor, const std::string & name){
65 | getMapper()[cTor] = new objectStructure (cTor, ccTor, assign, dtor, name);
66 | return 0;
67 | }
68 |
69 | static std::map & getMapper(void) {
70 | static std::map mymap;
71 | return mymap;
72 | }
73 | };
74 | #else
75 | #define LIBJSON_OBJECT(name)
76 | #define LIBJSON_CTOR (void)0
77 | #define LIBJSON_DTOR (void)0
78 | #define LIBJSON_COPY_CTOR (void)0
79 | #define LIBJSON_ASSIGNMENT (void)0
80 | typedef int JSONStats;
81 | #endif
82 |
83 | #endif
84 |
--------------------------------------------------------------------------------
/inst/sampleData/web.json:
--------------------------------------------------------------------------------
1 | {"web-app": {
2 | "servlet": [
3 | {
4 | "servlet-name": "cofaxCDS",
5 | "servlet-class": "org.cofax.cds.CDSServlet",
6 | "init-param": {
7 | "configGlossary:installationAt": "Philadelphia, PA",
8 | "configGlossary:adminEmail": "ksm@pobox.com",
9 | "configGlossary:poweredBy": "Cofax",
10 | "configGlossary:poweredByIcon": "/images/cofax.gif",
11 | "configGlossary:staticPath": "/content/static",
12 | "templateProcessorClass": "org.cofax.WysiwygTemplate",
13 | "templateLoaderClass": "org.cofax.FilesTemplateLoader",
14 | "templatePath": "templates",
15 | "templateOverridePath": "",
16 | "defaultListTemplate": "listTemplate.htm",
17 | "defaultFileTemplate": "articleTemplate.htm",
18 | "useJSP": false,
19 | "jspListTemplate": "listTemplate.jsp",
20 | "jspFileTemplate": "articleTemplate.jsp",
21 | "cachePackageTagsTrack": 200,
22 | "cachePackageTagsStore": 200,
23 | "cachePackageTagsRefresh": 60,
24 | "cacheTemplatesTrack": 100,
25 | "cacheTemplatesStore": 50,
26 | "cacheTemplatesRefresh": 15,
27 | "cachePagesTrack": 200,
28 | "cachePagesStore": 100,
29 | "cachePagesRefresh": 10,
30 | "cachePagesDirtyRead": 10,
31 | "searchEngineListTemplate": "forSearchEnginesList.htm",
32 | "searchEngineFileTemplate": "forSearchEngines.htm",
33 | "searchEngineRobotsDb": "WEB-INF/robots.db",
34 | "useDataStore": true,
35 | "dataStoreClass": "org.cofax.SqlDataStore",
36 | "redirectionClass": "org.cofax.SqlRedirection",
37 | "dataStoreName": "cofax",
38 | "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
39 | "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
40 | "dataStoreUser": "sa",
41 | "dataStorePassword": "dataStoreTestQuery",
42 | "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
43 | "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
44 | "dataStoreInitConns": 10,
45 | "dataStoreMaxConns": 100,
46 | "dataStoreConnUsageLimit": 100,
47 | "dataStoreLogLevel": "debug",
48 | "maxUrlLength": 500}},
49 | {
50 | "servlet-name": "cofaxEmail",
51 | "servlet-class": "org.cofax.cds.EmailServlet",
52 | "init-param": {
53 | "mailHost": "mail1",
54 | "mailHostOverride": "mail2"}},
55 | {
56 | "servlet-name": "cofaxAdmin",
57 | "servlet-class": "org.cofax.cds.AdminServlet"},
58 |
59 | {
60 | "servlet-name": "fileServlet",
61 | "servlet-class": "org.cofax.cds.FileServlet"},
62 | {
63 | "servlet-name": "cofaxTools",
64 | "servlet-class": "org.cofax.cms.CofaxToolsServlet",
65 | "init-param": {
66 | "templatePath": "toolstemplates/",
67 | "log": 1,
68 | "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
69 | "logMaxSize": "",
70 | "dataLog": 1,
71 | "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
72 | "dataLogMaxSize": "",
73 | "removePageCache": "/content/admin/remove?cache=pages&id=",
74 | "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
75 | "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
76 | "lookInContext": 1,
77 | "adminGroupID": 4,
78 | "betaServer": true}}],
79 | "servlet-mapping": {
80 | "cofaxCDS": "/",
81 | "cofaxEmail": "/cofaxutil/aemail/*",
82 | "cofaxAdmin": "/admin/*",
83 | "fileServlet": "/static/*",
84 | "cofaxTools": "/tools/*"},
85 |
86 | "taglib": {
87 | "taglib-uri": "cofax.tld",
88 | "taglib-location": "/WEB-INF/tlds/cofax.tld"}}}
89 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONGlobals.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_GLOBALS_H
2 | #define JSON_GLOBALS_H
3 |
4 | #include "JSONDefs.h"
5 |
6 | /*
7 | * The use of singletons for globals makes globals not
8 | * actually be initialized until it is first needed, this
9 | * makes the library faster to load, and have a smaller
10 | * memory footprint
11 | */
12 |
13 | #define json_global_decl(TYPE, NAME, VALUE) \
14 | class jsonSingleton ## NAME { \
15 | public: \
16 | inline static TYPE & getValue() json_nothrow { \
17 | static jsonSingleton ## NAME single; \
18 | return single.val; \
19 | } \
20 | protected: \
21 | inline jsonSingleton ## NAME() json_nothrow : val(VALUE) {} \
22 | TYPE val; \
23 | }
24 |
25 | #define json_global_decl_strconfig(TYPE, NAME, VALUE) \
26 | class jsonSingleton ## NAME { \
27 | public: \
28 | inline static TYPE & getValue() json_nothrow { \
29 | static jsonSingleton ## NAME single; \
30 | return single.val; \
31 | } \
32 | protected: \
33 | inline jsonSingleton ## NAME() json_nothrow { \
34 | const std::string tmp = std::string(VALUE); \
35 | val = json_string(tmp.begin(), tmp.end()); \
36 | } \
37 | TYPE val; \
38 | }
39 |
40 | #define json_global(NAME) jsonSingleton ## NAME::getValue()
41 |
42 | #include
43 | json_global_decl(json_string, EMPTY_JSON_STRING, );
44 | json_global_decl(std::string, EMPTY_STD_STRING, );
45 |
46 | json_global_decl(json_string, CONST_TRUE, JSON_TEXT("true"));
47 | json_global_decl(json_string, CONST_FALSE, JSON_TEXT("false"));
48 | json_global_decl(json_string, CONST_NULL, JSON_TEXT("null"));
49 |
50 | #ifndef JSON_NEWLINE
51 | json_global_decl(json_string, NEW_LINE, JSON_TEXT("\n"));
52 | #else
53 | json_global_decl_strconfig(json_string, NEW_LINE, JSON_NEWLINE);
54 | #endif
55 |
56 | #ifdef JSON_WRITE_BASH_COMMENTS
57 | json_global_decl(json_string, SINGLELINE_COMMENT, JSON_TEXT("#"));
58 | #else
59 | json_global_decl(json_string, SINGLELINE_COMMENT, JSON_TEXT("//"));
60 | #endif
61 |
62 | #ifdef JSON_INDENT
63 | json_global_decl_strconfig(json_string, INDENT, JSON_INDENT);
64 | #endif
65 |
66 | #ifdef JSON_MUTEX_CALLBACKS
67 | #include
68 | json_global_decl(JSON_MAP(void *, unsigned int), MUTEX_MANAGER, );
69 | json_global_decl(JSON_MAP(int, JSON_MAP(void *, unsigned int) ), THREAD_LOCKS, );
70 | #endif
71 |
72 | #ifdef JSON_LIBRARY
73 | #ifdef JSON_MEMORY_MANAGE
74 | #include "JSONMemory.h"
75 | json_global_decl(auto_expand, STRING_HANDLER, );
76 | json_global_decl(auto_expand_node, NODE_HANDLER, );
77 | #ifdef JSON_STREAM
78 | json_global_decl(auto_expand_stream, STREAM_HANDLER, );
79 | #endif
80 | #endif
81 | #endif
82 |
83 | //These are common error responses
84 | json_global_decl(json_string, ERROR_TOO_LONG, JSON_TEXT("Exceeding JSON_SECURITY_MAX_STRING_LENGTH"));
85 | json_global_decl(json_string, ERROR_UNKNOWN_LITERAL, JSON_TEXT("Unknown JSON literal: "));
86 | json_global_decl(json_string, ERROR_NON_CONTAINER, JSON_TEXT("Calling container method on non-container: "));
87 | json_global_decl(json_string, ERROR_NON_ITERATABLE, JSON_TEXT("Calling iterator method on non-iteratable: "));
88 | json_global_decl(json_string, ERROR_NULL_IN_CHILDREN, JSON_TEXT("a null pointer within the children"));
89 | json_global_decl(json_string, ERROR_UNDEFINED, JSON_TEXT("Undefined results: "));
90 | json_global_decl(json_string, ERROR_LOWER_RANGE, JSON_TEXT(" is outside the lower range of "));
91 | json_global_decl(json_string, ERROR_UPPER_RANGE, JSON_TEXT(" is outside the upper range of "));
92 | json_global_decl(json_string, ERROR_NOT_BASE64, JSON_TEXT("Not base64"));
93 | json_global_decl(json_string, ERROR_OUT_OF_MEMORY, JSON_TEXT("Out of memory"));
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONChildren.cpp:
--------------------------------------------------------------------------------
1 | #include "JSONChildren.h"
2 | #include "JSONNode.h"
3 |
4 | /*
5 | * reserves a certain number of bytes, in memory saving mode it creates a special
6 | * type of child container that will not autoshrink
7 | */
8 | void jsonChildren::reserve2(jsonChildren *& mine, json_index_t amount) json_nothrow {
9 | if (mine -> array != 0){
10 | if (mine -> mycapacity < amount){
11 | mine -> inc(amount - mine -> mycapacity);
12 | #ifdef JSON_LESS_MEMORY
13 | mine = jsonChildren_Reserved::newChildren_Reserved(mine, amount);
14 | #endif
15 | }
16 | } else {
17 | mine -> reserve(amount);
18 | }
19 | }
20 |
21 | void jsonChildren::inc(void) json_nothrow {
22 | JSON_ASSERT(this != 0, JSON_TEXT("Children is null inc"));
23 | if (json_unlikely(mysize == mycapacity)){ //it's full
24 | if (json_unlikely(mycapacity == 0)){ //the array hasn't been created yet
25 | JSON_ASSERT(!array, JSON_TEXT("Expanding a 0 capacity array, but not null"));
26 | #ifdef JSON_LESS_MEMORY
27 | array = json_malloc(1);
28 | mycapacity = 1;
29 | #else
30 | array = json_malloc(8); //8 seems average for JSON, and it's only 64 bytes
31 | mycapacity = 8;
32 | #endif
33 | } else {
34 | #ifdef JSON_LESS_MEMORY
35 | mycapacity += 1; //increment the size of the array
36 | #else
37 | mycapacity <<= 1; //double the size of the array
38 | #endif
39 | array = json_realloc(array, mycapacity);
40 | }
41 | }
42 | }
43 |
44 |
45 | void jsonChildren::inc(json_index_t amount) json_nothrow {
46 | JSON_ASSERT(this != 0, JSON_TEXT("Children is null inc(amount)"));
47 | if (json_unlikely(amount == 0)) return;
48 | if (json_likely(mysize + amount >= mycapacity)){ //it's full
49 | if (json_unlikely(mycapacity == 0)){ //the array hasn't been created yet
50 | JSON_ASSERT(!array, JSON_TEXT("Expanding a 0 capacity array, but not null"));
51 | #ifdef JSON_LESS_MEMORY
52 | array = json_malloc(amount);
53 | mycapacity = amount;
54 | #else
55 | array = json_malloc(amount > 8 ? amount : 8); //8 seems average for JSON, and it's only 64 bytes
56 | mycapacity = amount > 8 ? amount : 8;
57 | #endif
58 | } else {
59 | #ifdef JSON_LESS_MEMORY
60 | mycapacity = mysize + amount; //increment the size of the array
61 | #else
62 | while(mysize + amount > mycapacity){
63 | mycapacity <<= 1; //double the size of the array
64 | }
65 | #endif
66 | array = json_realloc(array, mycapacity);
67 | }
68 | }
69 | }
70 |
71 | //actually deletes everything within the vector, this is safe to do on an empty or even a null array
72 | void jsonChildren::deleteAll(void) json_nothrow {
73 | JSON_ASSERT(this != 0, JSON_TEXT("Children is null deleteAll"));
74 | json_foreach(this, runner){
75 | JSON_ASSERT(*runner != (JSONNode *) JSON_TEXT('\0'), JSON_TEXT("a null pointer within the children"));
76 | JSONNode::deleteJSONNode(*runner); //this is why I can't do forward declaration
77 | }
78 | }
79 |
80 | void jsonChildren::doerase(JSONNode ** position, json_index_t number) json_nothrow {
81 | JSON_ASSERT(this != 0, JSON_TEXT("Children is null doerase"));
82 | JSON_ASSERT(array != 0, JSON_TEXT("erasing something from a null array 2"));
83 | JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array 2"));
84 | JSON_ASSERT(position + number <= array + mysize, JSON_TEXT("erasing out of bounds 2"));
85 | if (position + number >= array + mysize){
86 | mysize = (json_index_t)(position - array);
87 | #ifndef JSON_ISO_STRICT
88 | JSON_ASSERT((long long)position - (long long)array >= 0, JSON_TEXT("doing negative allocation"));
89 | #endif
90 | } else {
91 | std::memmove(position, position + number, (mysize - (position - array) - number) * sizeof(JSONNode *));
92 | mysize -= number;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/inst/doc/missingValues.Rdb:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 | JSON, null and
8 |
9 | Duncan Temple Lang
10 | University of California at Davis
11 | Department of Statistics
12 |
13 |
14 |
15 |
16 |
17 | Limitations of JSON regarding the meaning of null
18 |
19 |
20 | JavaScript Object Notation (JSON) is a convenient format for
21 | representing data and facilitates transferring data between
22 | applications. It is widely used in different applications, Web
23 | services and other contexts. As such, it is useful for R to be able
24 | to import and export data in this format. Unfortunately, JSON is a
25 | little too simple and cannot faithfully represent all of the types and
26 | values in R. Most specifically, there is no way to support ,
27 | Inf or NaN . Typically, these
28 | values are represented in JSON as "null". However, that is also used
29 | to represent a null object. So there is ambiguity in how we interpret
30 | null in JSON.
31 | We don't know whether it is , NaN, Inf or in R.
32 | This many-to-one mapping results in a loss of information.
33 |
34 |
35 | In spite of the shortcomings of the format, we can still work with
36 | JSON. However, how we convert null values to R and how we
37 | convert values from R is not automatic and uniquely defined.
38 | For that reason, the caller must control how these are mapped.
39 | We provide some mechanisms to do this in the
40 | fromJSON and toJSON functions.
41 |
42 |
43 | When converting R objects to JSON via toJSON ,
44 | one can specify how to map values to JSON.
45 | One provides a value for the parameter .na
46 | to control this.
47 | For example, suppose we want to transform the R list
48 |
49 | x = list(1, 2, NA, c(TRUE, NA, FALSE))
50 |
51 | to JSON and want values to map to null.
52 | We can achieve this with
53 |
54 | toJSON(x, .na = "null")
55 |
56 |
57 |
58 | In some applications, we represent a missing value with a fixed number that is unlikely
59 | to occur in actual data, e.g. -99999.
60 | We can map values to such a number with
61 |
62 | toJSON(list(1, 2, list(NA)), .na = -99999)
63 |
64 |
65 |
66 | Now consider round-tripping , e.g.
67 |
68 | o = toJSON ( NA )
69 |
70 | [1] "[ null ]"
71 |
72 | fromJSON( o )
73 |
77 |
78 | So we have lost information.
79 |
80 |
81 |
82 |
83 | We can correct this loss of information by
84 | specifying how to map null values in JSON
85 | to R values. We use the nullValue
86 |
87 | fromJSON( toJSON ( NA ), nullValue = NA)
88 |
89 | Again, here we as the caller of fromJSON
90 | (and also toJSON ) we are providing
91 | information about how to transfer the null value from JSON to R.
92 | Only we know what it means in this case.
93 | If we knew that the null corresponded to Inf ,
94 | we could specify that:
95 |
96 | fromJSON( "[null]", nullValue = Inf)
97 |
98 |
99 |
100 | Where this mechanism breaks down is when we have multiple
101 | null values in our JSON content and they map to different
102 | R values, e.g. , and NaN.
103 | The nullValue parameter is a global replacement for
104 | null entries in the JSON. To adaptively process these null
105 | entries in a context specific manner, we have to use a customized
106 | parser. We can do this by providing an R function as the
107 | callback handler for the JSON parser.
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/utfTest/json.c:
--------------------------------------------------------------------------------
1 | /* main.c */
2 |
3 | /*
4 | This program demonstrates a simple application of JSON_parser. It reads
5 | a JSON text from STDIN, producing an error message if the text is rejected.
6 |
7 | % JSON_parser
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include "JSON_parser.h"
17 |
18 | static int print(void* ctx, int type, const JSON_value* value);
19 |
20 | int main(int argc, char* argv[]) {
21 | int count = 0;
22 | FILE* input;
23 |
24 | JSON_config config;
25 |
26 | struct JSON_parser_struct* jc = NULL;
27 |
28 | init_JSON_config(&config);
29 |
30 | config.depth = 20;
31 | config.callback = &print;
32 | config.allow_comments = 1;
33 | config.handle_floats_manually = 0;
34 |
35 | /* Important! Set locale before parser is created.*/
36 | if (argc >= 2) {
37 | if (!setlocale(LC_ALL, argv[1])) {
38 | fprintf(stderr, "Failed to set locale to '%s'\n", argv[1]);
39 | }
40 | } else {
41 | fprintf(stderr, "No locale provided, C locale is used\n");
42 | }
43 |
44 | jc = new_JSON_parser(&config);
45 |
46 | input = stdin;
47 | for (; input ; ++count) {
48 | int next_char = fgetc(input);
49 | if(count == 1601)
50 | fprintf(stderr, "1061\n");
51 | if (next_char <= 0) {
52 | break;
53 | }
54 | fprintf(stderr, "%d) %c %u\n", count, next_char, (unsigned int) next_char);fflush(stderr);
55 | if (!JSON_parser_char(jc, next_char)) {
56 | delete_JSON_parser(jc);
57 | fprintf(stderr, "JSON_parser_char: syntax error, byte %d\n", count);
58 | return 1;
59 | }
60 | }
61 | if (!JSON_parser_done(jc)) {
62 | delete_JSON_parser(jc);
63 | fprintf(stderr, "JSON_parser_end: syntax error\n");
64 | return 1;
65 | }
66 |
67 | return 0;
68 | }
69 |
70 | static size_t s_Level = 0;
71 |
72 | static const char* s_pIndention = " ";
73 |
74 | static int s_IsKey = 0;
75 |
76 | static void print_indention()
77 | {
78 | size_t i;
79 |
80 | for (i = 0; i < s_Level; ++i) {
81 | printf(s_pIndention);
82 | }
83 | }
84 |
85 |
86 | static int print(void* ctx, int type, const JSON_value* value)
87 | {
88 | switch(type) {
89 | case JSON_T_ARRAY_BEGIN:
90 | if (!s_IsKey) print_indention();
91 | s_IsKey = 0;
92 | printf("[\n");
93 | ++s_Level;
94 | break;
95 | case JSON_T_ARRAY_END:
96 | assert(!s_IsKey);
97 | if (s_Level > 0) --s_Level;
98 | print_indention();
99 | printf("]\n");
100 | break;
101 | case JSON_T_OBJECT_BEGIN:
102 | if (!s_IsKey) print_indention();
103 | s_IsKey = 0;
104 | printf("{\n");
105 | ++s_Level;
106 | break;
107 | case JSON_T_OBJECT_END:
108 | assert(!s_IsKey);
109 | if (s_Level > 0) --s_Level;
110 | print_indention();
111 | printf("}\n");
112 | break;
113 | case JSON_T_INTEGER:
114 | if (!s_IsKey) print_indention();
115 | s_IsKey = 0;
116 | printf("integer: "JSON_PARSER_INTEGER_SPRINTF_TOKEN"\n", value->vu.integer_value);
117 | break;
118 | case JSON_T_FLOAT:
119 | if (!s_IsKey) print_indention();
120 | s_IsKey = 0;
121 | printf("float: %f\n", value->vu.float_value); /* We wanted stringified floats */
122 | break;
123 | case JSON_T_NULL:
124 | if (!s_IsKey) print_indention();
125 | s_IsKey = 0;
126 | printf("null\n");
127 | break;
128 | case JSON_T_TRUE:
129 | if (!s_IsKey) print_indention();
130 | s_IsKey = 0;
131 | printf("true\n");
132 | break;
133 | case JSON_T_FALSE:
134 | if (!s_IsKey) print_indention();
135 | s_IsKey = 0;
136 | printf("false\n");
137 | break;
138 | case JSON_T_KEY:
139 | s_IsKey = 1;
140 | print_indention();
141 | printf("key = '%s', value = ", value->vu.str.value);
142 | break;
143 | case JSON_T_STRING:
144 | if (!s_IsKey) print_indention();
145 | s_IsKey = 0;
146 | printf("string: '%s'\n", value->vu.str.value);
147 | break;
148 | default:
149 | assert(0);
150 | break;
151 | }
152 |
153 | return 1;
154 | }
155 |
156 |
157 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONStream.cpp:
--------------------------------------------------------------------------------
1 | #include "JSONStream.h"
2 |
3 | #ifdef JSON_STREAM
4 | #include "JSONWorker.h"
5 | #include "JSONValidator.h"
6 |
7 |
8 | JSONStream::JSONStream(json_stream_callback_t call_p, json_stream_e_callback_t call_e, void * callbackIdentifier) json_nothrow : state(true), call(call_p), err_call(call_e), buffer(), callback_identifier(callbackIdentifier) {
9 | LIBJSON_CTOR;
10 | }
11 |
12 | JSONStream::JSONStream(const JSONStream & orig) json_nothrow : state(orig.state), call(orig.call), err_call(orig.err_call), buffer(orig.buffer), callback_identifier(orig.callback_identifier){
13 | LIBJSON_COPY_CTOR;
14 | }
15 |
16 | JSONStream & JSONStream::operator =(const JSONStream & orig) json_nothrow {
17 | LIBJSON_ASSIGNMENT;
18 | err_call = orig.err_call;
19 | call = orig.call;
20 | state = orig.state;
21 | buffer = orig.buffer;
22 | callback_identifier = orig.callback_identifier;
23 | return *this;
24 | }
25 |
26 | #ifdef JSON_LIBRARY
27 | JSONStream & JSONStream::operator << (const json_char * str) json_nothrow {
28 | #else
29 | JSONStream & JSONStream::operator << (const json_string & str) json_nothrow {
30 | #endif
31 | if (state){
32 | buffer += str;
33 | parse();
34 | }
35 | return *this;
36 | }
37 |
38 |
39 | #define QUOTECASE_STREAM()\
40 | case JSON_TEXT('\"'):\
41 | while (*(++p) != JSON_TEXT('\"')){\
42 | if (json_unlikely(*p == JSON_TEXT('\0'))) return json_string::npos;\
43 | }\
44 | break;
45 |
46 |
47 | #define NULLCASE_STREAM()\
48 | case JSON_TEXT('\0'):\
49 | return json_string::npos;\
50 |
51 |
52 | #define BRACKET_STREAM(left, right)\
53 | case left: {\
54 | size_t brac = 1;\
55 | while (brac){\
56 | switch (*(++p)){\
57 | case right:\
58 | --brac;\
59 | break;\
60 | case left:\
61 | ++brac;\
62 | break;\
63 | QUOTECASE_STREAM()\
64 | NULLCASE_STREAM()\
65 | }\
66 | }\
67 | break;}\
68 | case right:\
69 | return json_string::npos;
70 |
71 | #if (JSON_READ_PRIORITY == HIGH) && (!(defined(JSON_LESS_MEMORY)))
72 | #define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant(vt, po)
73 | template
74 | size_t JSONStream::FindNextRelevant(const json_string & value_t, const size_t pos) json_nothrow {
75 | #else
76 | #define STREAM_FIND_NEXT_RELEVANT(ch, vt, po) FindNextRelevant(ch, vt, po)
77 | size_t JSONStream::FindNextRelevant(json_char ch, const json_string & value_t, const size_t pos) json_nothrow {
78 | #endif
79 | const json_char * start = value_t.c_str();
80 | for (const json_char * p = start + pos; *p; ++p){
81 | if (json_unlikely(*p == ch)) return p - start;
82 | switch (*p){
83 | BRACKET_STREAM(JSON_TEXT('['), JSON_TEXT(']'))
84 | BRACKET_STREAM(JSON_TEXT('{'), JSON_TEXT('}'))
85 | QUOTECASE_STREAM()
86 | }
87 | };
88 | return json_string::npos;
89 | }
90 |
91 | void JSONStream::parse(void) json_nothrow {
92 | #ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
93 | size_t objects = 0;
94 | #endif
95 | for(;;){
96 | size_t pos = buffer.find_first_of(JSON_TEXT("{["));
97 | if (json_likely(pos != json_string::npos)){
98 | size_t end = (buffer[pos] == JSON_TEXT('[')) ? STREAM_FIND_NEXT_RELEVANT(JSON_TEXT(']'), buffer, pos + 1) : STREAM_FIND_NEXT_RELEVANT(JSON_TEXT('}'), buffer, pos + 1);
99 | if (end != json_string::npos){
100 | #ifdef JSON_SECURITY_MAX_STREAM_OBJECTS
101 | if (++objects > JSON_SECURITY_MAX_STREAM_OBJECTS){
102 | JSON_FAIL(JSON_TEXT("Maximum number of json objects for a stream at once has been reached"));
103 | if (err_call) err_call(getIdentifier());
104 | state = false;
105 | return;
106 | }
107 | #endif
108 | START_MEM_SCOPE
109 | JSONNode temp(JSONWorker::parse(buffer.substr(pos, end - pos + 1)));
110 | #ifndef JSON_LIBRARY
111 | call(temp, getIdentifier());
112 | #else
113 | call(&temp, getIdentifier());
114 | #endif
115 | END_MEM_SCOPE
116 | json_string::iterator beginning = buffer.begin();
117 | buffer.erase(beginning, beginning + end);
118 | continue; //parse(); //parse the next object too
119 | }
120 | #ifdef JSON_SAFE
121 | else {
122 | //verify that what's in there is at least valid so far
123 | #ifndef JSON_VALIDATE
124 | #error In order to use safe mode and streams, JSON_VALIDATE needs to be defined
125 | #endif
126 |
127 | json_auto s;
128 | size_t len;
129 | s.set(JSONWorker::RemoveWhiteSpace(json_string(buffer.c_str() + pos), len, false));
130 |
131 |
132 | if (!JSONValidator::isValidPartialRoot(s.ptr)){
133 | if (err_call) err_call(getIdentifier());
134 | state = false;
135 | }
136 | }
137 | #endif
138 | }
139 | break;
140 | }
141 | }
142 |
143 | #endif
144 |
--------------------------------------------------------------------------------
/foo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Change Log for RJSONIO
6 |
7 |
8 | Change Log for RJSONIO
9 |
10 | RJSONIO
11 |
12 | Version 0.6-0
13 |
14 |
15 | Updated the libjson source code in the package to libjson 7.0.1.
16 | This removes a bug in parsing numbers of the form 3.14E4. Found
17 | by Jeroen Ooms.
18 |
19 |
20 |
21 | Added configuration so that we can use a libjson installed on the system.
22 | This avoids issues of using older versions of libjson shipped with this package.
23 |
24 |
25 |
26 |
27 |
28 | Version 0.5-0
29 |
30 | Enhancements to disambiguate serializing empty lists from as empty arrays or associative
31 | arrays. See also emptyNamedList to map to {}.
32 |
33 |
34 | Method for identifying an R scalar that should be mapped to a JSON array via the
35 | AsIs class and I() function.
36 |
37 |
38 | toJSON() honors these also ensuring transformation from JSON to R to JSON
39 | preserves the same structure.
40 |
41 |
42 |
43 | Both changes thanks to suggestions by Keith Bonawitz.
44 |
45 |
46 |
47 |
48 |
49 | Version 0.4-2
50 |
51 | Fixed significant memory leaks found by Keith Bonawitz
52 |
53 |
54 |
55 |
56 | Version 0.4-1
57 |
58 | Tidied up C++ code from libjsonio to avoid a warning about no
59 | argument to initializeFetch() when compiling the C++ code.
60 |
61 |
62 | Fixed a C routine (R_fromJSON) that did not return a value.
63 |
64 |
65 |
66 |
67 | Version 0.4-0
68 |
69 |
70 | fromJSON() now uses libjson for the native parsing
71 | and a C routine to transform the resulting tree into R.
72 | This leads to a considerable speedup in parsing documents,
73 | approximately a factor of 200 over the customizable, event
74 | driven mechanism in earlier versions and still available
75 | in this package via the basicJSONHandler()
76 | function and fromJSON() .
77 |
78 |
79 |
80 |
81 |
82 | Version 0.3-4
83 |
84 | Refinement of handling large integers that do not fit into a 4 byte int.
85 | Tested on Windows.
86 |
87 |
88 |
89 |
90 |
91 | Version 0.3-3
92 |
93 | Handle large integers that do not fit into a 4 byte int. Return as numeric values.
94 |
95 |
96 |
97 |
98 | Version 0.3-1
99 |
100 | Convert factors to character vectors in toJSON() and then serialize.
101 |
102 |
103 |
104 |
105 | Version 0.2-4
106 |
107 | Handles UTF-8 content as input. We convert the text to raw and then integer
108 | values.
109 |
110 |
111 |
112 |
113 |
114 | Version 0.2-3
115 |
116 | (Minor) Change to the C code to make it compile on Windows.
117 |
118 |
119 |
120 |
121 | Version 0.2-2
122 |
123 |
124 | named atomic/primitive vectors serialized as associative arrays rather
125 | than simple arrays.
126 |
127 |
128 |
129 |
130 |
131 | Version 0.2-1
132 |
133 |
134 | names on R objects from associative arrays from JSON were in reverse order.
135 |
136 |
137 |
138 |
139 |
140 | Version 0.2-0
141 |
142 |
143 | Scalar, by default, values are represented in JSON as scalars and not
144 | arrays of length 1. One can control this via the
145 | container parameter in toJSON() .
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
--------------------------------------------------------------------------------
/utfTest/news.txt:
--------------------------------------------------------------------------------
1 | {"offset" : "0" , "results" : [{"body" : "Whenever modern humans reached a new continent in the expansion from their African homeland 50,000 years ago, whether Australia, Europe or the Americas, all the large fauna quickly disappeared. This circumstantial evidence from the fossil record suggests that people’s first accomplishment upon reaching new territory was to hunt all its all" , "byline" : "By NICHOLAS WADE" , "date" : "20091124" , "title" : "New Data Shed Light on Large-Animal Extinction" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/science\/24fauna.html"} , {"body" : "Perhaps by living on another planet, you might have missed the popular conclusion that Asia must increase consumption and let its exchange rates climb to help put the world economy on a more even keel. But, until recently, another part of the policy prescription for stronger Asian demand to reduce global imbalances has received far less attention:" , "byline" : "By ALAN WHEATLEY" , "date" : "20091124" , "title" : "INSIDE ASIA; Asia Could Benefit From Cooperating on Infrastructure" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/business\/global\/24inside.html"} , {"body" : "BRASÍLIA As leaders from Brazil and Iran prepared to meet here on Monday, the Brazilian president, Luiz Inacio Lula da Silva , defended his decision to play host to the Iranian president at a moment of rising tension over Iran’s nuclear ambitions. In his national radio show, Mr. da Silva said that “you don’t move" , "byline" : "By ALEXEI BARRIONUEVO" , "date" : "20091124" , "title" : "Brazil’s President Defends Visit of Iranian Leader" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/world\/americas\/24brazil.html"} , {"body" : "Let’s stipulate: Lloyd Blankfein and Jamie Dimon are enlightened, broad-gauge chief executive officers, among the finest in the world. Their firms, Goldman Sachs and JPMorgan Chase, are indispensable in raising capital for companies, creating wealth. They’ve repaid the government assistance money received in the financial crisis and are" , "byline" : "By ALBERT R. HUNT" , "date" : "20091124" , "title" : "LETTER FROM WASHINGTON; No Lessons Learned on Wall Street" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/us\/24iht-letter.html"} , {"body" : "Joe Witte, a meteorologist for News Channel 8 in Virginia and Maryland, hopes that people watching his television forecasts will think about more than just the weather. Two years ago, Mr. Witte started to include phenomena linked with climate change in his reports, like how warmer conditions affect life in Chesapeake Bay and prospects for" , "byline" : "By JAMES KANTER" , "date" : "20091123" , "title" : "GREEN INC. COLUMN; New Voices on Climate Change" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/business\/energy-environment\/23iht-green23.html"} , {"body" : "BUSINESS DAY An article on Friday about a House committee’s approval of a measure that would expand Congressional oversight of the Federal Reserve misidentified the state represented by Paul E. Kanjorski, who offered an amendment that would expand government power over large financial institutions. It is Pennsylvania, not Ohio. ( Go to" , "date" : "20091123" , "title" : "Corrections" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/pageoneplus\/corrections.html"} , {"body" : "An article on Thursday about turmoil within the United States Chamber of Commerce over its opposition to climate change legislation erroneously included one company among those that have resigned from the chamber over the climate policy. A spokeswoman for Levi Strauss & Company said that although the company had differed with the chamber over" , "date" : "20091123" , "title" : "Corrections" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/pageoneplus\/23corrections-003.html"} , {"body" : "WASHINGTON On the House floor during a debate over health care reform , he taunted a colleague who had been calling for his ouster. At a recent fund-raiser, he complained that the House speaker had made an end run around him and his committee. Confronted by a persistent conservative activist in a hallway, he let loose an expletive, telling" , "byline" : "By RAYMOND HERNANDEZ and JIM RUTENBERG" , "date" : "20091123" , "title" : "His Ethics Under Scrutiny, Rangel Is Frayed but Defiant" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/nyregion\/23rangel.html"} , {"body" : "BRASÍLIA Brazil ’s ambitions to be a more important player on the global diplomatic stage are crashing headlong into the efforts of the United States and other Western powers to rein in Iran ’s nuclear arms program. Luiz Inácio Lula da Silva , Brazil’s president, is set to receive Iran’s president, Mahmoud" , "byline" : "By ALEXEI BARRIONUEVO" , "date" : "20091123" , "title" : "Brazil Elbows U.S. on the Diplomatic Stage" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/world\/americas\/23brazil.html"} , {"body" : "PORTLAND, Ore. For decades, the world’s supercomputers have been the tightly guarded property of universities and governments. But what would happen if regular folks could get their hands on one? The price of supercomputers is dropping quickly, in part because they are often built with the same off-the-shelf parts found in PCs, as a" , "byline" : "By ASHLEE VANCE" , "date" : "20091123" , "title" : "Shared Supercomputing and Everyday Research" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/technology\/23compute.html"}] , "tokens" : ["climate" , "change"] , "total" : 10492}
--------------------------------------------------------------------------------
/utfTest/news1.txt:
--------------------------------------------------------------------------------
1 | {"offset" : "0" , "results" : [{"body" : "Whenever modern humans reached a new continent in the expansion from their African homeland 50,000 years ago, whether Australia, Europe or the Americas, all the large fauna quickly disappeared. This circumstantial evidence from the fossil record suggests that people’s first accomplishment upon reaching new territory was to hunt all its all" , "byline" : "By NICHOLAS WADE" , "date" : "20091124" , "title" : "New Data Shed Light on Large-Animal Extinction" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/science\/24fauna.html"} , {"body" : "Perhaps by living on another planet, you might have missed the popular conclusion that Asia must increase consumption and let its exchange rates climb to help put the world economy on a more even keel. But, until recently, another part of the policy prescription for stronger Asian demand to reduce global imbalances has received far less attention:" , "byline" : "By ALAN WHEATLEY" , "date" : "20091124" , "title" : "INSIDE ASIA; Asia Could Benefit From Cooperating on Infrastructure" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/business\/global\/24inside.html"} , {"body" : "BRASÍLIA As leaders from Brazil and Iran prepared to meet here on Monday, the Brazilian president, Luiz Inacio Lula da Silva , defended his decision to play host to the Iranian president at a moment of rising tension over Iran’s nuclear ambitions. In his national radio show, Mr. da Silva said that “you don’t move" , "byline" : "By ALEXEI BARRIONUEVO" , "date" : "20091124" , "title" : "Brazil's President Defends Visit of Iranian Leader" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/world\/americas\/24brazil.html"} , {"body" : "Let’s stipulate: Lloyd Blankfein and Jamie Dimon are enlightened, broad-gauge chief executive officers, among the finest in the world. Their firms, Goldman Sachs and JPMorgan Chase, are indispensable in raising capital for companies, creating wealth. They’ve repaid the government assistance money received in the financial crisis and are" , "byline" : "By ALBERT R. HUNT" , "date" : "20091124" , "title" : "LETTER FROM WASHINGTON; No Lessons Learned on Wall Street" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/us\/24iht-letter.html"} , {"body" : "Joe Witte, a meteorologist for News Channel 8 in Virginia and Maryland, hopes that people watching his television forecasts will think about more than just the weather. Two years ago, Mr. Witte started to include phenomena linked with climate change in his reports, like how warmer conditions affect life in Chesapeake Bay and prospects for" , "byline" : "By JAMES KANTER" , "date" : "20091123" , "title" : "GREEN INC. COLUMN; New Voices on Climate Change" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/business\/energy-environment\/23iht-green23.html"} , {"body" : "BUSINESS DAY An article on Friday about a House committee’s approval of a measure that would expand Congressional oversight of the Federal Reserve misidentified the state represented by Paul E. Kanjorski, who offered an amendment that would expand government power over large financial institutions. It is Pennsylvania, not Ohio. ( Go to" , "date" : "20091123" , "title" : "Corrections" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/pageoneplus\/corrections.html"} , {"body" : "An article on Thursday about turmoil within the United States Chamber of Commerce over its opposition to climate change legislation erroneously included one company among those that have resigned from the chamber over the climate policy. A spokeswoman for Levi Strauss & Company said that although the company had differed with the chamber over" , "date" : "20091123" , "title" : "Corrections" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/pageoneplus\/23corrections-003.html"} , {"body" : "WASHINGTON On the House floor during a debate over health care reform , he taunted a colleague who had been calling for his ouster. At a recent fund-raiser, he complained that the House speaker had made an end run around him and his committee. Confronted by a persistent conservative activist in a hallway, he let loose an expletive, telling" , "byline" : "By RAYMOND HERNANDEZ and JIM RUTENBERG" , "date" : "20091123" , "title" : "His Ethics Under Scrutiny, Rangel Is Frayed but Defiant" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/nyregion\/23rangel.html"} , {"body" : "BRASÍLIA Brazil ’s ambitions to be a more important player on the global diplomatic stage are crashing headlong into the efforts of the United States and other Western powers to rein in Iran ’s nuclear arms program. Luiz Inácio Lula da Silva , Brazil’s president, is set to receive Iran’s president, Mahmoud" , "byline" : "By ALEXEI BARRIONUEVO" , "date" : "20091123" , "title" : "Brazil Elbows U.S. on the Diplomatic Stage" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/world\/americas\/23brazil.html"} , {"body" : "PORTLAND, Ore. For decades, the world’s supercomputers have been the tightly guarded property of universities and governments. But what would happen if regular folks could get their hands on one? The price of supercomputers is dropping quickly, in part because they are often built with the same off-the-shelf parts found in PCs, as a" , "byline" : "By ASHLEE VANCE" , "date" : "20091123" , "title" : "Shared Supercomputing and Everyday Research" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/technology\/23compute.html"}] , "tokens" : ["climate" , "change"] , "total" : 10492}
2 |
--------------------------------------------------------------------------------
/utfTest/news2.txt:
--------------------------------------------------------------------------------
1 | {"offset" : "0" , "results" : [{"body" : "Whenever modern humans reached a new continent in the expansion from their African homeland 50,000 years ago, whether Australia, Europe or the Americas, all the large fauna quickly disappeared. This circumstantial evidence from the fossil record suggests that people’s first accomplishment upon reaching new territory was to hunt all its all" , "byline" : "By NICHOLAS WADE" , "date" : "20091124" , "title" : "New Data Shed Light on Large-Animal Extinction" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/science\/24fauna.html"} , {"body" : "Perhaps by living on another planet, you might have missed the popular conclusion that Asia must increase consumption and let its exchange rates climb to help put the world economy on a more even keel. But, until recently, another part of the policy prescription for stronger Asian demand to reduce global imbalances has received far less attention:" , "byline" : "By ALAN WHEATLEY" , "date" : "20091124" , "title" : "INSIDE ASIA; Asia Could Benefit From Cooperating on Infrastructure" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/business\/global\/24inside.html"} , {"body" : "BRASÍLIA As leaders from Brazil and Iran prepared to meet here on Monday, the Brazilian president, Luiz Inacio Lula da Silva , defended his decision to play host to the Iranian president at a moment of rising tension over Iran’s nuclear ambitions. In his national radio show, Mr. da Silva said that “you don’t move" , "byline" : "By ALEXEI BARRIONUEVO" , "date" : "20091124" , "title" : "Brazil’s President Defends Visit of Iranian Leader" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/world\/americas\/24brazil.html"} , {"body" : "Let’s stipulate: Lloyd Blankfein and Jamie Dimon are enlightened, broad-gauge chief executive officers, among the finest in the world. Their firms, Goldman Sachs and JPMorgan Chase, are indispensable in raising capital for companies, creating wealth. They’ve repaid the government assistance money received in the financial crisis and are" , "byline" : "By ALBERT R. HUNT" , "date" : "20091124" , "title" : "LETTER FROM WASHINGTON; No Lessons Learned on Wall Street" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/24\/us\/24iht-letter.html"} , {"body" : "Joe Witte, a meteorologist for News Channel 8 in Virginia and Maryland, hopes that people watching his television forecasts will think about more than just the weather. Two years ago, Mr. Witte started to include phenomena linked with climate change in his reports, like how warmer conditions affect life in Chesapeake Bay and prospects for" , "byline" : "By JAMES KANTER" , "date" : "20091123" , "title" : "GREEN INC. COLUMN; New Voices on Climate Change" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/business\/energy-environment\/23iht-green23.html"} , {"body" : "BUSINESS DAY An article on Friday about a House committee’s approval of a measure that would expand Congressional oversight of the Federal Reserve misidentified the state represented by Paul E. Kanjorski, who offered an amendment that would expand government power over large financial institutions. It is Pennsylvania, not Ohio. ( Go to" , "date" : "20091123" , "title" : "Corrections" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/pageoneplus\/corrections.html"} , {"body" : "An article on Thursday about turmoil within the United States Chamber of Commerce over its opposition to climate change legislation erroneously included one company among those that have resigned from the chamber over the climate policy. A spokeswoman for Levi Strauss & Company said that although the company had differed with the chamber over" , "date" : "20091123" , "title" : "Corrections" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/pageoneplus\/23corrections-003.html"} , {"body" : "WASHINGTON On the House floor during a debate over health care reform , he taunted a colleague who had been calling for his ouster. At a recent fund-raiser, he complained that the House speaker had made an end run around him and his committee. Confronted by a persistent conservative activist in a hallway, he let loose an expletive, telling" , "byline" : "By RAYMOND HERNANDEZ and JIM RUTENBERG" , "date" : "20091123" , "title" : "His Ethics Under Scrutiny, Rangel Is Frayed but Defiant" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/nyregion\/23rangel.html"} , {"body" : "BRASÍLIA Brazil ’s ambitions to be a more important player on the global diplomatic stage are crashing headlong into the efforts of the United States and other Western powers to rein in Iran ’s nuclear arms program. Luiz Inácio Lula da Silva , Brazil’s president, is set to receive Iran’s president, Mahmoud" , "byline" : "By ALEXEI BARRIONUEVO" , "date" : "20091123" , "title" : "Brazil Elbows U.S. on the Diplomatic Stage" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/world\/americas\/23brazil.html"} , {"body" : "PORTLAND, Ore. For decades, the world’s supercomputers have been the tightly guarded property of universities and governments. But what would happen if regular folks could get their hands on one? The price of supercomputers is dropping quickly, in part because they are often built with the same off-the-shelf parts found in PCs, as a" , "byline" : "By ASHLEE VANCE" , "date" : "20091123" , "title" : "Shared Supercomputing and Everyday Research" , "url" : "http:\/\/www.nytimes.com\/2009\/11\/23\/technology\/23compute.html"}] , "tokens" : ["climate" , "change"] , "total" : 10492}
2 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONDefs.h:
--------------------------------------------------------------------------------
1 | #ifndef JSONDEFS_H
2 | #define JSONDEFS_H
3 |
4 | /*
5 | Defines all of the types of functions and various other definitions
6 | that are used in C applications, this is very useful if dynamically loading
7 | the library instead of linking.
8 | */
9 |
10 | #include "../../JSONOptions.h"
11 | #include "JSONDefs/Unknown_C.h"
12 | #include "JSONDefs/GNU_C.h"
13 | #include "JSONDefs/Visual_C.h"
14 | #include "JSONDefs/Strings_Defs.h"
15 |
16 | #define __LIBJSON_MAJOR__ 7
17 | #define __LIBJSON_MINOR__ 6
18 | #define __LIBJSON_PATCH__ 1
19 | #define __LIBJSON_VERSION__ (__LIBJSON_MAJOR__ * 10000 + __LIBJSON_MINOR__ * 100 + __LIBJSON_PATCH__)
20 |
21 | #define JSON_NULL '\0'
22 | #define JSON_STRING '\1'
23 | #define JSON_NUMBER '\2'
24 | #define JSON_BOOL '\3'
25 | #define JSON_ARRAY '\4'
26 | #define JSON_NODE '\5'
27 |
28 | #ifdef __cplusplus
29 | #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
30 | #include "JSONAllocator.h"
31 | #else
32 | #define json_allocator std::allocator
33 | #endif
34 |
35 | #ifdef JSON_STRING_HEADER
36 | #include JSON_STRING_HEADER
37 | #else
38 | typedef std::basic_string, json_allocator > json_string;
39 | #endif
40 | #endif
41 | #define JSON_MAP(x, y) std::map, json_allocator > >
42 |
43 | #ifdef JSON_NO_EXCEPTIONS
44 | #define json_throw(x)
45 | #define json_try
46 | #define json_catch(exception, code)
47 | #else
48 | #define json_throw(x) throw(x)
49 | #define json_try try
50 | #define json_catch(exception, code) catch(exception){ code }
51 | #endif
52 |
53 | #ifdef JSON_STRICT
54 | #ifndef JSON_UNICODE
55 | #error, JSON_UNICODE is required for JSON_STRICT
56 | #endif
57 | #ifdef JSON_COMMENTS
58 | #error, JSON_COMMENTS is required to be off for JSON_STRICT
59 | #endif
60 | #endif
61 |
62 | #ifdef JSON_ISO_STRICT
63 | #ifdef JSON_UNICODE
64 | #error, You can not use unicode under ANSI Strict C++
65 | #endif
66 | #else
67 | #ifdef __GNUC__
68 | #ifdef __STRICT_ANSI__
69 | #warning, Using -ansi GCC option, but JSON_ISO_STRICT not on, turning it on for you
70 | #define JSON_ISO_STRICT
71 | #endif
72 | #endif
73 | #endif
74 |
75 |
76 | #ifdef JSON_NUMBER_TYPE
77 | typedef JSON_NUMBER_TYPE json_number;
78 | #define JSON_FLOAT_THRESHHOLD 0.00001
79 | #else
80 | #ifdef JSON_LESS_MEMORY
81 | typedef float json_number;
82 | #define JSON_FLOAT_THRESHHOLD 0.00001f
83 | #else
84 | typedef double json_number;
85 | #define JSON_FLOAT_THRESHHOLD 0.00001
86 | #endif
87 | #endif
88 |
89 |
90 | #ifdef JSON_LESS_MEMORY
91 | /* PACKED and BITS stored in compiler specific headers */
92 | #define START_MEM_SCOPE {
93 | #define END_MEM_SCOPE }
94 | #else
95 | #define PACKED(x)
96 | #define BITS(x)
97 | #define START_MEM_SCOPE
98 | #define END_MEM_SCOPE
99 | #endif
100 |
101 | #if defined JSON_DEBUG || defined JSON_SAFE
102 | #ifdef JSON_LIBRARY
103 | typedef void (*json_error_callback_t)(const json_char *);
104 | #else
105 | typedef void (*json_error_callback_t)(const json_string &);
106 | #endif
107 | #endif
108 |
109 | #ifdef JSON_INDEX_TYPE
110 | typedef JSON_INDEX_TYPE json_index_t;
111 | #else
112 | typedef unsigned int json_index_t;
113 | #endif
114 |
115 | #ifdef JSON_BOOL_TYPE
116 | typedef JSON_BOOL_TYPE json_bool_t;
117 | #else
118 | typedef int json_bool_t;
119 | #endif
120 |
121 | #ifdef JSON_INT_TYPE
122 | typedef JSON_INT_TYPE json_int_t;
123 | #else
124 | typedef long json_int_t;
125 | #endif
126 |
127 | #define JSONSTREAM_SELF (void*)-1
128 | typedef void (*json_stream_e_callback_t)(void * identifier);
129 |
130 | typedef void (*json_mutex_callback_t)(void *);
131 | typedef void (*json_free_t)(void *);
132 | #ifndef JSON_LIBRARY
133 | typedef void * (*json_malloc_t)(size_t);
134 | typedef void * (*json_realloc_t)(void *, size_t);
135 | #else
136 | #define JSONNODE void /* so that JSONNODE* is void* */
137 | typedef JSONNODE** JSONNODE_ITERATOR;
138 | #ifdef JSON_STREAM
139 | #define JSONSTREAM void
140 | typedef void (*json_stream_callback_t)(JSONNODE *, void * identifier);
141 | #endif
142 | typedef void * (*json_malloc_t)(unsigned long);
143 | typedef void * (*json_realloc_t)(void *, unsigned long);
144 | #endif
145 |
146 | #ifdef JSON_DEBUG
147 | #ifdef NDEBUG
148 | #ifdef __GNUC__
149 | #warning, Have JSON_DEBUG on in a release build
150 | #else
151 | #error, Have JSON_DEBUG on in a release build
152 | #endif
153 | #endif
154 | #else
155 | #ifndef NDEBUG
156 | #ifdef __GNUC__
157 | #warning, Release build of libjson, but NDEBUG is not on
158 | #else
159 | #error, Release build of libjson, but NDEBUG is not on
160 | #endif
161 | #endif
162 | #endif
163 |
164 | #ifdef JSON_UNIT_TEST
165 | #define JSON_PRIVATE public:
166 | #define JSON_PROTECTED public:
167 | #else
168 | #define JSON_PRIVATE private:
169 | #define JSON_PROTECTED protected:
170 | #endif
171 | #ifdef JSON_STREAM
172 | #ifndef JSON_READ_PRIORITY
173 | #error, JSON_STREAM also requires JSON_READ_PRIORITY
174 | #endif
175 | #endif
176 | #ifdef JSON_VALIDATE
177 | #ifndef JSON_READ_PRIORITY
178 | #error, JSON_VALIDATE also requires JSON_READ_PRIORITY
179 | #endif
180 | #endif
181 |
182 | #define JSON_TEMP_COMMENT_IDENTIFIER JSON_TEXT('#')
183 |
184 | #endif
185 |
--------------------------------------------------------------------------------
/src/JSON_parser.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_PARSER_H
2 | #define JSON_PARSER_H
3 |
4 | /* JSON_parser.h */
5 |
6 |
7 | #include
8 |
9 | #if 0
10 |
11 | /* Windows DLL stuff */
12 | #ifdef _WIN32
13 | # ifdef JSON_PARSER_DLL_EXPORTS
14 | # define JSON_PARSER_DLL_API __declspec(dllexport)
15 | # else
16 | # define JSON_PARSER_DLL_API __declspec(dllimport)
17 | # endif
18 | #else
19 | # define JSON_PARSER_DLL_API
20 | #endif
21 |
22 | #else
23 |
24 | #define JSON_PARSER_DLL_API
25 |
26 | #endif /* #if 0 */
27 |
28 |
29 | /* Determine the integer type use to parse non-floating point numbers */
30 | #if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG == 1
31 | typedef long long JSON_int_t;
32 | //#warning "using long long"
33 | #define JSON_PARSER_INTEGER_SSCANF_TOKEN "%lld"
34 | #define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%lld"
35 | #else
36 | typedef long JSON_int_t;
37 | #define JSON_PARSER_INTEGER_SSCANF_TOKEN "%ld"
38 | #define JSON_PARSER_INTEGER_SPRINTF_TOKEN "%ld"
39 | #endif
40 |
41 | #define MAX_INT 2147483647L
42 |
43 |
44 | #ifdef __cplusplus
45 | extern "C" {
46 | #endif
47 |
48 | typedef enum
49 | {
50 | JSON_T_NONE = 0,
51 | JSON_T_ARRAY_BEGIN,
52 | JSON_T_ARRAY_END,
53 | JSON_T_OBJECT_BEGIN,
54 | JSON_T_OBJECT_END,
55 | JSON_T_INTEGER,
56 | JSON_T_FLOAT,
57 | JSON_T_NULL,
58 | JSON_T_TRUE,
59 | JSON_T_FALSE,
60 | JSON_T_STRING,
61 | JSON_T_KEY,
62 | JSON_T_MAX
63 | } JSON_type;
64 |
65 | #ifndef WIN32
66 | typedef long double DoubleType;
67 | #define DoubleScanFormat "%Lf"
68 | #else
69 | typedef double DoubleType;
70 | #define DoubleScanFormat "%lf"
71 | #endif
72 |
73 | typedef struct JSON_value_struct {
74 | union {
75 | JSON_int_t integer_value;
76 |
77 | DoubleType float_value;
78 |
79 | struct {
80 | const char* value;
81 | size_t length;
82 | } str;
83 | } vu;
84 | } JSON_value;
85 |
86 | /*! \brief JSON parser callback
87 |
88 | \param ctx The pointer passed to new_JSON_parser.
89 | \param type An element of JSON_type but not JSON_T_NONE.
90 | \param value A representation of the parsed value. This parameter is NULL for
91 | JSON_T_ARRAY_BEGIN, JSON_T_ARRAY_END, JSON_T_OBJECT_BEGIN, JSON_T_OBJECT_END,
92 | JSON_T_NULL, JSON_T_TRUE, and SON_T_FALSE. String values are always returned
93 | as zero-terminated C strings.
94 |
95 | \return Non-zero if parsing should continue, else zero.
96 | */
97 | typedef int (*JSON_parser_callback)(void* ctx, int type, const struct JSON_value_struct* value);
98 |
99 |
100 | /*! \brief The structure used to configure a JSON parser object
101 |
102 | \param depth If negative, the parser can parse arbitrary levels of JSON, otherwise
103 | the depth is the limit
104 | \param Pointer to a callback. This parameter may be NULL. In this case the input is merely checked for validity.
105 | \param Callback context. This parameter may be NULL.
106 | \param depth. Specifies the levels of nested JSON to allow. Negative numbers yield unlimited nesting.
107 | \param allowComments. To allow C style comments in JSON, set to non-zero.
108 | \param handleFloatsManually. To decode floating point numbers manually set this parameter to non-zero.
109 |
110 | \return The parser object.
111 | */
112 | typedef struct JSON_config_struct {
113 | JSON_parser_callback callback;
114 | void* callback_ctx;
115 | int depth;
116 | int allow_comments;
117 | int handle_floats_manually;
118 | } JSON_config;
119 |
120 |
121 | /*! \brief Initializes the JSON parser configuration structure to default values.
122 |
123 | The default configuration is
124 | - 127 levels of nested JSON (depends on JSON_PARSER_STACK_SIZE, see json_parser.c)
125 | - no parsing, just checking for JSON syntax
126 | - no comments
127 |
128 | \param config. Used to configure the parser.
129 | */
130 | JSON_PARSER_DLL_API void init_JSON_config(JSON_config* config);
131 |
132 | /*! \brief Create a JSON parser object
133 |
134 | \param config. Used to configure the parser. Set to NULL to use the default configuration.
135 | See init_JSON_config
136 |
137 | \return The parser object.
138 | */
139 | JSON_PARSER_DLL_API extern struct JSON_parser_struct* new_JSON_parser(JSON_config* config);
140 |
141 | /*! \brief Destroy a previously created JSON parser object. */
142 | JSON_PARSER_DLL_API extern void delete_JSON_parser(struct JSON_parser_struct* jc);
143 |
144 | /*! \brief Parse a character.
145 |
146 | \return Non-zero, if all characters passed to this function are part of are valid JSON.
147 | */
148 | JSON_PARSER_DLL_API extern int JSON_parser_char(struct JSON_parser_struct* jc, int next_char);
149 |
150 | /*! \brief Finalize parsing.
151 |
152 | Call this method once after all input characters have been consumed.
153 |
154 | \return Non-zero, if all parsed characters are valid JSON, zero otherwise.
155 | */
156 | JSON_PARSER_DLL_API extern int JSON_parser_done(struct JSON_parser_struct* jc);
157 |
158 | /*! \brief Determine if a given string is valid JSON white space
159 |
160 | \return Non-zero if the string is valid, zero otherwise.
161 | */
162 | JSON_PARSER_DLL_API extern int JSON_parser_is_legal_white_space_string(const char* s);
163 |
164 |
165 | #ifdef __cplusplus
166 | }
167 | #endif
168 |
169 |
170 | #endif /* JSON_PARSER_H */
171 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONMemory.cpp:
--------------------------------------------------------------------------------
1 | #include "JSONMemory.h"
2 |
3 | #ifdef JSON_MEMORY_MANAGE
4 | #include "JSONNode.h"
5 | void auto_expand::purge(void) json_nothrow {
6 | for(JSON_MAP(void *, void *)::iterator i = mymap.begin(), en = mymap.end(); i != en; ++i){
7 | #if defined(JSON_DEBUG) || defined(JSON_SAFE)
8 | void * temp = (void*)i -> first; //because its pass by reference
9 | libjson_free(temp);
10 | #else
11 | libjson_free((void*)i -> first);
12 | #endif
13 | }
14 | }
15 |
16 | void auto_expand_node::purge(void) json_nothrow {
17 | for(JSON_MAP(void *, JSONNode *)::iterator i = mymap.begin(), en = mymap.end(); i != en; ++i){
18 | JSONNode::deleteJSONNode((JSONNode *)i -> second);
19 | }
20 | }
21 |
22 | #ifdef JSON_STREAM
23 | #include "JSONStream.h"
24 | void auto_expand_stream::purge(void) json_nothrow {
25 | for(JSON_MAP(void *, JSONStream *)::iterator i = mymap.begin(), en = mymap.end(); i != en; ++i){
26 | JSONStream::deleteJSONStream((JSONStream *)i -> second);
27 | }
28 | }
29 | #endif
30 | #endif
31 |
32 | #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
33 |
34 | #ifdef JSON_MEMORY_POOL
35 | #include "JSONMemoryPool.h"
36 | static bucket_pool_8 json_generic_mempool;
37 |
38 | //This class is only meant to initiate the mempool to start out using std::malloc/realloc/free
39 | class mempool_callback_setter {
40 | public:
41 | LIBJSON_OBJECT(mempool_callback_setter);
42 | inline mempool_callback_setter(void) json_nothrow {
43 | ` LIBJSON_CTOR;
44 | mempool_callbacks::set(std::malloc, std::realloc, std::free);
45 | }
46 | private:
47 | inline mempool_callback_setter(const mempool_callback_setter & o);
48 | inline mempool_callback_setter & operator = (const mempool_callback_setter & o);
49 | };
50 | static mempool_callback_setter __mempoolcallbacksetter;
51 | #endif
52 |
53 | #include "JSONSingleton.h"
54 |
55 | void * JSONMemory::json_malloc(size_t siz) json_nothrow {
56 | #ifdef JSON_MEMORY_POOL
57 | return json_generic_mempool.allocate(siz);
58 | #else
59 | if (json_malloc_t callback = JSONSingleton::get()){
60 | #if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
61 | void * result = callback(siz);
62 | JSON_ASSERT(result, JSON_TEXT("Out of memory"));
63 | return result;
64 | #else
65 | return callback(siz);
66 | #endif
67 | }
68 | #if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
69 | void * result = std::malloc(siz);
70 | JSON_ASSERT(result, JSON_TEXT("Out of memory"));
71 | return result;
72 | #else
73 | return std::malloc(siz);
74 | #endif
75 | #endif
76 | }
77 |
78 | void JSONMemory::json_free(void * ptr) json_nothrow {
79 | #ifdef JSON_MEMORY_POOL
80 | json_generic_mempool.deallocate(ptr);
81 | #else
82 | if (json_free_t callback = JSONSingleton::get()){
83 | callback(ptr);
84 | } else {
85 | std::free(ptr);
86 | }
87 | #endif
88 | }
89 |
90 | void * JSONMemory::json_realloc(void * ptr, size_t siz) json_nothrow {
91 | #ifdef JSON_MEMORY_POOL
92 | return json_generic_mempool.reallocate(ptr, siz);
93 | #else
94 | if (json_realloc_t callback = JSONSingleton::get()){
95 | #if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
96 | void * result = callback(ptr, siz);
97 | JSON_ASSERT(result, JSON_TEXT("Out of memory"));
98 | return result;
99 | #else
100 | return callback(ptr, siz);
101 | #endif
102 | }
103 | #if(defined(JSON_DEBUG) && (!defined(JSON_MEMORY_CALLBACKS))) //in debug mode without mem callback, see if the malloc was successful
104 | void * result = std::realloc(ptr, siz);
105 | JSON_ASSERT(result, JSON_TEXT("Out of memory"));
106 | return result;
107 | #else
108 | return std::realloc(ptr, siz);
109 | #endif
110 | #endif
111 | }
112 |
113 | #ifdef JSON_MEMORY_POOL
114 | //it is okay to pass null to these callbacks, no make sure they function exists
115 | static void * malloc_proxy(size_t siz) json_nothrow {
116 | if (json_malloc_t callback = JSONSingleton::get()){
117 | return callback(siz);
118 | }
119 | return std::malloc(siz);
120 | }
121 |
122 | static void * realloc_proxy(void * ptr, size_t siz) json_nothrow {
123 | if (json_realloc_t callback = JSONSingleton::get()){
124 | return callback(ptr, siz);
125 | }
126 | return std::realloc(ptr, siz);
127 | }
128 |
129 | static void free_proxy(void * ptr){
130 | if (json_free_t callback = JSONSingleton::get()){
131 | callback(ptr);
132 | } else {
133 | std::free(ptr);
134 | }
135 | }
136 | #endif
137 |
138 |
139 | void JSONMemory::registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow {
140 | JSONSingleton::set(mal);
141 | JSONSingleton::set(real);
142 | JSONSingleton::set(fre);
143 | #ifdef JSON_MEMORY_POOL
144 | mempool_callbacks::set(malloc_proxy, realloc_proxy, free_proxy);
145 | #endif
146 | }
147 |
148 |
149 | #endif
150 |
--------------------------------------------------------------------------------
/src/ConvertUTF.h:
--------------------------------------------------------------------------------
1 | #ifndef CONVERT_UNICODE_H
2 | #define CONVERT_UNICODE_H
3 |
4 | /*
5 | * Copyright 2001-2004 Unicode, Inc.
6 | *
7 | * Disclaimer
8 | *
9 | * This source code is provided as is by Unicode, Inc. No claims are
10 | * made as to fitness for any particular purpose. No warranties of any
11 | * kind are expressed or implied. The recipient agrees to determine
12 | * applicability of information provided. If this file has been
13 | * purchased on magnetic or optical media from Unicode, Inc., the
14 | * sole remedy for any claim will be exchange of defective media
15 | * within 90 days of receipt.
16 | *
17 | * Limitations on Rights to Redistribute This Code
18 | *
19 | * Unicode, Inc. hereby grants the right to freely use the information
20 | * supplied in this file in the creation of products supporting the
21 | * Unicode Standard, and to make copies of this file in any form
22 | * for internal or external distribution as long as this notice
23 | * remains attached.
24 | */
25 |
26 | /* ---------------------------------------------------------------------
27 |
28 | Conversions between UTF32, UTF-16, and UTF-8. Header file.
29 |
30 | Several funtions are included here, forming a complete set of
31 | conversions between the three formats. UTF-7 is not included
32 | here, but is handled in a separate source file.
33 |
34 | Each of these routines takes pointers to input buffers and output
35 | buffers. The input buffers are const.
36 |
37 | Each routine converts the text between *sourceStart and sourceEnd,
38 | putting the result into the buffer between *targetStart and
39 | targetEnd. Note: the end pointers are *after* the last item: e.g.
40 | *(sourceEnd - 1) is the last item.
41 |
42 | The return result indicates whether the conversion was successful,
43 | and if not, whether the problem was in the source or target buffers.
44 | (Only the first encountered problem is indicated.)
45 |
46 | After the conversion, *sourceStart and *targetStart are both
47 | updated to point to the end of last text successfully converted in
48 | the respective buffers.
49 |
50 | Input parameters:
51 | sourceStart - pointer to a pointer to the source buffer.
52 | The contents of this are modified on return so that
53 | it points at the next thing to be converted.
54 | targetStart - similarly, pointer to pointer to the target buffer.
55 | sourceEnd, targetEnd - respectively pointers to the ends of the
56 | two buffers, for overflow checking only.
57 |
58 | These conversion functions take a ConversionFlags argument. When this
59 | flag is set to strict, both irregular sequences and isolated surrogates
60 | will cause an error. When the flag is set to lenient, both irregular
61 | sequences and isolated surrogates are converted.
62 |
63 | Whether the flag is strict or lenient, all illegal sequences will cause
64 | an error return. This includes sequences such as: , ,
65 | or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
66 | must check for illegal sequences.
67 |
68 | When the flag is set to lenient, characters over 0x10FFFF are converted
69 | to the replacement character; otherwise (when the flag is set to strict)
70 | they constitute an error.
71 |
72 | Output parameters:
73 | The value "sourceIllegal" is returned from some routines if the input
74 | sequence is malformed. When "sourceIllegal" is returned, the source
75 | value will point to the illegal value that caused the problem. E.g.,
76 | in UTF-8 when a sequence is malformed, it points to the start of the
77 | malformed sequence.
78 |
79 | Author: Mark E. Davis, 1994.
80 | Rev History: Rick McGowan, fixes & updates May 2001.
81 | Fixes & updates, Sept 2001.
82 |
83 | ------------------------------------------------------------------------ */
84 |
85 | /* ---------------------------------------------------------------------
86 | The following 4 definitions are compiler-specific.
87 | The C standard does not guarantee that wchar_t has at least
88 | 16 bits, so wchar_t is no less portable than unsigned short!
89 | All should be unsigned values to avoid sign extension during
90 | bit mask & shift operations.
91 | ------------------------------------------------------------------------ */
92 |
93 |
94 | typedef unsigned int UTF32; /* at least 32 bits */
95 | typedef unsigned short UTF16; /* at least 16 bits */
96 | typedef unsigned char UTF8; /* typically 8 bits */
97 | typedef unsigned char Boolean; /* 0 or 1 */
98 |
99 | /* Some fundamental constants */
100 | #define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
101 | #define UNI_MAX_BMP (UTF32)0x0000FFFF
102 | #define UNI_MAX_UTF16 (UTF32)0x0010FFFF
103 | #define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
104 | #define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
105 |
106 | typedef enum {
107 | conversionOK, /* conversion successful */
108 | sourceExhausted, /* partial character in source, but hit end */
109 | targetExhausted, /* insuff. room in target for conversion */
110 | sourceIllegal /* source sequence is illegal/malformed */
111 | } ConversionResult;
112 |
113 | typedef enum {
114 | strictConversion = 0,
115 | lenientConversion
116 | } ConversionFlags;
117 |
118 | /* This is for C++ and does no harm in C */
119 | #ifdef __cplusplus
120 | extern "C" {
121 | #endif
122 |
123 | ConversionResult ConvertUTF8toUTF16 (
124 | const UTF8** sourceStart, const UTF8* sourceEnd,
125 | UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
126 |
127 | ConversionResult ConvertUTF16toUTF8 (
128 | const UTF16** sourceStart, const UTF16* sourceEnd,
129 | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
130 |
131 | ConversionResult ConvertUTF8toUTF32 (
132 | const UTF8** sourceStart, const UTF8* sourceEnd,
133 | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
134 |
135 | ConversionResult ConvertUTF32toUTF8 (
136 | const UTF32** sourceStart, const UTF32* sourceEnd,
137 | UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
138 |
139 | ConversionResult ConvertUTF16toUTF32 (
140 | const UTF16** sourceStart, const UTF16* sourceEnd,
141 | UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
142 |
143 | ConversionResult ConvertUTF32toUTF16 (
144 | const UTF32** sourceStart, const UTF32* sourceEnd,
145 | UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
146 |
147 | Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
148 |
149 | #ifdef __cplusplus
150 | }
151 | #endif
152 |
153 | /* --------------------------------------------------------------------- */
154 |
155 | #endif // CONVERT_UNICODE_H
156 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONMemory.h:
--------------------------------------------------------------------------------
1 | #ifndef JSON_MEMORY_H
2 | #define JSON_MEMORY_H
3 |
4 | #include //for malloc, realloc, and free
5 | #include //for memmove
6 | #include "JSONDebug.h"
7 |
8 | #if defined(JSON_DEBUG) || defined(JSON_SAFE)
9 | #define JSON_FREE_PASSTYPE &
10 | #else
11 | #define JSON_FREE_PASSTYPE
12 | #endif
13 |
14 | #if defined(JSON_MEMORY_CALLBACKS) || defined(JSON_MEMORY_POOL)
15 | class JSONMemory {
16 | public:
17 | static void * json_malloc(size_t siz) json_malloc_attr;
18 | static void * json_realloc(void * ptr, size_t siz) json_malloc_attr;
19 | static void json_free(void * ptr) json_nothrow;
20 | static void registerMemoryCallbacks(json_malloc_t mal, json_realloc_t real, json_free_t fre) json_nothrow json_cold;
21 | private:
22 | JSONMemory(void);
23 | };
24 |
25 | template static inline T * json_malloc(size_t count) json_malloc_attr;
26 | template static inline T * json_malloc(size_t count) json_nothrow {
27 | return (T *)JSONMemory::json_malloc(sizeof(T) * count);
28 | }
29 |
30 | template static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
31 | template static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
32 | return (T *)JSONMemory::json_realloc(ptr, sizeof(T) * count);
33 | }
34 |
35 | template static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
36 | JSONMemory::json_free(ptr);
37 | #if defined(JSON_DEBUG) || defined(JSON_SAFE) //in debug or safe mode, set the pointer to 0 so that it can't be used again
38 | ptr = 0;
39 | #endif
40 | }
41 | #else
42 |
43 | template static inline T * json_malloc(size_t count) json_malloc_attr;
44 | template static inline T * json_malloc(size_t count) json_nothrow {
45 | #ifdef JSON_DEBUG //in debug mode, see if the malloc was successful
46 | void * result = std::malloc(count * sizeof(T));
47 | JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
48 | #ifdef JSON_NULL_MEMORY
49 | std::memset(result, '\0', count * sizeof(T));
50 | #endif
51 | return (T *)result;
52 | #else
53 | return (T *)std::malloc(count * sizeof(T));
54 | #endif
55 | }
56 |
57 | template static inline void libjson_free(T * JSON_FREE_PASSTYPE ptr) json_nothrow {
58 | std::free(ptr);
59 | #if defined(JSON_DEBUG) || defined(JSON_SAFE) //in debug or safe mode, set the pointer to 0 so that it can't be used again
60 | ptr = 0;
61 | #endif
62 | }
63 |
64 | template static inline T * json_realloc(T * ptr, size_t count) json_malloc_attr;
65 | template static inline T * json_realloc(T * ptr, size_t count) json_nothrow {
66 | #ifdef JSON_DEBUG //in debug mode, check the results of realloc to be sure it was successful
67 | void * result = std::realloc(ptr, count * sizeof(T));
68 | JSON_ASSERT(result != 0, JSON_TEXT("Out of memory"));
69 | return (T *)result;
70 | #else
71 | return (T *)std::realloc(ptr, count * sizeof(T));
72 | #endif
73 | }
74 | #endif
75 |
76 | #ifdef JSON_MEMORY_MANAGE
77 | #include
78 | class JSONNode;
79 | struct auto_expand {
80 | public:
81 | LIBJSON_OBJECT(auto_expand);
82 | auto_expand(void) json_nothrow : mymap(){ LIBJSON_CTOR;}
83 | ~auto_expand(void) json_nothrow { purge(); LIBJSON_DTOR; }
84 | void purge(void) json_nothrow;
85 | inline void clear(void) json_nothrow { purge(); mymap.clear(); }
86 | inline void * insert(void * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
87 | inline void remove(void * ptr) json_nothrow {
88 | JSON_MAP(void *, void *)::iterator i = mymap.find(ptr);
89 | JSON_ASSERT(i != mymap.end(), JSON_TEXT("Removing a non-managed item"));
90 | mymap.erase(i);
91 | }
92 | JSON_MAP(void *, void *) mymap;
93 | private:
94 | auto_expand(const auto_expand &);
95 | auto_expand & operator = (const auto_expand &);
96 | };
97 |
98 | struct auto_expand_node {
99 | public:
100 | LIBJSON_OBJECT(auto_expand_node);
101 | auto_expand_node(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
102 | ~auto_expand_node(void) json_nothrow { purge(); LIBJSON_DTOR; }
103 | void purge(void) json_nothrow ;
104 | inline void clear(void) json_nothrow { purge(); mymap.clear(); }
105 | inline JSONNode * insert(JSONNode * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
106 | inline void remove(void * ptr) json_nothrow {
107 | JSON_MAP(void *, JSONNode *)::iterator i = mymap.find(ptr);
108 | if(json_likely(i != mymap.end())) mymap.erase(i);
109 | }
110 | JSON_MAP(void *, JSONNode *) mymap;
111 | private:
112 | auto_expand_node(const auto_expand_node &);
113 | auto_expand_node & operator = (const auto_expand_node &);
114 | };
115 |
116 | #ifdef JSON_STREAM
117 | class JSONStream;
118 | struct auto_expand_stream {
119 | public:
120 | LIBJSON_OBJECT(auto_expand_stream);
121 | auto_expand_stream(void) json_nothrow : mymap(){ LIBJSON_CTOR; }
122 | ~auto_expand_stream(void) json_nothrow { purge(); LIBJSON_DTOR; }
123 | void purge(void) json_nothrow ;
124 | inline void clear(void) json_nothrow { purge(); mymap.clear(); }
125 | inline JSONStream * insert(JSONStream * ptr) json_nothrow { mymap[ptr] = ptr; return ptr; }
126 | inline void remove(void * ptr) json_nothrow {
127 | JSON_MAP(void *, JSONStream *)::iterator i = mymap.find(ptr);
128 | if(json_likely(i != mymap.end())) mymap.erase(i);
129 | }
130 | JSON_MAP(void *, JSONStream *) mymap;
131 | private:
132 | auto_expand_stream(const auto_expand_stream &);
133 | auto_expand_stream & operator = (const auto_expand_stream &);
134 | };
135 | #endif
136 | #endif
137 |
138 | //The C++ way, use an self-deleting pointer and let the optimizer decide when it gets destroyed
139 | template
140 | class json_auto {
141 | public:
142 | LIBJSON_OBJECT(json_auto);
143 | json_auto(void) json_nothrow : ptr(0){ LIBJSON_CTOR; }
144 | json_auto(size_t count) json_nothrow : ptr(json_malloc(count)){ LIBJSON_CTOR; }
145 | json_auto(T * arg) json_nothrow : ptr(arg){ LIBJSON_CTOR; }
146 | ~json_auto(void) json_nothrow {
147 | libjson_free(ptr);
148 | LIBJSON_DTOR;
149 | }
150 | inline void set(T * p) json_nothrow{
151 | ptr = p;
152 | }
153 | T * ptr;
154 | private:
155 | json_auto(const json_auto &);
156 | json_auto & operator =(const json_auto &);
157 | };
158 |
159 | //Clears a string, if required, frees the memory
160 | static inline void clearString(json_string & str) json_nothrow {
161 | #ifdef JSON_LESS_MEMORY
162 | json_string().swap(str);
163 | #else
164 | str.clear();
165 | #endif
166 | }
167 |
168 | //Shrinks a string
169 | static inline void shrinkString(json_string & str) json_nothrow {
170 | #ifdef JSON_LESS_MEMORY
171 | if (str.capacity() != str.length()) str = json_string(str.begin(), str.end());
172 | #endif
173 | }
174 |
175 | #endif
176 |
--------------------------------------------------------------------------------
/src/libjson/Source/JSONNode_Mutex.cpp:
--------------------------------------------------------------------------------
1 | #include "JSONNode.h"
2 | #include "JSONGlobals.h"
3 |
4 | #ifdef JSON_MUTEX_CALLBACKS
5 |
6 | json_mutex_callback_t json_lock_callback = 0;
7 | json_mutex_callback_t json_unlock_callback = 0;
8 | void * global_mutex = 0;
9 | void * manager_mutex = 0;
10 |
11 | struct AutoLock {
12 | public:
13 | LIBJSON_OBJECT(AutoLock);
14 | AutoLock(void) json_nothrow {
15 | LIBJSON_CTOR;
16 | json_lock_callback(manager_mutex);
17 | }
18 | ~AutoLock(void) json_nothrow {
19 | LIBJSON_DTOR;
20 | json_unlock_callback(manager_mutex);
21 | }
22 | private:
23 | AutoLock(const AutoLock &);
24 | AutoLock & operator = (const AutoLock &);
25 | };
26 |
27 | #ifdef JSON_MUTEX_MANAGE
28 | json_mutex_callback_t json_destroy = 0;
29 |
30 | //make sure that the global mutex is taken care of too
31 | struct auto_global {
32 | public:
33 | LIBJSON_OBJECT(auto_global;)
34 | auto_global(void) json_nothrow { LIBJSON_CTOR; }
35 | ~auto_global(void) json_nothrow {
36 | LIBJSON_DTOR;
37 | if (global_mutex){
38 | JSON_ASSERT_SAFE(json_destroy != 0, JSON_TEXT("No json_destroy in mutex managed mode"), return;);
39 | json_destroy(global_mutex);
40 | }
41 | }
42 | private:
43 | auto_global(const auto_global &);
44 | auto_global & operator = (const auto_global &);
45 | };
46 | auto_global cleanupGlobal;
47 | #endif
48 |
49 | void JSONNode::register_mutex_callbacks(json_mutex_callback_t lock, json_mutex_callback_t unlock, void * manager_lock) json_nothrow {
50 | json_lock_callback = lock;
51 | json_unlock_callback = unlock;
52 | manager_mutex = manager_lock;
53 | }
54 |
55 | void JSONNode::set_global_mutex(void * mutex) json_nothrow {
56 | global_mutex = mutex;
57 | }
58 |
59 | void JSONNode::set_mutex(void * mutex) json_nothrow {
60 | makeUniqueInternal();
61 | internal -> _set_mutex(mutex);
62 | }
63 |
64 | void * JSONNode::getThisLock(JSONNode * pthis) json_nothrow {
65 | if (pthis -> internal -> mylock != 0){
66 | return pthis -> internal -> mylock;
67 | }
68 | JSON_ASSERT(global_mutex != 0, JSON_TEXT("No global_mutex")); //this is safe, because it's just goingi to return 0 anyway
69 | return global_mutex;
70 | }
71 |
72 | void JSONNode::lock(int thread) json_nothrow {
73 | JSON_ASSERT_SAFE(json_lock_callback != 0, JSON_TEXT("No locking callback"), return;);
74 |
75 | AutoLock lockControl;
76 |
77 | //first, figure out what needs to be locked
78 | void * thislock = getThisLock(this);
79 | #ifdef JSON_SAFE
80 | if (json_unlikely(thislock == 0)) return;
81 | #endif
82 |
83 | //make sure that the same thread isn't locking it more than once (possible due to complex ref counting)
84 | JSON_MAP(int, JSON_MAP(void *, unsigned int) )::iterator it = json_global(THREAD_LOCKS).find(thread);
85 | if (it == json_global(THREAD_LOCKS).end()){
86 | JSON_MAP(void *, unsigned int) newthread;
87 | newthread[thislock] = 1;
88 | json_global(THREAD_LOCKS).insert(std::pair(thread, newthread));
89 | } else { //this thread already has some things locked, check if the current mutex is
90 | JSON_MAP(void *, unsigned int) & newthread = it -> second;
91 | JSON_MAP(void *, unsigned int)::iterator locker(newthread.find(thislock));
92 | if (locker == newthread.end()){ //current mutex is not locked, set it to locked
93 | newthread.insert(std::pair(thislock, 1));
94 | } else { //it's already locked, don't relock it
95 | ++(locker -> second);
96 | return; //don't try to relock, it will deadlock the program
97 | }
98 | }
99 |
100 | //if I need to, lock it
101 | json_lock_callback(thislock);
102 | }
103 |
104 | void JSONNode::unlock(int thread) json_nothrow{
105 | JSON_ASSERT_SAFE(json_unlock_callback != 0, JSON_TEXT("No unlocking callback"), return;);
106 |
107 | AutoLock lockControl;
108 |
109 | //first, figure out what needs to be locked
110 | void * thislock = getThisLock(this);
111 | #ifdef JSON_SAFE
112 | if (thislock == 0) return;
113 | #endif
114 |
115 | //get it out of the map
116 | JSON_MAP(int, JSON_MAP(void *, unsigned int) )::iterator it = json_global(THREAD_LOCKS).find(thread);
117 | JSON_ASSERT_SAFE(it != json_global(THREAD_LOCKS).end(), JSON_TEXT("thread unlocking something it didn't lock"), return;);
118 |
119 | //get the mutex out of the thread
120 | JSON_MAP(void *, unsigned int) & newthread = it -> second;
121 | JSON_MAP(void *, unsigned int)::iterator locker = newthread.find(thislock);
122 | JSON_ASSERT_SAFE(locker != newthread.end(), JSON_TEXT("thread unlocking mutex it didn't lock"), return;);
123 |
124 | //unlock it
125 | if (--(locker -> second)) return; //other nodes is this same thread still have a lock on it
126 |
127 | //if I need to, unlock it
128 | newthread.erase(locker);
129 | json_unlock_callback(thislock);
130 |
131 | }
132 |
133 | #ifdef JSON_MUTEX_MANAGE
134 | void JSONNode::register_mutex_destructor(json_mutex_callback_t destroy) json_nothrow {
135 | json_destroy = destroy;
136 | }
137 | #endif
138 |
139 |
140 | void internalJSONNode::_set_mutex(void * mutex, bool unset) json_nothrow {
141 | if (unset) _unset_mutex(); //for reference counting
142 | mylock = mutex;
143 | if (mutex != 0){
144 | #ifdef JSON_MUTEX_MANAGE
145 | JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mutex);
146 | if (it == json_global(MUTEX_MANAGER).end()){
147 | json_global(MUTEX_MANAGER).insert(std::pair(mutex, 1));
148 | } else {
149 | ++it -> second;
150 | }
151 | #endif
152 | if (isContainer()){
153 | json_foreach(CHILDREN, myrunner){
154 | (*myrunner) -> set_mutex(mutex);
155 | }
156 | }
157 | }
158 | }
159 |
160 | void internalJSONNode::_unset_mutex(void) json_nothrow {
161 | #ifdef JSON_MUTEX_MANAGE
162 | if (mylock != 0){
163 | JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mylock);
164 | JSON_ASSERT_SAFE(it != json_global(MUTEX_MANAGER).end(), JSON_TEXT("Mutex not managed"), return;);
165 | --it -> second;
166 | if (it -> second == 0){
167 | JSON_ASSERT_SAFE(json_destroy, JSON_TEXT("You didn't register a destructor for mutexes"), return;);
168 | json_global(MUTEX_MANAGER).erase(it);
169 | }
170 | }
171 | #endif
172 | }
173 |
174 | #ifdef JSON_DEBUG
175 | #ifndef JSON_LIBRARY
176 | JSONNode internalJSONNode::DumpMutex(void) const json_nothrow {
177 | JSONNode mut(JSON_NODE);
178 | mut.set_name(JSON_TEXT("mylock"));
179 | #ifdef JSON_MUTEX_MANAGE
180 | if (mylock != 0){
181 | mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (long)mylock)));
182 | JSON_MAP(void *, unsigned int)::iterator it = json_global(MUTEX_MANAGER).find(mylock);
183 | if (it == json_global(MUTEX_MANAGER).end()){
184 | mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), JSON_TEXT("error"))));
185 | } else {
186 | mut.push_back(JSON_NEW(JSONNode(JSON_TEXT("references"), it -> second)));
187 | }
188 | } else {
189 | mut = (long)mylock;
190 | }
191 | #else
192 | mut = (long)mylock;
193 | #endif
194 | return mut;
195 | }
196 | #endif
197 | #endif
198 |
199 | #else
200 | #ifdef JSON_MUTEX_MANAGE
201 | #error You can not have JSON_MUTEX_MANAGE on without JSON_MUTEX_CALLBACKS
202 | #endif
203 | #endif
204 |
--------------------------------------------------------------------------------
/man/toJSON.Rd:
--------------------------------------------------------------------------------
1 | \name{toJSON}
2 | \alias{toJSON}
3 | \alias{toJSON,list-method}
4 | \alias{toJSON,ANY-method}
5 | \alias{toJSON,numeric-method}
6 | \alias{toJSON,integer-method}
7 | \alias{toJSON,integer,missing-method}
8 | \alias{toJSON,character-method}
9 | \alias{toJSON,logical-method}
10 | \alias{toJSON,hexmode-method}
11 | \alias{toJSON,matrix-method}
12 | \alias{toJSON,ANY-method}
13 | \alias{toJSON,name-method}
14 | \alias{toJSON,list-method}
15 | \alias{toJSON,NULL-method}
16 | \alias{toJSON,factor-method}
17 | \alias{toJSON,AsIs-method}
18 | \alias{toJSON,environment-method}
19 | \alias{toJSON,data.frame-method}
20 | \alias{toJSON,array-method}
21 | \alias{toJSON,function-method}
22 |
23 |
24 | \alias{emptyNamedList}
25 |
26 | \title{Convert an R object to a string in Javascript Object Notation}
27 | \description{
28 | This function and its methods convert an R object into a string
29 | that represents the object in Javascript Object Notation (JSON).
30 |
31 | The different methods try to map R's vectors to JSON arrays and
32 | associative arrays. There is ambiguity here as an R vector of length 1
33 | can be a JSON scalar or an array with one element. When there are
34 | names on the R vector, the descision is clearer.
35 | We have introduced the \code{emptyNamedList} variable to identify
36 | an empty list that has an empty names character vector and so
37 | maps to an associative array in JSON, albeit an empty one.
38 |
39 | Objects of class \code{AsIs} in R, i.e. that are enclosed in a call to
40 | \code{I()} are treated as containers even if they are of length 1.
41 | This allows callers to indicate the desired representation of an R "scalar"
42 | as an array of length 1 in JSON
43 | }
44 | \usage{
45 | toJSON(x, container = isContainer(x, asIs, .level),
46 | collapse = "\n", ..., .level = 1L,
47 | .withNames = length(x) > 0 && length(names(x)) > 0, .na = "null",
48 | .escapeEscapes = TRUE, pretty = FALSE, asIs = NA, .inf = " Infinity")
49 | }
50 | %- maybe also 'usage' for other objects documented here.
51 | \arguments{
52 | \item{x}{the R object to be converted to JSON format}
53 | \item{\dots}{additional arguments controlling the formatting of the
54 | JSON.
55 | }
56 | \item{container}{a logical value indicating whether to treat the
57 | object as a vector/container or a scalar and so represent it as an
58 | array or primitive in JavaScript.}
59 | \item{collapse}{a string that is used as the separator when combining the individual lines of the
60 | generated JSON content}
61 | \item{.level}{an integer value. This is not a parameter the caller is supposed to supply. It is a
62 | value that is passed in recursive calls to identify the top-level and sub-level serialization to JSON
63 | and so help to identify when a scalar needs to be in a container and when it is legitimate to
64 | output a scalar value directly.}
65 | \item{.withNames}{a logical value. If we are dealing with a named
66 | vector/list, we typically generate a JSON associative
67 | array/dictionary. If there are no names, we create a simple array.
68 | This argument allows us to explicitly control whether we use a
69 | dictionary or to ignore the names and use an array.
70 | }
71 | \item{.na}{a value to use when we encounter an \code{NA} value in the R
72 | objects. This allows the caller to convert these to whatever makes
73 | sense to them. For example, we might specify this as \code{"null"}
74 | and then the \code{NA} values will appear as \code{null} in the JSON
75 | output. One can also specify an unusual numeric value, e.g. -9999999
76 | to indicate a missing value!
77 | }
78 | \item{.escapeEscapes}{a logical value that controls how
79 | new line and tab characters are serialized. If this is \code{TRUE},
80 | we preserve them symbolically by escaping the \\.
81 | Otherwise, we replace them with their literal value.
82 | }
83 | \item{pretty}{a logical value that controls if extra processing is done
84 | on the result to make it indented for easier human-readability.
85 | At present, this reparses the generated JSON content and
86 | re-formats it (using libjson). This means that there
87 | can be three copies of the data in memory simultaneously -
88 | the original data, the JSON text and the pretty-printed
89 | version of the JSON text. For large objects, this can
90 | require a lot of memory.
91 | }
92 | \item{asIs}{a logical value that, if \code{TRUE} causes
93 | R vectors of length 1 to be represented as arrays in JSON,
94 | but if \code{FALSE} to be represented as scalars, where appropriate
95 | (i.e. not the top level of the JSON content). This avoids having
96 | to explicitly mark sub-elements in an R object as being of class
97 | \code{AsIs}.
98 | }
99 | \item{.inf}{how to represent infinity in JSON. This should be a string.}
100 | }
101 |
102 | \value{
103 | A string containing the JSON content.
104 | }
105 | \references{
106 | \url{http://www.json.org}
107 | }
108 | \author{Duncan Temple Lang }
109 |
110 | \seealso{
111 | \code{\link{fromJSON}}
112 | }
113 | \examples{
114 | toJSON(1:10)
115 | toJSON(rnorm(3))
116 | toJSON(rnorm(3), digits = 4)
117 |
118 | toJSON(c("Duncan", "Temple Lang"))
119 |
120 | toJSON(c(FALSE, FALSE, TRUE))
121 |
122 | # List of elements
123 | toJSON(list(1L, c("a", "b"), c(FALSE, FALSE, TRUE), rnorm(3)))
124 | # with digits controlling formatting of sub-elements
125 | toJSON(list(1L, c("a", "b"), c(FALSE, FALSE, TRUE), rnorm(3)),
126 | digits = 10)
127 |
128 | # nested lists
129 | toJSON(list(1L, c("a", "b"), list(c(FALSE, FALSE, TRUE), rnorm(3))))
130 |
131 | # with names
132 | toJSON(list(a = 1L, c("a", "b"), c(FALSE, FALSE, TRUE), rnorm(3)))
133 |
134 | setClass("TEMP", representation(a = "integer", xyz = "logical"))
135 | setClass("TEMP1", representation(one = "integer", two = "TEMP"))
136 |
137 | new("TEMP1", one = 1:10, two = new("TEMP", a = 4L, xyz = c(TRUE, FALSE)))
138 |
139 |
140 | toJSON(list())
141 | toJSON(emptyNamedList)
142 | toJSON(I(list("hi")))
143 | toJSON(I("hi"))
144 |
145 |
146 | x = list(list(),
147 | emptyNamedList,
148 | I(list("hi")),
149 | "hi",
150 | I("hi"))
151 | toJSON(x)
152 |
153 | # examples of specifying .withNames
154 | toJSON(structure(1:3, names = letters[1:3]))
155 | toJSON(structure(1:3, names = letters[1:3]), .withNames = FALSE)
156 |
157 |
158 | # Controlling NAs and mapping them to whatever we want.
159 | toJSON(c(1L, 2L, NA), .na = "null")
160 | toJSON(c(1L, 2L, NA), .na = -9999)
161 |
162 | toJSON(c(1, 2, pi, NA), .na = "null")
163 |
164 | toJSON(c(TRUE, FALSE, NA), .na = "null")
165 |
166 | toJSON(c("A", "BCD", NA), .na = "null")
167 |
168 | toJSON( factor(c("A", "B", "A", NA, "A")), .na = "null" )
169 |
170 | toJSON(list(TRUE, list(1, NA), NA), .na = "null")
171 |
172 |
173 |
174 | setClass("Foo", representation(a = "integer", b = "character"))
175 | obj = new("Foo", a = c(1L, 2L, NA, 4L), b = c("abc", NA, "def"))
176 | toJSON(obj)
177 | toJSON(obj, .na = "null")
178 |
179 | # hexmode example with .na ?
180 |
181 | toJSON(matrix(c(1, 2, NA, 4), 2, 2), .na = "null")
182 | toJSON(matrix(c(1, 2, NA, 4), 2, 2), .na = -9999999)
183 |
184 |
185 | x = '"foo\tbar\n\tagain"'
186 | cat(toJSON(x))
187 | cat(toJSON(list(x)))
188 |
189 | # if we want to expand the new lines and tab characters
190 | cat(toJSON(x), .escapeEscapes = FALSE)
191 |
192 |
193 | # illustration of the asIs argument
194 | cat(toJSON(list(a = 1, b = 2L, c = TRUE,
195 | d = c(1, 3),
196 | e = "abc"), asIs = TRUE))
197 |
198 | cat(toJSON(list(a = 1, b = 2L, c = TRUE,
199 | d = c(1, 3),
200 | e = "abc"), asIs = FALSE))
201 |
202 | # extra level
203 | cat(toJSON(list(a = c(x = 1), b = 2L, c = TRUE,
204 | d = list(1, 3),
205 | e = "abc"), asIs = FALSE, pretty = TRUE))
206 |
207 |
208 | # data frame by row as arrays
209 | twoRows = data.frame(a = 1:2, b = as.numeric(1:2))
210 | j = toJSON(twoRows, byrow = TRUE)
211 | r = data.frame(do.call(rbind, fromJSON(j)))
212 |
213 | # here we keep the names of the columns on each row
214 | # which allows us to round-trip the object back to R
215 | j = toJSON(twoRows, byrow = TRUE, colNames = TRUE)
216 | r = data.frame(do.call(rbind, fromJSON(j)))
217 | }
218 |
219 | \keyword{IO}
220 | \keyword{programming}
221 |
--------------------------------------------------------------------------------
/src/rparser.c:
--------------------------------------------------------------------------------
1 | #include "Rlibjson.h"
2 |
3 | typedef struct {
4 | int cumBytes;
5 | SEXP call;
6 | JSONSTREAM *stream;
7 | SEXP result;
8 |
9 | int simplify;
10 | int simplifyWithNames;
11 | SEXP nullValue;
12 |
13 | FILE *file;
14 | } RCallback;
15 |
16 | //#define R_DEBUG_STREAM 1
17 | //#define CHECK_CONTENT 1
18 | #ifdef CHECK_CONTENT
19 | static FILE *out = NULL;
20 | #endif
21 |
22 | void
23 | errorCB(void *ptr)
24 | {
25 | RCallback *data = (RCallback *) ptr;
26 | int num = 0;
27 | if(data)
28 | num = data->cumBytes;
29 |
30 | if(data->file)
31 | fclose(data->file);
32 |
33 | // if(data->stream)
34 | // json_delete_stream(data->stream);
35 | #ifdef CHECK_CONTENT
36 | if(out) {
37 | fclose(out); out = NULL;
38 | }
39 | #endif
40 |
41 | PROBLEM "failed to parse json at %d", num
42 | ERROR;
43 | }
44 |
45 |
46 | SEXP
47 | R_makeJSONRef(JSONNODE *node)
48 | {
49 | return(processJSONNode(node, json_type(node), 1, R_NilValue, 1, CE_NATIVE, NULL, GARBAGE));
50 | }
51 |
52 | void
53 | R_json_parser_callback(JSONNODE *node, void *userdata)
54 | {
55 | SEXP ans;
56 | RCallback *data = (RCallback*)userdata;
57 |
58 | SEXP tmp;
59 |
60 |
61 | tmp = processJSONNode(node, json_type(node), data->simplify, data->nullValue, data->simplifyWithNames,
62 | CE_NATIVE, NULL, GARBAGE);
63 |
64 | if(data->call == R_NilValue) {
65 | ans = tmp;
66 | } else {
67 | // SETCAR( CDR(e), ScalarInteger(json_type(node)));
68 | PROTECT(tmp);
69 | PROTECT(ans = tmp); // R_makeJSONRef(node));
70 | SETCAR( CDR(data->call), ans);
71 |
72 | ans = Rf_eval(data->call, R_GlobalEnv);
73 | UNPROTECT(2);
74 | }
75 | data->result = ans;
76 | R_PreserveObject(data->result);
77 | }
78 |
79 |
80 |
81 | static int
82 | getData(SEXP call, JSONSTREAM *stream, int *numBytes)
83 | {
84 | SEXP r_str;
85 | int num;
86 |
87 |
88 | PROTECT(r_str = Rf_eval(call, R_GlobalEnv));
89 | if( (num = Rf_length(r_str)) ) {
90 | const char *ptr = CHAR(STRING_ELT(r_str, 0));
91 | int len = strlen(ptr);
92 |
93 | *numBytes += len;
94 | ptr = strdup(ptr); //xxx
95 | #ifdef CHECK_CONTENT
96 | if(!out)
97 | out = fopen("/tmp/check.json", "w");
98 | #endif
99 |
100 |
101 | #if R_DEBUG_STREAM
102 | fprintf(stderr, "# %d to %d\n '%s'\n", (int) strlen(ptr), *numBytes, ptr);
103 | #endif
104 |
105 | #ifdef CHECK_CONTENT
106 | fprintf(out, "%s", ptr);
107 | #endif
108 |
109 | json_stream_push(stream, ptr);
110 |
111 | } else {
112 | #if 0
113 | fprintf(stderr, "finished reading data with %d bytes\n", *numBytes);
114 | #endif
115 | }
116 | UNPROTECT(1);
117 |
118 | return(num > 0);
119 | }
120 |
121 |
122 | int
123 | readFileData(FILE *f, JSONSTREAM *stream, int *numBytes)
124 | {
125 | char buffer[1024];
126 | size_t num;
127 | int len = sizeof(buffer)/sizeof(buffer[0]) - 1;
128 | num = fread(buffer, 1, len - 2, f);
129 | *numBytes += num;
130 | buffer[num] = '\0';
131 |
132 | json_stream_push(stream, strdup(buffer));
133 | #ifdef R_DEBUG_STREAM
134 | fprintf(stderr, "Read (%d) %d/%d bytes\n'%s'\n", (int) strlen(buffer), (int) num, *numBytes, buffer);
135 | #endif
136 | return(num == len - 2);
137 | }
138 |
139 |
140 | typedef void (*ParserCallback)(JSONNODE *, void *);
141 |
142 | SEXP
143 | R_json_parser_init_from_con(SEXP conCall, SEXP cbCall,
144 | SEXP simplify, SEXP nullValue, SEXP simplifyWithNames)
145 | {
146 | JSONSTREAM *stream;
147 | RCallback cb;
148 | int nprotect = 0;
149 | ParserCallback callback;
150 |
151 | /* If the callback is an external pointer, use that as the callback for the top-level JSONNODE objects */
152 | if(TYPEOF(cbCall) == EXTPTRSXP)
153 | callback = R_ExternalPtrAddr(cbCall);
154 | else /* otherwise use our own callback to process the JSONNODE */
155 | callback = R_json_parser_callback;
156 |
157 | stream = json_new_stream(callback, errorCB, &cb);
158 | if(!stream) {
159 | PROBLEM "Couldn't create json stream"
160 | ERROR;
161 | }
162 |
163 | cb.stream = stream;
164 | cb.cumBytes = 0;
165 | cb.result = NULL;
166 | cb.simplify = INTEGER(simplify)[0];
167 | cb.simplifyWithNames = INTEGER(simplifyWithNames)[0];
168 | cb.nullValue = nullValue;
169 | cb.file = NULL;
170 |
171 | if(TYPEOF(cbCall) == CLOSXP) {
172 | PROTECT(cb.call = allocVector(LANGSXP, 2));
173 | SETCAR(cb.call, cbCall);
174 | nprotect++;
175 | } else
176 | cb.call = cbCall; // expression.
177 |
178 | if(TYPEOF(conCall) == STRSXP) {
179 | FILE *f;
180 | f = fopen(CHAR(STRING_ELT(conCall, 0)), "r");
181 | if(!f) {
182 | json_delete_stream(stream);
183 | PROBLEM "cannot open JSON file %s", CHAR(STRING_ELT(conCall, 0))
184 | ERROR;
185 | }
186 | cb.file = f;
187 |
188 | while(readFileData(f, stream, &(cb.cumBytes))) { }
189 | fclose(f);
190 | } else {
191 | while(getData(conCall, stream, &(cb.cumBytes))) { }
192 | }
193 |
194 | if(nprotect)
195 | UNPROTECT(nprotect);
196 |
197 | #ifdef CHECK_CONTENT
198 | if(out) {
199 | fclose(out); out = NULL;
200 | }
201 | #endif
202 |
203 | json_delete_stream(stream);
204 |
205 | return(cb.result ? cb.result : R_NilValue);
206 | }
207 |
208 |
209 |
210 |
211 | #if 1
212 |
213 | SEXP top = NULL;
214 |
215 | void
216 | R_json_cb_test_stream(JSONNODE *node, void *userdata)
217 | {
218 | // fprintf(stderr, "Finished parsing\n");
219 | top = processJSONNode(node, 0, 1, R_NilValue, 1, CE_NATIVE, NULL, GARBAGE);
220 | R_PreserveObject(top);
221 | }
222 |
223 | static int total = 0;
224 | int
225 | test_get_data(FILE *f, JSONSTREAM *stream)
226 | {
227 | char buffer[1024];
228 | size_t num;
229 | int len = sizeof(buffer)/sizeof(buffer[0]) - 1;
230 | num = fread(buffer, 1, len - 2, f);
231 | total += num;
232 | buffer[num] = '\0';
233 |
234 | json_stream_push(stream, strdup(buffer));
235 | #ifdef R_DEBUG_STREAM
236 | fprintf(stderr, "Read (%d) %d/%d bytes\n'%s'\n", (int) strlen(buffer), (int) num, total, buffer);
237 | #endif
238 | return(num == len - 2);
239 | }
240 |
241 | SEXP
242 | R_json_parser_test_stream(SEXP r_filename)
243 | {
244 | JSONSTREAM *stream;
245 | FILE *fileptr;
246 |
247 | fileptr = fopen(CHAR(STRING_ELT(r_filename, 0)), "r");
248 | if(!fileptr) {
249 | PROBLEM "cannot open file"
250 | ERROR;
251 | }
252 |
253 | stream = json_new_stream(R_json_cb_test_stream, errorCB, NULL);
254 | if(!stream) {
255 | PROBLEM "Couldn't create json stream"
256 | ERROR;
257 | }
258 |
259 | json_stream_push(stream, "{ \"a\": [1, 2, 3]}[true, false]");
260 |
261 | while(test_get_data(fileptr, stream)) { }
262 | json_stream_push(stream, "");
263 |
264 | fclose(fileptr);
265 | json_delete_stream(stream);
266 |
267 | return(R_NilValue);
268 | }
269 |
270 |
271 | SEXP
272 | R_json_parser_test_stream_str(SEXP r_filename)
273 | {
274 | JSONSTREAM *stream;
275 | const char *str = CHAR(STRING_ELT(r_filename, 0));
276 |
277 | stream = json_new_stream(R_json_cb_test_stream, errorCB, NULL);
278 | if(!stream) {
279 | PROBLEM "Couldn't create json stream"
280 | ERROR;
281 | }
282 |
283 | json_stream_push(stream, str);
284 |
285 | R_ReleaseObject(top);
286 | return(top);
287 | // return(R_NilValue);
288 | }
289 |
290 |
291 | SEXP
292 | R_json_parser_test_stream_chunk(SEXP r_filename)
293 | {
294 | JSONSTREAM *stream;
295 | const char *str = CHAR(STRING_ELT(r_filename, 0));
296 |
297 | stream = json_new_stream(R_json_cb_test_stream, errorCB, NULL);
298 | if(!stream) {
299 | PROBLEM "Couldn't create json stream"
300 | ERROR;
301 | }
302 |
303 | int len = strlen(str), cur = 0, blocksize = 100;
304 | int count = 0;
305 | char tmp[blocksize + 1];
306 | tmp[blocksize] = '\0';
307 | while(cur < len) {
308 | strncpy(tmp, str + cur, blocksize);
309 |
310 | #ifdef R_DEBUG_STREAM
311 | fprintf(stderr, "%d) %s\n", count++, tmp);
312 | #endif
313 | json_stream_push(stream, strdup(tmp));
314 | cur += blocksize;
315 | }
316 |
317 | json_delete_stream(stream);
318 | R_ReleaseObject(top);
319 | return(top);
320 | }
321 |
322 |
323 |
324 | SEXP
325 | R_json_parser_test_stream_chunk_con(SEXP r_getData)
326 | {
327 | JSONSTREAM *stream;
328 |
329 | stream = json_new_stream(R_json_cb_test_stream, errorCB, NULL);
330 | if(!stream) {
331 | PROBLEM "Couldn't create json stream"
332 | ERROR;
333 | }
334 |
335 | int n = 0;
336 | while(getData(r_getData, stream, &n)) {}
337 |
338 | json_delete_stream(stream);
339 |
340 | R_ReleaseObject(top);
341 | return(top);
342 | }
343 |
344 |
345 | #endif
346 |
--------------------------------------------------------------------------------
/inst/doc/missingValues.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | JSON, null and NA
4 |
5 |
16 | Duncan Temple Lang University of California at Davis Department of Statistics
Limitations of JSON regarding the meaning of null
17 | JavaScript Object Notation (JSON) is a convenient format for
18 | representing data and facilitates transferring data between
19 | applications. It is widely used in different applications, Web
20 | services and other contexts. As such, it is useful for R to be able
21 | to import and export data in this format. Unfortunately, JSON is a
22 | little too simple and cannot faithfully represent all of the types and
23 | values in R. Most specifically, there is no way to support NA ,
24 | Inf or NaN . Typically, these
25 | values are represented in JSON as "null". However, that is also used
26 | to represent a null object. So there is ambiguity in how we interpret
27 | null in JSON.
28 | We don't know whether it is NA , NaN, Inf or NULL in R.
29 | This many-to-one mapping results in a loss of information.
30 |
31 | In spite of the shortcomings of the format, we can still work with
32 | JSON. However, how we convert null values to R and how we
33 | convert NA values from R is not automatic and uniquely defined.
34 | For that reason, the caller must control how these are mapped.
35 | We provide some mechanisms to do this in the
36 | fromJSON() and toJSON() functions.
37 |
38 | When converting R objects to JSON via toJSON() ,
39 | one can specify how to map NA values to JSON.
40 | One provides a value for the parameter .na
41 | to control this.
42 | For example, suppose we want to transform the R list
43 |
44 | x = list(1, 2, NA, c(TRUE, NA, FALSE))
45 |
46 |
47 |
48 | to JSON and want NA values to map to null.
49 | We can achieve this with
50 |
51 | toJSON(x, .na = "null")
52 |
53 |
54 |
55 |
56 | In some applications, we represent a missing value with a fixed number that is unlikely
57 | to occur in actual data, e.g. -99999.
58 | We can map NA values to such a number with
59 |
60 | toJSON(list(1, 2, list(NA)), .na = -99999)
61 |
62 |
63 |
64 |
65 | Now consider round-tripping NA , e.g.
66 |
67 | o = toJSON ( NA )
68 |
69 | [1] "[ null ]"
70 |
71 | fromJSON( o )
72 |
73 | [[1]]
74 | NULL
75 |
76 |
77 |
78 |
79 | So we have lost information.
80 |
81 | We can correct this loss of information by
82 | specifying how to map null values in JSON
83 | to R values. We use the nullValue
84 |
85 | fromJSON( toJSON ( NA ), nullValue = NA)
86 |
87 |
88 |
89 | Again, here we as the caller of fromJSON()
90 | (and also toJSON() ) we are providing
91 | information about how to transfer the null value from JSON to R.
92 | Only we know what it means in this case.
93 | If we knew that the null corresponded to Inf ,
94 | we could specify that:
95 |
96 | fromJSON( "[null]", nullValue = Inf)
97 |
98 |
99 |
100 |
101 | Where this mechanism breaks down is when we have multiple
102 | null values in our JSON content and they map to different
103 | R values, e.g. NULL , NA and NaN.
104 | The nullValue parameter is a global replacement for
105 | null entries in the JSON. To adaptively process these null
106 | entries in a context specific manner, we have to use a customized
107 | parser. We can do this by providing an R function as the
108 | callback handler for the JSON parser.
109 |
110 |
--------------------------------------------------------------------------------
/Changes:
--------------------------------------------------------------------------------
1 |
2 | RJSONIO
3 |
4 |
5 | Version 1.3-1
6 |
7 | * Fix for simplify = TRUE and getting the correct element type. Problem identified by Ivan Yevshin
8 |
9 |
10 |
11 | Version 1.3-0
12 |
13 |
14 |
15 | Version 1.2-1
16 |
17 | * Fix for toJSON(character(0)) in a hierarchy. Found by Kevin Ushey.
18 |
19 | * Method for toJSON() for function.
20 |
21 |
22 |
23 | Version 1.2-0
24 |
25 | * Included updated code from libjson which is used if one does not have libjson installed.
26 |
27 | * Method for toJSON() for function.
28 |
29 |
30 |
31 | Version 1.1-0
32 |
33 | * Inf in R mapped to Infinity in JSON. This is customizable.
34 |
35 | * Fixed dQuote() to handle empty vectors and not create a vector of length 1. This allows toJSON() to work correctly. Thanks to Murat Tasan for identifying the larger problem.
36 |
37 | * Added toJSON() method for data.frame that allows output by row and also handles the cases where the number of rows is 1. Fix from Joe Cheng.
38 |
39 |
40 |
41 | Version 1.0-4
42 |
43 | * Updates for toJSON() for handling array, table and function objects. These don't fail (with infinite recursion) but may not be what is desired for a particular application. Identified by Stavros Macrakis
44 |
45 | * Added a warning about +/- Inf values in a vector.
46 |
47 |
48 |
49 |
50 | Version 1.0-3
51 |
52 | * Removed the limit on the size of the string that was on by default in libjson (via JSON_SECURITY_MAX_STRING_LENGTH in JSONOptions.h). Issue identified by Adrian Alexa.
53 |
54 |
55 |
56 | Version 1.1-0
57 |
58 | * Escape \b \r and \f when exporting strings from R to JSON. Thanks to Joe Cheng.
59 |
60 | * Fix use of snprintf in libjson code to remove the std:: qualifier.
61 |
62 | *
63 |
64 |
65 |
66 | Version 1.0-1
67 |
68 | * Fixes to the libjson code to make it compile on different machines.
69 |
70 |
71 |
72 | Version 1.0-0
73 |
74 | * toJSON() for S4 objects adds , separating slots that was omitted.
75 |
76 | * Force the values of container and .withNames in the toJSON() generic to fix a bug that caused vectors of length 1 with names to appear as scalars and so lose the names. Thanks to Igor Elbert.
77 |
78 | * Added stringFun as parameter in fromJSON() to allow processing of each string value as it is encountered. This can be used to convert strings to arbitrary R objects.
79 |
80 | * Initial implementation of parsing streaming data from a file or connection. Unreliable at present.
81 |
82 | * Changes to libjson source for missing arguments in C++ macros.
83 |
84 |
85 |
86 |
87 | Version 0.99-0
88 |
89 | * Implemented reading JSON from a connection using a "pull" mechanism which reads from the connection as more content is needed by the parser. This avoids having all the content in memory before parsing.
90 |
91 | * Incorporated libjson_7.6.0 which has support for escaped content (e.g. \x).
92 |
93 |
94 |
95 | Version 0.98-1
96 |
97 | * Compilation issues fixed for new libjson code on Solaris and Windows. Thanks to Brian Ripley for Solaris corrections.
98 |
99 |
100 |
101 | Version 0.98-0
102 |
103 | * Update default libjson code to version 7.4.0.
104 |
105 | * Changes to configuration to allow the use of a version of libjson that is not installed but not in the RJSONIO package directory itself. Use the environment variable LIBJSON_SRC.
106 |
107 | * Configuration determines version of libjson and adapts compilation flags accordingly.
108 |
109 |
110 |
111 | Version 0.97-0
112 |
113 | * Add isValidJSON() to test whether the JSON content is valid. Suggested by Jeroen Ooms.
114 |
115 |
116 |
117 | Version 0.96-0
118 |
119 | * Added encoding argument for fromJSON() and that encoding is preserved on the resulting strings. Thanks to Tony Breyal for pointing out the issue.
120 |
121 |
122 |
123 | Version 0.95-0
124 |
125 | * In fromJSON(), when nullValue is (the logical NA) we attempt to simplify vectors with JSON null values.
126 |
127 |
128 |
129 | Version 0.94-0
130 |
131 | * Added simplifyWithNames to fromJSON() for controlling whether we attempt to collapse collections of values read from JSON if they have names. This can be used to collapse unnamed vectors, but leave named lists that would otherwise be collapsed to vectors.
132 |
133 |
134 |
135 | Version 0.93-0
136 |
137 | * Added support in fromJSON() for collapsing particular types of elements, i.e. logicals, numbers or characters via StrictLogical, StrictNumeric and StrictCharacter. This allows "strict" collapsing, but for different types, while leaving others as lists. These can be combined.
138 |
139 |
140 |
141 | Version 0.92-0
142 |
143 | * Added to the ability to control whether we simplify the content using simplify = Strict or or .
144 |
145 |
146 |
147 | Version 0.91-0
148 |
149 | * Added .escapeEscapes to toJSON() to allow the caller to preserve new lines and tabs symbolically or not. Thanks to Antonio Piccolboni for the report about the issue.
150 |
151 |
152 |
153 | Version 0.9-0
154 |
155 | * Added .na parameter to the toJSON() function and methods so that the caller can control how values are mapped to JSON. This defaults to "null" so that the resulting JSON is well-formed. However, users should explicitly think about how values (and Inf and NaN) are mapped to JSON in order to avoid ambiguity and faithfully serialize their data in a meaningful manner.
156 |
157 | * Added a nullValue parameter to fromJSON() to allow the caller to provide an R object that will be used when we encounter a JSON null value. This can be used for example to map null to in R.
158 |
159 | * Added more support for simplifying lists to vectors of different types. In the future, I might add a simplify = "strict" mode that would only collapse vectors if all the elements were of the same type, not just compatible types. In other words, [true, 1 ] would not collapse to c(1, 1) in R.
160 |
161 |
162 |
163 | Version 0.8-2
164 |
165 | * Corrected what toJSON() does with new lines (\n) and avoid the escaping of the \. Thanks to Antonio Piccolboni for the report.
166 |
167 |
168 |
169 | Version 0.8-1
170 |
171 | * Corrections to the libjson C/C++ code from Brian Ripley.
172 |
173 |
174 |
175 | Version 0.8-0
176 |
177 | * Added a .withNames parameter to toJSON() so that the caller can explicitly control whether an R object with names is written as an associative array or as a simple array.
178 |
179 |
180 | * Added a simplify parameter to fromJSON() that controls whether we collapse lists of homogeneous element types to an R vector.
181 |
182 |
183 |
184 | Version 0.7-3
185 |
186 | * Added .withNames parameter for toJSON() which allows the caller to control whether we ignore or use any names. Defaults to use the names if they are present.
187 |
188 |
189 |
190 | Version 0.7-3
191 |
192 | * Honor the collapse argument in more places to allow avoiding new line characters being inserted.
193 |
194 |
195 |
196 | Version 0.7-2
197 |
198 | * Copied compiler flags for libjson code into Makevars.win
199 |
200 |
201 |
202 | Version 0.7-1
203 |
204 | * Correction for toJSON() method for handling of \ in strings so that they round-trip and work in other JSON tools. Thanks to Patrick Perry.
205 |
206 |
207 |
208 | Version 0.7-0
209 |
210 | * Round-tripping from JSON to R and back behaves a lot more consistently. Thanks to Kevin Coombes for the examples/tests. Next, we will add functionality to customize serialization of .
211 |
212 | * Change to the default value of container of toJSON() so that this is when at the top-level or initial call to toJSON().
213 |
214 | * We now know the type of the top-most node so can correctly handle empty associative arrays, etc.
215 |
216 |
217 |
218 | Version 0.6-0
219 |
220 | * Updated the libjson source code in the package to libjson 7.0.1. This removes a bug in parsing numbers of the form 3.14E4. Found by Jeroen Ooms.
221 |
222 | * Added configuration so that we can use a libjson installed on the system. This avoids issues of using older versions of libjson shipped with this package.
223 |
224 |
225 |
226 | Version 0.5-0
227 |
228 | * Enhancements to disambiguate serializing empty lists from as empty arrays or associative arrays. See also emptyNamedList to map to {}.
229 |
230 | * Method for identifying an R scalar that should be mapped to a JSON array via the AsIs class and I() function.
231 |
232 | * toJSON() honors these also ensuring transformation from JSON to R to JSON preserves the same structure.
233 |
234 | * Both changes thanks to suggestions by Keith Bonawitz.
235 |
236 |
237 |
238 | Version 0.4-2
239 |
240 | * Fixed significant memory leaks found by Keith Bonawitz
241 |
242 |
243 |
244 | Version 0.4-1
245 |
246 | * Tidied up C++ code from libjsonio to avoid a warning about no argument to initializeFetch() when compiling the C++ code.
247 |
248 | * Fixed a C routine (R_fromJSON) that did not return a value.
249 |
250 |
251 |
252 | Version 0.4-0
253 |
254 | * fromJSON() now uses libjson for the native parsing and a C routine to transform the resulting tree into R. This leads to a considerable speedup in parsing documents, approximately a factor of 200 over the customizable, event driven mechanism in earlier versions and still available in this package via the basicJSONHandler() function and fromJSON().
255 |
256 |
257 |
258 | Version 0.3-4
259 |
260 | * Refinement of handling large integers that do not fit into a 4 byte int. Tested on Windows.
261 |
262 |
263 |
264 | Version 0.3-3
265 |
266 | * Handle large integers that do not fit into a 4 byte int. Return as numeric values.
267 |
268 |
269 |
270 | Version 0.3-1
271 |
272 | * Convert factors to character vectors in toJSON() and then serialize.
273 |
274 |
275 |
276 | Version 0.2-4
277 |
278 | * Handles UTF-8 content as input. We convert the text to raw and then integer values.
279 |
280 |
281 |
282 | Version 0.2-3
283 |
284 | * (Minor) Change to the C code to make it compile on Windows.
285 |
286 |
287 |
288 | Version 0.2-2
289 |
290 | * named atomic/primitive vectors serialized as associative arrays rather than simple arrays.
291 |
292 |
293 |
294 | Version 0.2-1
295 |
296 | * names on R objects from associative arrays from JSON were in reverse order.
297 |
298 |
299 |
300 | Version 0.2-0
301 |
302 | * Scalar, by default, values are represented in JSON as scalars and not arrays of length 1. One can control this via the container parameter in toJSON().
303 |
304 |
305 |
--------------------------------------------------------------------------------