Merge changes from 3.16 and below into libcom/master

This commit is contained in:
Andrew Johnson
2017-11-01 16:11:58 -05:00
39 changed files with 4556 additions and 1271 deletions

View File

@@ -79,6 +79,7 @@ include $(LIBCOM)/error/RULES
include $(LIBCOM)/flex/RULES
include $(LIBCOM)/misc/RULES
include $(LIBCOM)/osi/RULES
include $(LIBCOM)/yajl/RULES
# Can't use EXPAND as generated headers must appear
# in O.Common, but EXPAND emits rules for O.$(T_A)

View File

@@ -31,6 +31,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,C)
typedef int osiSockIoctl_t;
typedef socklen_t osiSocklen_t;
typedef int osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE)

View File

@@ -35,6 +35,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,C)
typedef int osiSockIoctl_t;
typedef socklen_t osiSocklen_t;
typedef int osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE)

View File

@@ -42,6 +42,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,C)
typedef int osiSockIoctl_t;
typedef socklen_t osiSocklen_t;
typedef char osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE)

View File

@@ -28,6 +28,7 @@
#define socket_ioctl(A,B,C) ioctlsocket(A,B,C)
typedef u_long FAR osiSockIoctl_t;
typedef int osiSocklen_t;
typedef BOOL osiSockOptMcastLoop_t;
#ifndef SHUT_RD
# define SHUT_RD SD_RECEIVE

View File

@@ -34,6 +34,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,C)
typedef int osiSockIoctl_t;
typedef int osiSocklen_t;
typedef int osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE&&(FD)>=0)
#ifndef SHUT_RD
#define SHUT_RD 0

View File

@@ -36,6 +36,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,C)
typedef int osiSockIoctl_t;
typedef socklen_t osiSocklen_t;
typedef int osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE)

View File

@@ -32,6 +32,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,C)
typedef int osiSockIoctl_t;
typedef socklen_t osiSocklen_t;
typedef int osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE)

View File

@@ -42,6 +42,7 @@ typedef int osiSockIoctl_t;
#else
typedef int osiSocklen_t;
#endif
typedef char osiSockOptMcastLoop_t;
#define DOES_NOT_ACCEPT_ZERO_LENGTH_UDP

View File

@@ -65,6 +65,7 @@ typedef int SOCKET;
#define socket_ioctl(A,B,C) ioctl(A,B,(int)C)
typedef int osiSockIoctl_t;
typedef int osiSocklen_t;
typedef int osiSockOptMcastLoop_t;
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE&&(FD)>=0)

View File

@@ -1,13 +0,0 @@
record(ai, "alarm") {
field(HIGH, 1)
field(HSV, MINOR)
field(HIHI, 2)
field(HHSV, MAJOR)
field(FLNK, "latch")
}
record(calc, "latch") {
field(INPA, "alarm NPP MS")
field(INPB, "latch NPP MS")
field(CALC, "A")
}

View File

@@ -1,169 +0,0 @@
/*************************************************************************\
* Copyright (c) 2017 UChicago Argonne LLC, as operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <string.h>
#include "dbAccess.h"
#include "dbStaticLib.h"
#include "dbTest.h"
#include "dbUnitTest.h"
#include "errlog.h"
#include "registryFunction.h"
#include "subRecord.h"
#include "testMain.h"
static
void checkDtyp(const char *rec)
{
char dtyp[16];
strcpy(dtyp, rec);
strcat(dtyp, ".DTYP");
testdbGetFieldEqual(dtyp, DBF_LONG, 0); /* Soft Channel = 0 */
}
static
void checkInput(const char *rec, int value)
{
char proc[16];
testDiag("Checking record '%s'", rec);
strcpy(proc, rec);
strcat(proc, ".PROC");
testdbPutFieldOk(proc, DBF_CHAR, 1);
testdbGetFieldEqual(rec, DBF_LONG, value);
}
static
void testGroup0(void)
{
const char ** rec;
const char * records[] = {
"ai0", "bi0", "di0", "ii0", "li0", "lsi0", "mi0", "si0", NULL
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
testdbPutFieldOk("source", DBF_LONG, 1);
for (rec = records; *rec; rec++) {
checkInput(*rec, 1);
checkDtyp(*rec);
}
testdbPutFieldOk("source", DBF_LONG, 0);
for (rec = records; *rec; rec++) {
checkInput(*rec, 0);
}
}
static
void testGroup1(void)
{
const char ** rec;
const char * records[] = {
"bi1",
"ai1", "di1", "ii1", "li1", "lsi1", "mi1", "si1", NULL
};
int init = 1; /* bi1 initializes to 1 */
testDiag("============ Starting %s ============", EPICS_FUNCTION);
for (rec = records; *rec; rec++) {
checkInput(*rec, init);
init = 9; /* remainder initialize to 9 */
}
}
int dest;
static
long destSubr(subRecord *prec)
{
dest = prec->val;
return 0;
}
static
void checkOutput(const char *rec, int value)
{
testDiag("Checking record '%s'", rec);
testdbPutFieldOk(rec, DBF_LONG, value);
testOk(dest == value, "value %d output -> %d", value, dest);
}
static
void testGroup2(void)
{
const char ** rec;
const char * records[] = {
"ao0", "bo0", "io0", "lo0", "lso0", "mo0", "so0", NULL,
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
for (rec = records; *rec; rec++) {
checkOutput(*rec, 1);
checkDtyp(*rec);
}
checkOutput("do0.B0", 1);
checkDtyp("do0");
for (rec = records; *rec; rec++) {
checkOutput(*rec, 0);
}
checkOutput("do0.B0", 0);
}
static
void testGroup3(void)
{
const char ** rec;
const char * records[] = {
"ao1", "bo1", "do1.B0", "io1", "lo1", "lso1", "mo1", "so1", NULL,
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
for (rec = records; *rec; rec++) {
checkOutput(*rec, 0);
}
}
void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
MAIN(softTest)
{
testPlan(114);
testdbPrepare();
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
recTestIoc_registerRecordDeviceDriver(pdbbase);
registryFunctionAdd("destSubr", (REGISTRYFUNCTION) destSubr);
testdbReadDatabase("softTest.db", NULL, NULL);
eltc(0);
testIocInitOk();
eltc(1);
testGroup0();
testGroup1();
testGroup2();
testGroup3();
testIocShutdownOk();
testdbCleanup();
return testDone();
}

View File

@@ -1,227 +0,0 @@
# Group 0 are input records with INP being a DB link to 'source'.
# Processing them reads that value.
record(longin, "source") {}
record(ai, "ai0") {
field(DTYP, "Soft Channel")
field(INP, "source")
}
record(bi, "bi0") {
field(DTYP, "Soft Channel")
field(INP, "source")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64in, "ii0") {
field(DTYP, "Soft Channel")
field(INP, "source")
}
record(longin, "li0") {
field(DTYP, "Soft Channel")
field(INP, "source")
}
record(mbbiDirect, "di0") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(INP, "source")
}
record(mbbi, "mi0") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(INP, "source")
field(ZRST, "Zero")
field(ONST, "One")
field(TWST, "Two")
field(THST, "Three")
field(FRST, "Four")
field(FVST, "Five")
field(SXST, "Six")
field(SVST, "Seven")
field(EIST, "Eight")
field(NIST, "Nine")
field(TEST, "Ten")
field(ELST, "Eleven")
field(TWST, "Twelve")
field(TTST, "Thirteen")
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lsi, "lsi0") {
field(DTYP, "Soft Channel")
field(SIZV, 40)
field(INP, "source")
}
record(stringin, "si0") {
field(DTYP, "Soft Channel")
field(INP, "source")
}
# Group 1 are input records with INP being a non-zero constant.
# Processing them succeeds but does not change VAL.
record(ai, "ai1") {
field(DTYP, "Soft Channel")
field(INP, {const:9})
}
record(bi, "bi1") {
field(DTYP, "Soft Channel")
field(INP, {const:1})
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64in, "ii1") {
field(DTYP, "Soft Channel")
field(INP, {const:9})
}
record(longin, "li1") {
field(DTYP, "Soft Channel")
field(INP, {const:9})
}
record(mbbiDirect, "di1") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(INP, {const:9})
}
record(mbbi, "mi1") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(INP, {const:9})
field(ZRST, "Zero")
field(ONST, "One")
field(TWST, "Two")
field(THST, "Three")
field(FRST, "Four")
field(FVST, "Five")
field(SXST, "Six")
field(SVST, "Seven")
field(EIST, "Eight")
field(NIST, "Nine")
field(TEST, "Ten")
field(ELST, "Eleven")
field(TWST, "Twelve")
field(TTST, "Thirteen")
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lsi, "lsi1") {
field(DTYP, "Soft Channel")
field(SIZV, 40)
field(INP, {const:"9"})
}
record(stringin, "si1") {
field(DTYP, "Soft Channel")
field(INP, {const:"9"})
}
# Group 2 are output records with OUT being a DB link to 'dest' with PP.
# Putting a value to them writes that value to 'dest'.
record(sub, "dest") {
field(SNAM, "destSubr")
}
record(ao, "ao0") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(bo, "bo0") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64out, "io0") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(longout, "lo0") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
record(mbboDirect, "do0") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest PP")
}
record(mbbo, "mo0") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest PP")
field(ZRST, "Zero")
field(ONST, "One")
field(TWST, "Two")
field(THST, "Three")
field(FRST, "Four")
field(FVST, "Five")
field(SXST, "Six")
field(SVST, "Seven")
field(EIST, "Eight")
field(NIST, "Nine")
field(TEST, "Ten")
field(ELST, "Eleven")
field(TWST, "Twelve")
field(TTST, "Thirteen")
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lso, "lso0") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
field(SIZV, 40)
}
record(stringout, "so0") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
# Group 3 are output records with OUT being empty (a constant link).
# Putting a value to them must succeed.
record(ao, "ao1") {
field(DTYP, "Soft Channel")
}
record(bo, "bo1") {
field(DTYP, "Soft Channel")
field(ZNAM, "Zero")
field(ONAM, "One")
}
record(int64out, "io1") {
field(DTYP, "Soft Channel")
}
record(longout, "lo1") {
field(DTYP, "Soft Channel")
}
record(mbboDirect, "do1") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
}
record(mbbo, "mo1") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(ZRST, "Zero")
field(ONST, "One")
field(TWST, "Two")
field(THST, "Three")
field(FRST, "Four")
field(FVST, "Five")
field(SXST, "Six")
field(SVST, "Seven")
field(EIST, "Eight")
field(NIST, "Nine")
field(TEST, "Ten")
field(ELST, "Eleven")
field(TWST, "Twelve")
field(TTST, "Thirteen")
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
record(lso, "lso1") {
field(DTYP, "Soft Channel")
field(SIZV, 40)
}
record(stringout, "so1") {
field(DTYP, "Soft Channel")
}

17
src/yajl/RULES Normal file
View File

@@ -0,0 +1,17 @@
#*************************************************************************
# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
# This is a Makefile fragment, see src/libCom/Makefile.
# Ensure epicsVersion.h gets built first
yajl$(DEP): $(COMMON_DIR)/epicsVersion.h
yajl_alloc$(DEP): $(COMMON_DIR)/epicsVersion.h
yajl_buf$(DEP): $(COMMON_DIR)/epicsVersion.h
yajl_encode$(DEP): $(COMMON_DIR)/epicsVersion.h
yajl_gen$(DEP): $(COMMON_DIR)/epicsVersion.h
yajl_lex$(DEP): $(COMMON_DIR)/epicsVersion.h
yajl_parser$(DEP): $(COMMON_DIR)/epicsVersion.h

View File

@@ -1,37 +1,22 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#define epicsExportSharedSymbols
@@ -51,9 +36,6 @@ yajl_status_to_string(yajl_status stat)
case yajl_status_client_canceled:
statStr = "client canceled parse";
break;
case yajl_status_insufficient_data:
statStr = "eof was met before the parse could complete";
break;
case yajl_status_error:
statStr = "parse error";
break;
@@ -63,15 +45,12 @@ yajl_status_to_string(yajl_status stat)
yajl_handle
yajl_alloc(const yajl_callbacks * callbacks,
const yajl_parser_config * config,
const yajl_alloc_funcs * afs,
yajl_alloc_funcs * afs,
void * ctx)
{
unsigned int allowComments = 0;
unsigned int validateUTF8 = 0;
yajl_handle hand = NULL;
yajl_alloc_funcs afsBuffer;
/* first order of business is to set up memory allocation routines */
if (afs != NULL) {
if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
@@ -84,65 +63,108 @@ yajl_alloc(const yajl_callbacks * callbacks,
}
hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t));
if (hand == NULL) {
return NULL;
}
/* copy in pointers to allocation routines */
memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
if (config != NULL) {
allowComments = config->allowComments;
validateUTF8 = config->checkUTF8;
}
hand->callbacks = callbacks;
hand->ctx = ctx;
hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8);
hand->lexer = NULL;
hand->bytesConsumed = 0;
hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
hand->flags = 0;
yajl_bs_init(hand->stateStack, &(hand->alloc));
yajl_bs_push(hand->stateStack, yajl_state_start);
yajl_bs_push(hand->stateStack, yajl_state_start);
return hand;
}
int
yajl_config(yajl_handle h, yajl_option opt, ...)
{
int rv = 1;
va_list ap;
va_start(ap, opt);
switch(opt) {
case yajl_allow_comments:
case yajl_dont_validate_strings:
case yajl_allow_trailing_garbage:
case yajl_allow_multiple_values:
case yajl_allow_partial_values:
if (va_arg(ap, int)) h->flags |= opt;
else h->flags &= ~opt;
break;
default:
rv = 0;
}
va_end(ap);
return rv;
}
void
yajl_free(yajl_handle handle)
{
yajl_bs_free(handle->stateStack);
yajl_buf_free(handle->decodeBuf);
yajl_lex_free(handle->lexer);
if (handle->lexer) {
yajl_lex_free(handle->lexer);
handle->lexer = NULL;
}
YA_FREE(&(handle->alloc), handle);
}
yajl_status
yajl_parse(yajl_handle hand, const unsigned char * jsonText,
unsigned int jsonTextLen)
size_t jsonTextLen)
{
yajl_status status;
/* lazy allocation of the lexer */
if (hand->lexer == NULL) {
hand->lexer = yajl_lex_alloc(&(hand->alloc),
hand->flags & yajl_allow_comments,
!(hand->flags & yajl_dont_validate_strings));
}
if (hand->lexer == NULL) {
return yajl_status_error;
}
status = yajl_do_parse(hand, jsonText, jsonTextLen);
return status;
}
yajl_status
yajl_parse_complete(yajl_handle hand)
yajl_complete_parse(yajl_handle hand)
{
/* The particular case we want to handle is a trailing number.
* Further input consisting of digits could cause our interpretation
* of the number to change (buffered "1" but "2" comes in).
* A very simple approach to this is to inject whitespace to terminate
* any number in the lex buffer.
*/
return yajl_parse(hand, (const unsigned char *)" ", 1);
/* The lexer is lazy allocated in the first call to parse. if parse is
* never called, then no data was provided to parse at all. This is a
* "premature EOF" error unless yajl_allow_partial_values is specified.
* allocating the lexer now is the simplest possible way to handle this
* case while preserving all the other semantics of the parser
* (multiple values, partial values, etc). */
if (hand->lexer == NULL) {
hand->lexer = yajl_lex_alloc(&(hand->alloc),
hand->flags & yajl_allow_comments,
!(hand->flags & yajl_dont_validate_strings));
}
return yajl_do_finish(hand);
}
unsigned char *
yajl_get_error(yajl_handle hand, int verbose,
const unsigned char * jsonText, unsigned int jsonTextLen)
const unsigned char * jsonText, size_t jsonTextLen)
{
return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose);
}
unsigned int
size_t
yajl_get_bytes_consumed(yajl_handle hand)
{
if (!hand) return 0;

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* \file yajl_alloc.h
@@ -41,13 +25,13 @@
#define epicsExportSharedSymbols
#include "yajl_alloc.h"
static void * yajl_internal_malloc(void *ctx, unsigned int sz)
static void * yajl_internal_malloc(void *ctx, size_t sz)
{
return malloc(sz);
}
static void * yajl_internal_realloc(void *ctx, void * previous,
unsigned int sz)
size_t sz)
{
return realloc(previous, sz);
}

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* \file yajl_alloc.h

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <stdlib.h>
@@ -40,16 +24,16 @@
#define YAJL_BUF_INIT_SIZE 2048
struct yajl_buf_t {
unsigned int len;
unsigned int used;
size_t len;
size_t used;
unsigned char * data;
yajl_alloc_funcs * alloc;
};
static
void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
void yajl_buf_ensure_available(yajl_buf buf, size_t want)
{
unsigned int need;
size_t need;
assert(buf != NULL);
@@ -73,6 +57,10 @@ void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
{
yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
if (b == NULL) {
return NULL;
}
memset((void *) b, 0, sizeof(struct yajl_buf_t));
b->alloc = alloc;
return b;
@@ -85,7 +73,7 @@ void yajl_buf_free(yajl_buf buf)
YA_FREE(buf->alloc, buf);
}
void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
void yajl_buf_append(yajl_buf buf, const void * data, size_t len)
{
yajl_buf_ensure_available(buf, len);
if (len > 0) {
@@ -107,13 +95,13 @@ const unsigned char * yajl_buf_data(yajl_buf buf)
return buf->data;
}
unsigned int yajl_buf_len(yajl_buf buf)
size_t yajl_buf_len(yajl_buf buf)
{
return buf->used;
}
void
yajl_buf_truncate(yajl_buf buf, unsigned int len)
yajl_buf_truncate(yajl_buf buf, size_t len)
{
assert(len <= buf->used);
buf->used = len;

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __YAJL_BUF_H__
#define __YAJL_BUF_H__
@@ -56,7 +40,7 @@ yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc);
void yajl_buf_free(yajl_buf buf);
/* append a number of bytes to the buffer */
void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len);
void yajl_buf_append(yajl_buf buf, const void * data, size_t len);
/* empty the buffer */
void yajl_buf_clear(yajl_buf buf);
@@ -65,9 +49,9 @@ void yajl_buf_clear(yajl_buf buf);
const unsigned char * yajl_buf_data(yajl_buf buf);
/* get the length of the buffer */
unsigned int yajl_buf_len(yajl_buf buf);
size_t yajl_buf_len(yajl_buf buf);
/* truncate the buffer */
void yajl_buf_truncate(yajl_buf buf, unsigned int len);
void yajl_buf_truncate(yajl_buf buf, size_t len);
#endif

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* A header only implementation of a simple stack of bytes, used in YAJL
@@ -45,8 +29,8 @@
typedef struct yajl_bytestack_t
{
unsigned char * stack;
unsigned int size;
unsigned int used;
size_t size;
size_t used;
yajl_alloc_funcs * yaf;
} yajl_bytestack;
@@ -61,7 +45,7 @@ typedef struct yajl_bytestack_t
/* initialize a bytestack */
#define yajl_bs_free(obs) \
if ((obs).stack) (obs).yaf->free((obs).yaf->ctx, (obs).stack);
if ((obs).stack) (obs).yaf->free((obs).yaf->ctx, (obs).stack);
#define yajl_bs_current(obs) \
(assert((obs).used > 0), (obs).stack[(obs).used - 1])
@@ -74,12 +58,12 @@ typedef struct yajl_bytestack_t
} \
(obs).stack[((obs).used)++] = (byte); \
}
/* removes the top item of the stack, returns nothing */
#define yajl_bs_pop(obs) { ((obs).used)--; }
#define yajl_bs_set(obs, byte) \
(obs).stack[((obs).used) - 1] = (byte);
(obs).stack[((obs).used) - 1] = (byte);
#endif

View File

@@ -1,58 +1,59 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __YAJL_COMMON_H__
#define __YAJL_COMMON_H__
#include <stddef.h>
#include <shareLib.h>
#include <epicsVersion.h>
#ifdef __cplusplus
extern "C" {
#endif
/** YAJL API history in brief
*
* Originally macro not defined
* YAJL 1.0.12
* Bundled with EPICS Base 3.15.0.1
*
* YAJL 2.1.0
* Changes argument type for yajl_integer() from 'int' to 'long long'
* Changes argument type for yajl_string() and yajl_map_key() from 'unsigned' to 'size_t'
* Replacement of struct yajl_parser_config with yajl_config()
* Replacement of yajl_parse_complete() with yajl_complete_parse()
*/
#define EPICS_YAJL_VERSION VERSION_INT(2,1,0,0)
#define YAJL_MAX_DEPTH 128
#define YAJL_API epicsShareFunc
/** pointer to a malloc function, supporting client overriding memory
* allocation routines */
typedef void * (*yajl_malloc_func)(void *ctx, unsigned int sz);
typedef void * (*yajl_malloc_func)(void *ctx, size_t sz);
/** pointer to a free function, supporting client overriding memory
* allocation routines */
typedef void (*yajl_free_func)(void *ctx, void * ptr);
/** pointer to a realloc function which can resize an allocation. */
typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, unsigned int sz);
typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz);
/** A structure which can be passed to yajl_*_alloc routines to allow the
* client to specify memory allocation functions to be used. */
@@ -71,6 +72,6 @@ typedef struct
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <stdlib.h>
@@ -46,20 +30,14 @@ static void CharToHex(unsigned char c, char * hexBuf)
}
void
yajl_string_encode(yajl_buf buf, const unsigned char * str,
unsigned int len)
yajl_string_encode(const yajl_print_t print,
void * ctx,
const unsigned char * str,
size_t len,
int escape_solidus)
{
yajl_string_encode2((const yajl_print_t) &yajl_buf_append, buf, str, len);
}
void
yajl_string_encode2(const yajl_print_t print,
void * ctx,
const unsigned char * str,
unsigned int len)
{
unsigned int beg = 0;
unsigned int end = 0;
size_t beg = 0;
size_t end = 0;
char hexBuf[7];
hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0';
hexBuf[6] = 0;
@@ -70,7 +48,12 @@ yajl_string_encode2(const yajl_print_t print,
case '\r': escaped = "\\r"; break;
case '\n': escaped = "\\n"; break;
case '\\': escaped = "\\\\"; break;
/* case '/': escaped = "\\/"; break; */
/* it is not required to escape a solidus in JSON:
* read sec. 2.5: http://www.ietf.org/rfc/rfc4627.txt
* specifically, this production from the grammar:
* unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
*/
case '/': if (escape_solidus) escaped = "\\/"; break;
case '"': escaped = "\\\""; break;
case '\f': escaped = "\\f"; break;
case '\b': escaped = "\\b"; break;
@@ -132,10 +115,10 @@ static void Utf32toUtf8(unsigned int codepoint, char * utf8Buf)
}
void yajl_string_decode(yajl_buf buf, const unsigned char * str,
unsigned int len)
size_t len)
{
unsigned int beg = 0;
unsigned int end = 0;
size_t beg = 0;
size_t end = 0;
while (end < len) {
if (str[end] == '\\') {
@@ -194,3 +177,45 @@ void yajl_string_decode(yajl_buf buf, const unsigned char * str,
}
yajl_buf_append(buf, str + beg, end - beg);
}
#define ADV_PTR s++; if (!(len--)) return 0;
int yajl_string_validate_utf8(const unsigned char * s, size_t len)
{
if (!len) return 1;
if (!s) return 0;
while (len--) {
/* single byte */
if (*s <= 0x7f) {
/* noop */
}
/* two byte */
else if ((*s >> 5) == 0x6) {
ADV_PTR;
if (!((*s >> 6) == 0x2)) return 0;
}
/* three byte */
else if ((*s >> 4) == 0x0e) {
ADV_PTR;
if (!((*s >> 6) == 0x2)) return 0;
ADV_PTR;
if (!((*s >> 6) == 0x2)) return 0;
}
/* four byte */
else if ((*s >> 3) == 0x1e) {
ADV_PTR;
if (!((*s >> 6) == 0x2)) return 0;
ADV_PTR;
if (!((*s >> 6) == 0x2)) return 0;
ADV_PTR;
if (!((*s >> 6) == 0x2)) return 0;
} else {
return 0;
}
s++;
}
return 1;
}

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __YAJL_ENCODE_H__
#define __YAJL_ENCODE_H__
@@ -36,15 +20,15 @@
#include "yajl_buf.h"
#include "yajl_gen.h"
void yajl_string_encode2(const yajl_print_t printer,
void * ctx,
const unsigned char * str,
unsigned int length);
void yajl_string_encode(yajl_buf buf, const unsigned char * str,
unsigned int length);
void yajl_string_encode(const yajl_print_t printer,
void * ctx,
const unsigned char * str,
size_t length,
int escape_solidus);
void yajl_string_decode(yajl_buf buf, const unsigned char * str,
unsigned int length);
size_t length);
int yajl_string_validate_utf8(const unsigned char * s, size_t len);
#endif

View File

@@ -1,38 +1,23 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#define epicsExportSharedSymbols
#include "epicsMath.h"
@@ -51,10 +36,10 @@ typedef enum {
yajl_gen_error
} yajl_gen_state;
struct yajl_gen_t
struct yajl_gen_t
{
unsigned int flags;
unsigned int depth;
unsigned int pretty;
const char * indentString;
yajl_gen_state state[YAJL_MAX_DEPTH];
yajl_print_t print;
@@ -63,18 +48,54 @@ struct yajl_gen_t
yajl_alloc_funcs alloc;
};
yajl_gen
yajl_gen_alloc(const yajl_gen_config * config,
const yajl_alloc_funcs * afs)
int
yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...)
{
return yajl_gen_alloc2(NULL, config, afs, NULL);
int rv = 1;
va_list ap;
va_start(ap, opt);
switch(opt) {
case yajl_gen_beautify:
case yajl_gen_validate_utf8:
if (va_arg(ap, int)) g->flags |= opt;
else g->flags &= ~opt;
break;
case yajl_gen_indent_string: {
const char *indent = va_arg(ap, const char *);
g->indentString = indent;
for (; *indent; indent++) {
if (*indent != '\n'
&& *indent != '\v'
&& *indent != '\f'
&& *indent != '\t'
&& *indent != '\r'
&& *indent != ' ')
{
g->indentString = NULL;
rv = 0;
}
}
break;
}
case yajl_gen_print_callback:
yajl_buf_free(g->ctx);
g->print = va_arg(ap, const yajl_print_t);
g->ctx = va_arg(ap, void *);
break;
default:
rv = 0;
}
va_end(ap);
return rv;
}
yajl_gen
yajl_gen_alloc2(const yajl_print_t callback,
const yajl_gen_config * config,
const yajl_alloc_funcs * afs,
void * ctx)
yajl_gen_alloc(const yajl_alloc_funcs * afs)
{
yajl_gen g = NULL;
yajl_alloc_funcs afsBuffer;
@@ -97,35 +118,9 @@ yajl_gen_alloc2(const yajl_print_t callback,
/* copy in pointers to allocation routines */
memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
if (config) {
const char *indent = config->indentString;
g->pretty = config->beautify;
g->indentString = config->indentString;
if (indent) {
for (; *indent; indent++) {
if (*indent != '\n'
&& *indent != '\v'
&& *indent != '\f'
&& *indent != '\t'
&& *indent != '\r'
&& *indent != ' ') {
g->indentString = NULL;
break;
}
}
}
if (!g->indentString) {
g->indentString = " ";
}
}
if (callback) {
g->print = callback;
g->ctx = ctx;
} else {
g->print = (yajl_print_t)&yajl_buf_append;
g->ctx = yajl_buf_alloc(&(g->alloc));
}
g->print = (yajl_print_t)&yajl_buf_append;
g->ctx = yajl_buf_alloc(&(g->alloc));
g->indentString = " ";
return g;
}
@@ -141,14 +136,14 @@ yajl_gen_free(yajl_gen g)
if (g->state[g->depth] == yajl_gen_map_key || \
g->state[g->depth] == yajl_gen_in_array) { \
g->print(g->ctx, ",", 1); \
if (g->pretty) g->print(g->ctx, "\n", 1); \
if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \
} else if (g->state[g->depth] == yajl_gen_map_val) { \
g->print(g->ctx, ":", 1); \
if (g->pretty) g->print(g->ctx, " ", 1); \
if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \
}
#define INSERT_WHITESPACE \
if (g->pretty) { \
if ((g->flags & yajl_gen_beautify)) { \
if (g->state[g->depth] != yajl_gen_map_val) { \
unsigned int _i; \
for (_i=0;_i<g->depth;_i++) \
@@ -199,15 +194,15 @@ yajl_gen_free(yajl_gen g)
} \
#define FINAL_NEWLINE \
if (g->pretty && g->state[g->depth] == yajl_gen_complete) \
g->print(g->ctx, "\n", 1);
if ((g->flags & yajl_gen_beautify) && g->state[g->depth] == yajl_gen_complete) \
g->print(g->ctx, "\n", 1);
yajl_gen_status
yajl_gen_integer(yajl_gen g, long int number)
yajl_gen_integer(yajl_gen g, long long int number)
{
char i[32];
ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
sprintf(i, "%ld", number);
sprintf(i, "%lld", number);
g->print(g->ctx, i, (unsigned int)strlen(i));
APPENDED_ATOM;
FINAL_NEWLINE;
@@ -229,7 +224,7 @@ yajl_gen_double(yajl_gen g, double number)
}
yajl_gen_status
yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
yajl_gen_number(yajl_gen g, const char * s, size_t l)
{
ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
g->print(g->ctx, s, l);
@@ -240,11 +235,19 @@ yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
yajl_gen_status
yajl_gen_string(yajl_gen g, const unsigned char * str,
unsigned int len)
size_t len)
{
// if validation is enabled, check that the string is valid utf8
// XXX: This checking could be done a little faster, in the same pass as
// the string encoding
if (g->flags & yajl_gen_validate_utf8) {
if (!yajl_string_validate_utf8(str, len)) {
return yajl_gen_invalid_string;
}
}
ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE;
g->print(g->ctx, "\"", 1);
yajl_string_encode2(g->print, g->ctx, str, len);
yajl_string_encode(g->print, g->ctx, str, len, g->flags & yajl_gen_escape_solidus);
g->print(g->ctx, "\"", 1);
APPENDED_ATOM;
FINAL_NEWLINE;
@@ -281,7 +284,7 @@ yajl_gen_map_open(yajl_gen g)
g->state[g->depth] = yajl_gen_map_start;
g->print(g->ctx, "{", 1);
if (g->pretty) g->print(g->ctx, "\n", 1);
if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
FINAL_NEWLINE;
return yajl_gen_status_ok;
}
@@ -292,7 +295,7 @@ yajl_gen_map_close(yajl_gen g)
ENSURE_VALID_STATE;
DECREMENT_DEPTH;
if (g->pretty) g->print(g->ctx, "\n", 1);
if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
APPENDED_ATOM;
INSERT_WHITESPACE;
g->print(g->ctx, "}", 1);
@@ -307,7 +310,7 @@ yajl_gen_array_open(yajl_gen g)
INCREMENT_DEPTH;
g->state[g->depth] = yajl_gen_array_start;
g->print(g->ctx, "[", 1);
if (g->pretty) g->print(g->ctx, "\n", 1);
if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
FINAL_NEWLINE;
return yajl_gen_status_ok;
}
@@ -317,7 +320,7 @@ yajl_gen_array_close(yajl_gen g)
{
ENSURE_VALID_STATE;
DECREMENT_DEPTH;
if (g->pretty) g->print(g->ctx, "\n", 1);
if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1);
APPENDED_ATOM;
INSERT_WHITESPACE;
g->print(g->ctx, "]", 1);
@@ -327,7 +330,7 @@ yajl_gen_array_close(yajl_gen g)
yajl_gen_status
yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
unsigned int * len)
size_t * len)
{
if (g->print != (yajl_print_t)&yajl_buf_append) return yajl_gen_no_buf;
*buf = yajl_buf_data((yajl_buf)g->ctx);

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* \file yajl_gen.h
@@ -38,11 +22,11 @@
#ifndef __YAJL_GEN_H__
#define __YAJL_GEN_H__
#include <yajl_common.h>
#include "yajl_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#endif
/** generator status codes */
typedef enum {
/** no error */
@@ -63,7 +47,11 @@ extern "C" {
yajl_gen_invalid_number,
/** A print callback was passed in, so there is no internal
* buffer to get from */
yajl_gen_no_buf
yajl_gen_no_buf,
/** returned from yajl_gen_string() when the yajl_gen_validate_utf8
* option is enabled and an invalid was passed by client code.
*/
yajl_gen_invalid_string
} yajl_gen_status;
/** an opaque handle to a generator */
@@ -72,21 +60,52 @@ extern "C" {
/** a callback used for "printing" the results. */
typedef void (*yajl_print_t)(void * ctx,
const char * str,
unsigned int len);
size_t len);
/** configuration structure for the generator */
typedef struct {
/** configuration parameters for the parser, these may be passed to
* yajl_gen_config() along with option specific argument(s). In general,
* all configuration parameters default to *off*. */
typedef enum {
/** generate indented (beautiful) output */
unsigned int beautify;
/** an opportunity to define an indent string. such as \\t or
* some number of spaces. default is four spaces ' '. This
* member is only relevant when beautify is true */
const char * indentString;
} yajl_gen_config;
yajl_gen_beautify = 0x01,
/**
* Set an indent string which is used when yajl_gen_beautify
* is enabled. Maybe something like \\t or some number of
* spaces. The default is four spaces ' '.
*/
yajl_gen_indent_string = 0x02,
/**
* Set a function and context argument that should be used to
* output generated json. the function should conform to the
* yajl_print_t prototype while the context argument is a
* void * of your choosing.
*
* example:
* yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr);
*/
yajl_gen_print_callback = 0x04,
/**
* Normally the generator does not validate that strings you
* pass to it via yajl_gen_string() are valid UTF8. Enabling
* this option will cause it to do so.
*/
yajl_gen_validate_utf8 = 0x08,
/**
* the forward solidus (slash or '/' in human) is not required to be
* escaped in json text. By default, YAJL will not escape it in the
* iterest of saving bytes. Setting this flag will cause YAJL to
* always escape '/' in generated JSON strings.
*/
yajl_gen_escape_solidus = 0x10
} yajl_gen_option;
/** allow the modification of generator options subsequent to handle
* allocation (via yajl_alloc)
* \returns zero in case of errors, non-zero otherwise
*/
YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...);
/** allocate a generator handle
* \param config a pointer to a structure containing parameters which
* configure the behavior of the json generator
* \param allocFuncs an optional pointer to a structure which allows
* the client to overide the memory allocation
* used by yajl. May be NULL, in which case
@@ -94,47 +113,24 @@ extern "C" {
*
* \returns an allocated handle on success, NULL on failure (bad params)
*/
YAJL_API yajl_gen yajl_gen_alloc(const yajl_gen_config * config,
const yajl_alloc_funcs * allocFuncs);
YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs);
/** allocate a generator handle that will print to the specified
* callback rather than storing the results in an internal buffer.
* \param callback a pointer to a printer function. May be NULL
* in which case, the results will be store in an
* internal buffer.
* \param config a pointer to a structure containing parameters
* which configure the behavior of the json
* generator.
* \param allocFuncs an optional pointer to a structure which allows
* the client to overide the memory allocation
* used by yajl. May be NULL, in which case
* malloc/free/realloc will be used.
* \param ctx a context pointer that will be passed to the
* printer callback.
*
* \returns an allocated handle on success, NULL on failure (bad params)
*/
YAJL_API yajl_gen yajl_gen_alloc2(const yajl_print_t callback,
const yajl_gen_config * config,
const yajl_alloc_funcs * allocFuncs,
void * ctx);
/** free a generator handle */
/** free a generator handle */
YAJL_API void yajl_gen_free(yajl_gen handle);
YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long int number);
YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number);
/** generate a floating point number. number may not be infinity or
* NaN, as these have no representation in JSON. In these cases the
* generator will return 'yajl_gen_invalid_number' */
YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number);
YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand,
const char * num,
unsigned int len);
size_t len);
YAJL_API yajl_gen_status yajl_gen_string(yajl_gen hand,
const unsigned char * str,
unsigned int len);
size_t len);
YAJL_API yajl_gen_status yajl_gen_null(yajl_gen hand);
YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean);
YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean);
YAJL_API yajl_gen_status yajl_gen_map_open(yajl_gen hand);
YAJL_API yajl_gen_status yajl_gen_map_close(yajl_gen hand);
YAJL_API yajl_gen_status yajl_gen_array_open(yajl_gen hand);
@@ -145,7 +141,7 @@ extern "C" {
* buffer. This allows stream generation. */
YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand,
const unsigned char ** buf,
unsigned int * len);
size_t * len);
/** clear yajl's output buffer, but maintain all internal generation
* state. This function will not "reset" the generator state, and is

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
@@ -84,8 +68,8 @@ tokToStr(yajl_tok tok)
struct yajl_lexer_t {
/* the overal line and char offset into the data */
unsigned int lineOff;
unsigned int charOff;
size_t lineOff;
size_t charOff;
/* error */
yajl_lex_error error;
@@ -96,7 +80,7 @@ struct yajl_lexer_t {
/* in the case where we have data in the lexBuf, bufOff holds
* the current offset into the lexBuf. */
unsigned int bufOff;
size_t bufOff;
/* are we using the lex buf? */
unsigned int bufInUse;
@@ -122,6 +106,10 @@ yajl_lex_alloc(yajl_alloc_funcs * alloc,
unsigned int allowComments, unsigned int validateUTF8)
{
yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
if (lxr == NULL) {
return NULL;
}
memset((void *) lxr, 0, sizeof(struct yajl_lexer_t));
lxr->buf = yajl_buf_alloc(alloc);
lxr->allowComments = allowComments;
@@ -139,15 +127,19 @@ yajl_lex_free(yajl_lexer lxr)
}
/* a lookup table which lets us quickly determine three things:
* VEC - valid escaped conrol char
* VEC - valid escaped control char
* note. the solidus '/' may be escaped or not.
* IJC - invalid json char
* VHC - valid hex char
* note. the solidus '/' may be escaped or not.
* note. the
* NFP - needs further processing (from a string scanning perspective)
* NUC - needs utf8 checking when enabled (from a string scanning perspective)
*/
#define VEC 1
#define IJC 2
#define VHC 4
#define VEC 0x01
#define IJC 0x02
#define VHC 0x04
#define NFP 0x08
#define NUC 0x10
static const char charLookupTable[256] =
{
/*00*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
@@ -155,7 +147,7 @@ static const char charLookupTable[256] =
/*10*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
/*18*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
/*20*/ 0 , 0 , VEC|IJC, 0 , 0 , 0 , 0 , 0 ,
/*20*/ 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 , 0 , 0 ,
/*28*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , VEC ,
/*30*/ VHC , VHC , VHC , VHC , VHC , VHC , VHC , VHC ,
/*38*/ VHC , VHC , 0 , 0 , 0 , 0 , 0 , 0 ,
@@ -163,33 +155,32 @@ static const char charLookupTable[256] =
/*40*/ 0 , VHC , VHC , VHC , VHC , VHC , VHC , 0 ,
/*48*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/*50*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/*58*/ 0 , 0 , 0 , 0 , VEC|IJC, 0 , 0 , 0 ,
/*58*/ 0 , 0 , 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 ,
/*60*/ 0 , VHC , VEC|VHC, VHC , VHC , VHC , VEC|VHC, 0 ,
/*68*/ 0 , 0 , 0 , 0 , 0 , 0 , VEC , 0 ,
/*70*/ 0 , 0 , VEC , 0 , VEC , 0 , 0 , 0 ,
/*78*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* include these so we don't have to always check the range of the char */
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC
};
/** process a variable length utf8 encoded codepoint.
@@ -207,7 +198,7 @@ static const char charLookupTable[256] =
static yajl_tok
yajl_lex_utf8_char(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int * offset,
size_t jsonTextLen, size_t * offset,
unsigned char curChar)
{
if (curChar <= 0x7f) {
@@ -261,17 +252,56 @@ if (*offset >= jsonTextLen) { \
goto finish_string_lex; \
}
/** scan a string for interesting characters that might need further
* review. return the number of chars that are uninteresting and can
* be skipped.
* (lth) hi world, any thoughts on how to make this routine faster? */
static size_t
yajl_string_scan(const unsigned char * buf, size_t len, int utf8check)
{
unsigned char mask = IJC|NFP|(utf8check ? NUC : 0);
size_t skip = 0;
while (skip < len && !(charLookupTable[*buf] & mask))
{
skip++;
buf++;
}
return skip;
}
static yajl_tok
yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int * offset)
size_t jsonTextLen, size_t * offset)
{
yajl_tok tok = yajl_tok_error;
int hasEscapes = 0;
for (;;) {
unsigned char curChar;
unsigned char curChar;
STR_CHECK_EOF;
/* now jump into a faster scanning routine to skip as much
* of the buffers as possible */
{
const unsigned char * p;
size_t len;
if ((lexer->bufInUse && yajl_buf_len(lexer->buf) &&
lexer->bufOff < yajl_buf_len(lexer->buf)))
{
p = ((const unsigned char *) yajl_buf_data(lexer->buf) +
(lexer->bufOff));
len = yajl_buf_len(lexer->buf) - lexer->bufOff;
lexer->bufOff += yajl_string_scan(p, len, lexer->validateUTF8);
}
else if (*offset < jsonTextLen)
{
p = jsonText + *offset;
len = jsonTextLen - *offset;
*offset += yajl_string_scan(p, len, lexer->validateUTF8);
}
}
STR_CHECK_EOF;
curChar = readChar(lexer, jsonText, offset);
@@ -344,7 +374,7 @@ yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
static yajl_tok
yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int * offset)
size_t jsonTextLen, size_t * offset)
{
/** XXX: numbers are the only entities in json that we must lex
* _beyond_ in order to know that they are complete. There
@@ -431,7 +461,7 @@ yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText,
static yajl_tok
yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int * offset)
size_t jsonTextLen, size_t * offset)
{
unsigned char c;
@@ -472,12 +502,12 @@ yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText,
yajl_tok
yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int * offset,
const unsigned char ** outBuf, unsigned int * outLen)
size_t jsonTextLen, size_t * offset,
const unsigned char ** outBuf, size_t * outLen)
{
yajl_tok tok = yajl_tok_error;
unsigned char c;
unsigned int startOffset = *offset;
size_t startOffset = *offset;
*outBuf = NULL;
*outLen = 0;
@@ -494,17 +524,17 @@ yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
switch (c) {
case '{':
tok = yajl_tok_left_bracket;
goto lexed;
case '}':
tok = yajl_tok_right_bracket;
goto lexed;
case '[':
tok = yajl_tok_left_brace;
goto lexed;
case ']':
case '}':
tok = yajl_tok_right_brace;
goto lexed;
case '[':
tok = yajl_tok_left_bracket;
goto lexed;
case ']':
tok = yajl_tok_right_bracket;
goto lexed;
case ',':
tok = yajl_tok_comma;
goto lexed;
@@ -707,23 +737,23 @@ yajl_lex_get_error(yajl_lexer lexer)
return lexer->error;
}
unsigned int yajl_lex_current_line(yajl_lexer lexer)
size_t yajl_lex_current_line(yajl_lexer lexer)
{
return lexer->lineOff;
}
unsigned int yajl_lex_current_char(yajl_lexer lexer)
size_t yajl_lex_current_char(yajl_lexer lexer)
{
return lexer->charOff;
}
yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int offset)
size_t jsonTextLen, size_t offset)
{
const unsigned char * outBuf;
unsigned int outLen;
unsigned int bufLen = yajl_buf_len(lexer->buf);
unsigned int bufOff = lexer->bufOff;
size_t outLen;
size_t bufLen = yajl_buf_len(lexer->buf);
size_t bufOff = lexer->bufOff;
unsigned int bufInUse = lexer->bufInUse;
yajl_tok tok;

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __YAJL_LEX_H__
#define __YAJL_LEX_H__
@@ -92,12 +76,12 @@ n * error messages.
* size to get adequate performance.
*/
yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int * offset,
const unsigned char ** outBuf, unsigned int * outLen);
size_t jsonTextLen, size_t * offset,
const unsigned char ** outBuf, size_t * outLen);
/** have a peek at the next token, but don't move the lexer forward */
yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
unsigned int jsonTextLen, unsigned int offset);
size_t jsonTextLen, size_t offset);
typedef enum {
@@ -121,13 +105,13 @@ const char * yajl_lex_error_to_string(yajl_lex_error error);
yajl_lex_error yajl_lex_get_error(yajl_lexer lexer);
/** get the current offset into the most recently lexed json string. */
unsigned int yajl_lex_current_offset(yajl_lexer lexer);
size_t yajl_lex_current_offset(yajl_lexer lexer);
/** get the number of lines lexed by this lexer instance */
unsigned int yajl_lex_current_line(yajl_lexer lexer);
size_t yajl_lex_current_line(yajl_lexer lexer);
/** get the number of chars lexed by this lexer instance since the last
* \n or \r */
unsigned int yajl_lex_current_char(yajl_lexer lexer);
size_t yajl_lex_current_char(yajl_lexer lexer);
#endif

View File

@@ -1,58 +1,38 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* \file yajl_parse.h
* Interface to YAJL's JSON parsing facilities.
* Interface to YAJL's JSON stream parsing facilities.
*/
#ifndef __YAJL_PARSE_H__
#define __YAJL_PARSE_H__
#include <yajl_common.h>
#include "yajl_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#endif
/** error codes returned from this interface */
typedef enum {
/** no error was encountered */
yajl_status_ok,
/** a client callback returned zero, stopping the parse */
yajl_status_client_canceled,
/** The parse cannot yet complete because more json input text
* is required, call yajl_parse with the next buffer of input text.
* (pertinent only when stream parsing) */
yajl_status_insufficient_data,
/** An error occured during the parse. Call yajl_get_error for
* more information about the encountered error */
yajl_status_error
@@ -75,64 +55,115 @@ extern "C" {
* continue. If zero, the parse will be canceled and
* yajl_status_client_canceled will be returned from the parse.
*
* Note about handling of numbers:
* yajl will only convert numbers that can be represented in a double
* or a long int. All other numbers will be passed to the client
* in string form using the yajl_number callback. Furthermore, if
* yajl_number is not NULL, it will always be used to return numbers,
* that is yajl_integer and yajl_double will be ignored. If
* yajl_number is NULL but one of yajl_integer or yajl_double are
* defined, parsing of a number larger than is representable
* in a double or long int will result in a parse error.
* \attention {
* A note about the handling of numbers:
*
* yajl will only convert numbers that can be represented in a
* double or a 64 bit (long long) int. All other numbers will
* be passed to the client in string form using the yajl_number
* callback. Furthermore, if yajl_number is not NULL, it will
* always be used to return numbers, that is yajl_integer and
* yajl_double will be ignored. If yajl_number is NULL but one
* of yajl_integer or yajl_double are defined, parsing of a
* number larger than is representable in a double or 64 bit
* integer will result in a parse error.
* }
*/
typedef struct {
int (* yajl_null)(void * ctx);
int (* yajl_boolean)(void * ctx, int boolVal);
int (* yajl_integer)(void * ctx, long integerVal);
int (* yajl_integer)(void * ctx, long long integerVal);
int (* yajl_double)(void * ctx, double doubleVal);
/** A callback which passes the string representation of the number
* back to the client. Will be used for all numbers when present */
int (* yajl_number)(void * ctx, const char * numberVal,
unsigned int numberLen);
size_t numberLen);
/** strings are returned as pointers into the JSON text when,
* possible, as a result, they are _not_ null padded */
int (* yajl_string)(void * ctx, const unsigned char * stringVal,
unsigned int stringLen);
size_t stringLen);
int (* yajl_start_map)(void * ctx);
int (* yajl_map_key)(void * ctx, const unsigned char * key,
unsigned int stringLen);
int (* yajl_end_map)(void * ctx);
size_t stringLen);
int (* yajl_end_map)(void * ctx);
int (* yajl_start_array)(void * ctx);
int (* yajl_end_array)(void * ctx);
int (* yajl_end_array)(void * ctx);
} yajl_callbacks;
/** configuration structure for the generator */
typedef struct {
/** if nonzero, javascript style comments will be allowed in
* the json input, both slash star and slash slash */
unsigned int allowComments;
/** if nonzero, invalid UTF8 strings will cause a parse
* error */
unsigned int checkUTF8;
} yajl_parser_config;
/** allocate a parser handle
* \param callbacks a yajl callbacks structure specifying the
* functions to call when different JSON entities
* are encountered in the input text. May be NULL,
* which is only useful for validation.
* \param config configuration parameters for the parse.
* \param afs memory allocation functions, may be NULL for to use
* C runtime library routines (malloc and friends)
* \param ctx a context pointer that will be passed to callbacks.
*/
YAJL_API yajl_handle yajl_alloc(const yajl_callbacks * callbacks,
const yajl_parser_config * config,
const yajl_alloc_funcs * allocFuncs,
yajl_alloc_funcs * afs,
void * ctx);
/** free a parser handle */
/** configuration parameters for the parser, these may be passed to
* yajl_config() along with option specific argument(s). In general,
* all configuration parameters default to *off*. */
typedef enum {
/** Ignore javascript style comments present in
* JSON input. Non-standard, but rather fun
* arguments: toggled off with integer zero, on otherwise.
*
* example:
* yajl_config(h, yajl_allow_comments, 1); // turn comment support on
*/
yajl_allow_comments = 0x01,
/**
* When set the parser will verify that all strings in JSON input are
* valid UTF8 and will emit a parse error if this is not so. When set,
* this option makes parsing slightly more expensive (~7% depending
* on processor and compiler in use)
*
* example:
* yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking
*/
yajl_dont_validate_strings = 0x02,
/**
* By default, upon calls to yajl_complete_parse(), yajl will
* ensure the entire input text was consumed and will raise an error
* otherwise. Enabling this flag will cause yajl to disable this
* check. This can be useful when parsing json out of a that contains more
* than a single JSON document.
*/
yajl_allow_trailing_garbage = 0x04,
/**
* Allow multiple values to be parsed by a single handle. The
* entire text must be valid JSON, and values can be seperated
* by any kind of whitespace. This flag will change the
* behavior of the parser, and cause it continue parsing after
* a value is parsed, rather than transitioning into a
* complete state. This option can be useful when parsing multiple
* values from an input stream.
*/
yajl_allow_multiple_values = 0x08,
/**
* When yajl_complete_parse() is called the parser will
* check that the top level value was completely consumed. I.E.,
* if called whilst in the middle of parsing a value
* yajl will enter an error state (premature EOF). Setting this
* flag suppresses that check and the corresponding error.
*/
yajl_allow_partial_values = 0x10
} yajl_option;
/** allow the modification of parser options subsequent to handle
* allocation (via yajl_alloc)
* \returns zero in case of errors, non-zero otherwise
*/
YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...);
/** free a parser handle */
YAJL_API void yajl_free(yajl_handle handle);
/** Parse some json!
@@ -142,7 +173,7 @@ extern "C" {
*/
YAJL_API yajl_status yajl_parse(yajl_handle hand,
const unsigned char * jsonText,
unsigned int jsonTextLength);
size_t jsonTextLength);
/** Parse any remaining buffered json.
* Since yajl is a stream-based parser, without an explicit end of
@@ -153,8 +184,8 @@ extern "C" {
*
* \param hand - a handle to the json parser allocated with yajl_alloc
*/
YAJL_API yajl_status yajl_parse_complete(yajl_handle hand);
YAJL_API yajl_status yajl_complete_parse(yajl_handle hand);
/** get an error string describing the state of the
* parse.
*
@@ -163,31 +194,31 @@ extern "C" {
* the specific char.
*
* \returns A dynamically allocated string will be returned which should
* be freed with yajl_free_error
* be freed with yajl_free_error
*/
YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose,
const unsigned char * jsonText,
unsigned int jsonTextLength);
size_t jsonTextLength);
/**
* get the amount of data consumed from the last chunk passed to YAJL.
*
* In the case of a successful parse this can help you understand if
* the entire buffer was consumed (which will allow you to handle
* "junk at end of input".
*
* "junk at end of input").
*
* In the event an error is encountered during parsing, this function
* affords the client a way to get the offset into the most recent
* chunk where the error occured. 0 will be returned if no error
* was encountered.
*/
YAJL_API unsigned int yajl_get_bytes_consumed(yajl_handle hand);
YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand);
/** free an error returned from yajl_get_error */
YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str);
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <limits.h>
@@ -40,21 +24,55 @@
#include <math.h>
#define epicsExportSharedSymbols
#include "yajl_parse.h"
#include "yajl_lex.h"
#include "yajl_parser.h"
#include "yajl_encode.h"
#include "yajl_bytestack.h"
#ifndef LLONG_MAX
#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL
#define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1)
#endif
#define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10))
/* same semantics as strtol */
long long
yajl_parse_integer(const unsigned char *number, size_t length)
{
long long ret = 0;
long sign = 1;
const unsigned char *pos = number;
if (*pos == '-') { pos++; sign = -1; }
if (*pos == '+') { pos++; }
while (pos < number + length) {
if ( ret > MAX_VALUE_TO_MULTIPLY ) {
errno = ERANGE;
return sign == 1 ? LLONG_MAX : LLONG_MIN;
}
ret *= 10;
if (LLONG_MAX - ret < (*pos - '0')) {
errno = ERANGE;
return sign == 1 ? LLONG_MAX : LLONG_MIN;
}
ret += (*pos++ - '0');
}
return sign * ret;
}
unsigned char *
yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
unsigned int jsonTextLen, int verbose)
size_t jsonTextLen, int verbose)
{
unsigned int offset = hand->bytesConsumed;
size_t offset = hand->bytesConsumed;
unsigned char * str;
const char * errorType = NULL;
const char * errorText = NULL;
char text[72];
const char * arrow = " (right here) ------^\n";
const char * arrow = " (right here) ------^\n";
if (yajl_bs_current(hand->stateStack) == yajl_state_parse_error) {
errorType = "parse";
@@ -67,34 +85,35 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
}
{
unsigned int memneeded = 0;
size_t memneeded = 0;
memneeded += strlen(errorType);
memneeded += strlen(" error");
if (errorText != NULL) {
memneeded += strlen(": ");
memneeded += strlen(errorText);
memneeded += strlen(": ");
memneeded += strlen(errorText);
}
str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2);
if (!str) return NULL;
str[0] = 0;
strcat((char *) str, errorType);
strcat((char *) str, " error");
strcat((char *) str, " error");
if (errorText != NULL) {
strcat((char *) str, ": ");
strcat((char *) str, errorText);
strcat((char *) str, ": ");
strcat((char *) str, errorText);
}
strcat((char *) str, "\n");
strcat((char *) str, "\n");
}
/* now we append as many spaces as needed to make sure the error
* falls at char 41, if verbose was specified */
if (verbose) {
unsigned int start, end, i;
unsigned int spacesNeeded;
size_t start, end, i;
size_t spacesNeeded;
spacesNeeded = (offset < 30 ? 40 - offset : 10);
start = (offset >= 30 ? offset - 30 : 0);
end = (offset + 30 > jsonTextLen ? jsonTextLen : offset + 30);
for (i=0;i<spacesNeeded;i++) text[i] = ' ';
for (;start < end;start++, i++) {
@@ -115,10 +134,12 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
YA_MALLOC(&(hand->alloc), (unsigned int)(strlen((char *) str) +
strlen((char *) text) +
strlen(arrow) + 1));
newStr[0] = 0;
strcat((char *) newStr, (char *) str);
strcat((char *) newStr, text);
strcat((char *) newStr, arrow);
if (newStr) {
newStr[0] = 0;
strcat((char *) newStr, (char *) str);
strcat((char *) newStr, text);
strcat((char *) newStr, arrow);
}
YA_FREE(&(hand->alloc), str);
str = (unsigned char *) newStr;
}
@@ -136,35 +157,78 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
}
yajl_status
yajl_do_finish(yajl_handle hand)
{
yajl_status stat;
stat = yajl_do_parse(hand,(const unsigned char *) " ",1);
if (stat != yajl_status_ok) return stat;
switch(yajl_bs_current(hand->stateStack))
{
case yajl_state_parse_error:
case yajl_state_lexical_error:
return yajl_status_error;
case yajl_state_got_value:
case yajl_state_parse_complete:
return yajl_status_ok;
default:
if (!(hand->flags & yajl_allow_partial_values))
{
yajl_bs_set(hand->stateStack, yajl_state_parse_error);
hand->parseError = "premature EOF";
return yajl_status_error;
}
return yajl_status_ok;
}
}
yajl_status
yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
unsigned int jsonTextLen)
size_t jsonTextLen)
{
yajl_tok tok;
const unsigned char * buf;
unsigned int bufLen;
unsigned int * offset = &(hand->bytesConsumed);
size_t bufLen;
size_t * offset = &(hand->bytesConsumed);
*offset = 0;
around_again:
switch (yajl_bs_current(hand->stateStack)) {
case yajl_state_parse_complete:
if (hand->flags & yajl_allow_multiple_values) {
yajl_bs_set(hand->stateStack, yajl_state_got_value);
goto around_again;
}
if (!(hand->flags & yajl_allow_trailing_garbage)) {
if (*offset != jsonTextLen) {
tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
offset, &buf, &bufLen);
if (tok != yajl_tok_eof) {
yajl_bs_set(hand->stateStack, yajl_state_parse_error);
hand->parseError = "trailing garbage";
}
goto around_again;
}
}
return yajl_status_ok;
case yajl_state_lexical_error:
case yajl_state_parse_error:
case yajl_state_parse_error:
return yajl_status_error;
case yajl_state_start:
case yajl_state_got_value:
case yajl_state_map_need_val:
case yajl_state_array_need_val:
case yajl_state_array_start: {
case yajl_state_array_start: {
/* for arrays and maps, we advance the state for this
* depth, then push the state of the next depth.
* If an error occurs during the parsing of the nesting
* enitity, the state at this level will not matter.
* a state that needs pushing will be anything other
* than state_start */
yajl_state stateToPush = yajl_state_start;
tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
@@ -172,7 +236,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
switch (tok) {
case yajl_tok_eof:
return yajl_status_insufficient_data;
return yajl_status_ok;
case yajl_tok_error:
yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
goto around_again;
@@ -191,53 +255,38 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
yajl_buf_len(hand->decodeBuf)));
}
break;
case yajl_tok_bool:
case yajl_tok_bool:
if (hand->callbacks && hand->callbacks->yajl_boolean) {
_CC_CHK(hand->callbacks->yajl_boolean(hand->ctx,
*buf == 't'));
}
break;
case yajl_tok_null:
case yajl_tok_null:
if (hand->callbacks && hand->callbacks->yajl_null) {
_CC_CHK(hand->callbacks->yajl_null(hand->ctx));
}
break;
case yajl_tok_left_bracket:
case yajl_tok_left_brace:
if (hand->callbacks && hand->callbacks->yajl_start_map) {
_CC_CHK(hand->callbacks->yajl_start_map(hand->ctx));
}
stateToPush = yajl_state_map_start;
break;
case yajl_tok_left_brace:
case yajl_tok_left_bracket:
if (hand->callbacks && hand->callbacks->yajl_start_array) {
_CC_CHK(hand->callbacks->yajl_start_array(hand->ctx));
}
stateToPush = yajl_state_array_start;
break;
case yajl_tok_integer:
/*
* note. strtol does not respect the length of
* the lexical token. in a corner case where the
* lexed number is a integer with a trailing zero,
* immediately followed by the end of buffer,
* sscanf could run off into oblivion and cause a
* crash. for this reason we copy the integer
* (and doubles), into our parse buffer (the same
* one used for unescaping strings), before
* calling strtol. yajl_buf ensures null padding,
* so we're safe.
*/
if (hand->callbacks) {
if (hand->callbacks->yajl_number) {
_CC_CHK(hand->callbacks->yajl_number(
hand->ctx,(const char *) buf, bufLen));
} else if (hand->callbacks->yajl_integer) {
long int i = 0;
yajl_buf_clear(hand->decodeBuf);
yajl_buf_append(hand->decodeBuf, buf, bufLen);
buf = yajl_buf_data(hand->decodeBuf);
i = strtol((const char *) buf, NULL, 10);
if ((i == LONG_MIN || i == LONG_MAX) &&
long long int i = 0;
i = yajl_parse_integer(buf, bufLen);
if ((i == LLONG_MIN || i == LLONG_MAX) &&
errno == ERANGE)
{
yajl_bs_set(hand->stateStack,
@@ -281,9 +330,10 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
}
}
break;
case yajl_tok_right_brace: {
if (yajl_bs_current(hand->stateStack) ==
yajl_state_array_start)
case yajl_tok_right_bracket: {
yajl_state s = yajl_bs_current(hand->stateStack);
if (s == yajl_state_array_start ||
s == yajl_state_array_need_val)
{
if (hand->callbacks &&
hand->callbacks->yajl_end_array)
@@ -291,13 +341,13 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
_CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
}
yajl_bs_pop(hand->stateStack);
goto around_again;
goto around_again;
}
/* intentional fall-through */
}
case yajl_tok_colon:
case yajl_tok_comma:
case yajl_tok_right_bracket:
case yajl_tok_colon:
case yajl_tok_comma:
case yajl_tok_right_brace:
yajl_bs_set(hand->stateStack, yajl_state_parse_error);
hand->parseError =
"unallowed token at this point in JSON text";
@@ -310,11 +360,11 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
/* got a value. transition depends on the state we're in. */
{
yajl_state s = yajl_bs_current(hand->stateStack);
if (s == yajl_state_start) {
if (s == yajl_state_start || s == yajl_state_got_value) {
yajl_bs_set(hand->stateStack, yajl_state_parse_complete);
} else if (s == yajl_state_map_need_val) {
yajl_bs_set(hand->stateStack, yajl_state_map_got_val);
} else {
} else {
yajl_bs_set(hand->stateStack, yajl_state_array_got_val);
}
}
@@ -324,7 +374,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
goto around_again;
}
case yajl_state_map_start:
case yajl_state_map_start:
case yajl_state_map_need_key: {
/* only difference between these two states is that in
* start '}' is valid, whereas in need_key, we've parsed
@@ -333,7 +383,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
offset, &buf, &bufLen);
switch (tok) {
case yajl_tok_eof:
return yajl_status_insufficient_data;
return yajl_status_ok;
case yajl_tok_error:
yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
goto around_again;
@@ -352,20 +402,21 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
}
yajl_bs_set(hand->stateStack, yajl_state_map_sep);
goto around_again;
case yajl_tok_right_bracket:
if (yajl_bs_current(hand->stateStack) ==
yajl_state_map_start)
{
case yajl_tok_right_brace: {
yajl_state s = yajl_bs_current(hand->stateStack);
if (s == yajl_state_map_start ||
s == yajl_state_map_need_key) {
if (hand->callbacks && hand->callbacks->yajl_end_map) {
_CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
}
yajl_bs_pop(hand->stateStack);
goto around_again;
goto around_again;
}
}
default:
yajl_bs_set(hand->stateStack, yajl_state_parse_error);
hand->parseError =
"invalid object key (must be a string)";
"invalid object key (must be a string)";
goto around_again;
}
}
@@ -375,9 +426,9 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
switch (tok) {
case yajl_tok_colon:
yajl_bs_set(hand->stateStack, yajl_state_map_need_val);
goto around_again;
goto around_again;
case yajl_tok_eof:
return yajl_status_insufficient_data;
return yajl_status_ok;
case yajl_tok_error:
yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
goto around_again;
@@ -392,24 +443,24 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
offset, &buf, &bufLen);
switch (tok) {
case yajl_tok_right_bracket:
case yajl_tok_right_brace:
if (hand->callbacks && hand->callbacks->yajl_end_map) {
_CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
}
yajl_bs_pop(hand->stateStack);
goto around_again;
goto around_again;
case yajl_tok_comma:
yajl_bs_set(hand->stateStack, yajl_state_map_need_key);
goto around_again;
goto around_again;
case yajl_tok_eof:
return yajl_status_insufficient_data;
return yajl_status_ok;
case yajl_tok_error:
yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
goto around_again;
default:
yajl_bs_set(hand->stateStack, yajl_state_parse_error);
hand->parseError = "after key and value, inside map, "
"I expect ',' or '}'";
hand->parseError = "after key and value, inside map, "
"I expect ',' or '}'";
/* try to restore error offset */
if (*offset >= bufLen) *offset -= bufLen;
else *offset = 0;
@@ -420,17 +471,17 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
offset, &buf, &bufLen);
switch (tok) {
case yajl_tok_right_brace:
case yajl_tok_right_bracket:
if (hand->callbacks && hand->callbacks->yajl_end_array) {
_CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
}
yajl_bs_pop(hand->stateStack);
goto around_again;
goto around_again;
case yajl_tok_comma:
yajl_bs_set(hand->stateStack, yajl_state_array_need_val);
goto around_again;
goto around_again;
case yajl_tok_eof:
return yajl_status_insufficient_data;
return yajl_status_ok;
case yajl_tok_error:
yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
goto around_again;
@@ -442,8 +493,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
}
}
}
abort();
return yajl_status_error;
}

View File

@@ -1,34 +1,18 @@
/*
* Copyright 2010, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 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.
*
* 3. Neither the name of Lloyd Hilaiel nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
*/
* Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __YAJL_PARSER_H__
#define __YAJL_PARSER_H__
@@ -36,6 +20,7 @@
#include "yajl_parse.h"
#include "yajl_bytestack.h"
#include "yajl_buf.h"
#include "yajl_lex.h"
typedef enum {
@@ -44,13 +29,14 @@ typedef enum {
yajl_state_parse_error,
yajl_state_lexical_error,
yajl_state_map_start,
yajl_state_map_sep,
yajl_state_map_sep,
yajl_state_map_need_val,
yajl_state_map_got_val,
yajl_state_map_need_key,
yajl_state_array_start,
yajl_state_array_got_val,
yajl_state_array_need_val
yajl_state_array_need_val,
yajl_state_got_value,
} yajl_state;
struct yajl_handle_t {
@@ -61,22 +47,32 @@ struct yajl_handle_t {
/* the number of bytes consumed from the last client buffer,
* in the case of an error this will be an error offset, in the
* case of an error this can be used as the error offset */
unsigned int bytesConsumed;
size_t bytesConsumed;
/* temporary storage for decoded strings */
yajl_buf decodeBuf;
/* a stack of states. access with yajl_state_XXX routines */
yajl_bytestack stateStack;
/* memory allocation routines */
yajl_alloc_funcs alloc;
/* bitfield */
unsigned int flags;
};
yajl_status
yajl_do_parse(yajl_handle handle, const unsigned char * jsonText,
unsigned int jsonTextLen);
size_t jsonTextLen);
yajl_status
yajl_do_finish(yajl_handle handle);
unsigned char *
yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
unsigned int jsonTextLen, int verbose);
size_t jsonTextLen, int verbose);
/* A little built in integer parsing routine with the same semantics as strtol
* that's unaffected by LOCALE. */
long long
yajl_parse_integer(const unsigned char *number, size_t length);
#endif

View File

@@ -12,6 +12,7 @@ include $(TOP)/configure/CONFIG
PROD_LIBS += Com
PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
PROD_SYS_LIBS_solaris += socket nsl
TESTPROD_HOST += epicsUnitTestTest
epicsUnitTestTest_SRCS += epicsUnitTestTest.c
@@ -48,8 +49,6 @@ TESTS += epicsMathTest
TESTPROD_HOST += epicsMMIOTest
epicsMMIOTest_SRCS += epicsMMIOTest.c
epicsMMIOTest_SYS_LIBS_solaris = socket
epicsMMIOTest_SYS_LIBS_WIN32 = ws2_32 user32
testHarness_SRCS += epicsMMIOTest.c
TESTS += epicsMMIOTest
@@ -65,8 +64,6 @@ TESTS += epicsEnvTest
TESTPROD_HOST += epicsErrlogTest
epicsErrlogTest_SRCS += epicsErrlogTest.c
epicsErrlogTest_SYS_LIBS_solaris = socket
epicsErrlogTest_SYS_LIBS_WIN32 = ws2_32 user32
testHarness_SRCS += epicsErrlogTest.c
TESTS += epicsErrlogTest
@@ -82,8 +79,6 @@ TESTS += epicsStdlibTest
TESTPROD_HOST += epicsSockResolveTest
epicsSockResolveTest_SRCS += epicsSockResolveTest.c
epicsSockResolveTest_SYS_LIBS_solaris = socket
epicsSockResolveTest_SYS_LIBS_WIN32 = ws2_32 user32
testHarness_SRCS += epicsSockResolveTest.c
TESTS += epicsSockResolveTest
@@ -198,9 +193,6 @@ TESTS += taskwdTest
TESTPROD_HOST += blockingSockTest
blockingSockTest_SRCS += blockingSockTest.cpp
testHarness_SRCS += blockingSockTest.cpp
# needed when its an object library build
blockingSockTest_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
blockingSockTest_SYS_LIBS_solaris = socket
TESTS += blockingSockTest
TESTPROD_HOST += epicsMessageQueueTest
@@ -218,6 +210,18 @@ ipAddrToAsciiTest_SRCS += ipAddrToAsciiTest.cpp
testHarness_SRCS += ipAddrToAsciiTest.cpp
TESTS += ipAddrToAsciiTest
TESTPROD_HOST += osiSockTest
osiSockTest_SRCS += osiSockTest.c
testHarness_SRCS += osiSockTest.c
TESTS += osiSockTest
ifneq ($(OS_CLASS),WIN32)
# This test can only be run on a build host, and is broken on Windows
TESTPROD_HOST += yajl_test
yajl_test_SRCS += yajl_test.c
TESTS += yajlTest
endif
# The testHarness runs all the test programs in a known working order.
testHarness_SRCS += epicsRunLibComTests.c
@@ -262,4 +266,3 @@ cvtFastPerform_SRCS += cvtFastPerform.cpp
testHarness_SRCS += cvtFastPerform.cpp
include $(TOP)/configure/RULES

View File

@@ -51,6 +51,7 @@ int epicsInlineTest(void);
int ipAddrToAsciiTest(void);
int macDefExpandTest(void);
int macLibTest(void);
int osiSockTest(void);
int ringBytesTest(void);
int ringPointerTest(void);
int taskwdTest(void);
@@ -104,6 +105,7 @@ void epicsRunLibComTests(void)
runTest(ipAddrToAsciiTest);
runTest(macDefExpandTest);
runTest(macLibTest);
runTest(osiSockTest);
runTest(ringBytesTest);
runTest(ringPointerTest);
runTest(taskwdTest);

74
test/osiSockTest.c Normal file
View File

@@ -0,0 +1,74 @@
/*************************************************************************\
* Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <string.h>
#include <stdio.h>
#include "osiSock.h"
#include "epicsUnitTest.h"
#include "testMain.h"
/* This could easily be generalized to test more options */
void udpBroadcast(SOCKET s, int put)
{
int status;
int flag = put;
osiSocklen_t len = sizeof(flag);
status = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&flag, len);
testOk(status >= 0, "setsockopt BROADCAST := %d", put);
status = getsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&flag, &len);
testOk(status >= 0 && len == sizeof(flag) && !flag == !put,
"getsockopt BROADCAST => %d", flag);
}
void multiCastLoop(SOCKET s, int put)
{
int status;
osiSockOptMcastLoop_t flag = put;
osiSocklen_t len = sizeof(flag);
status = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&flag, len);
testOk(status >= 0, "setsockopt MULTICAST_LOOP := %d", put);
status = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&flag, &len);
testOk(status >= 0 && len == sizeof(flag) && !flag == !put,
"getsockopt MULTICAST_LOOP => %d", (int) flag);
}
void udpSockTest(void)
{
SOCKET s;
s = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
testOk(s != INVALID_SOCKET, "epicsSocketCreate INET, DGRAM, 0");
udpBroadcast(s, 1);
udpBroadcast(s, 0);
multiCastLoop(s, 1);
multiCastLoop(s, 0);
epicsSocketDestroy(s);
}
MAIN(osiSockTest)
{
int status;
testPlan(10);
status = osiSockAttach();
testOk(status, "osiSockAttach");
udpSockTest();
osiSockRelease();
return testDone();
}

View File

@@ -238,9 +238,11 @@ MAIN(ringPointerTest)
testPlan(37);
testSingle();
epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityScanLow);
if (prio)
epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityScanLow);
testPair(0);
testPair(1);
epicsThreadSetPriority(epicsThreadGetIdSelf(), prio);
if (prio)
epicsThreadSetPriority(epicsThreadGetIdSelf(), prio);
return testDone();
}

View File

@@ -10,6 +10,7 @@
*/
#include <stdio.h>
#include <string.h>
#include "taskwd.h"
#include "errlog.h"
@@ -17,50 +18,78 @@
#include "epicsUnitTest.h"
#include "testMain.h"
/* This is a unique prefix used for the names of the test threads */
#define baseName "testTask"
void monInsert(void *usr, epicsThreadId tid)
{
testPass("monInsert(tid=%p)", (void *)tid);
char tname[32];
epicsThreadGetName(tid, tname, sizeof(tname));
if (strncmp(tname, baseName, strlen(baseName)) == 0)
testPass("monInsert(thread='%s')", tname);
else
testDiag("monInsert(thread='%s')", tname);
}
void monNotify(void *usr, epicsThreadId tid, int suspended)
{
testPass("monNotify(tid=%p, suspended=%d)", (void *)tid, suspended);
char tname[32];
epicsThreadGetName(tid, tname, sizeof(tname));
testPass("monNotify(thread='%s', suspended=%d)", tname, suspended);
epicsThreadResume(tid);
}
void monRemove(void *usr, epicsThreadId tid)
{
testPass("monRemove(tid=%p)", (void *)tid);
char tname[32];
epicsThreadGetName(tid, tname, sizeof(tname));
if (strncmp(tname, baseName, strlen(baseName)) == 0)
testPass("monRemove(thread='%s')", tname);
else
testDiag("monRemove(thread='%s')", tname);
}
taskwdMonitor monFuncs = {monInsert, monNotify, monRemove};
void anyNotify(void *usr, epicsThreadId tid)
{
testPass("anyNotify(tid=%p)", (void *)tid);
char tname[32];
epicsThreadGetName(tid, tname, sizeof(tname));
if (strncmp(tname, baseName, strlen(baseName)) == 0)
testPass("anyNotify(thread='%s')", tname);
else
testDiag("anyNotify(thread='%s')", tname);
}
void taskNotify(void *usr)
{
testPass("taskNotify");
const char *id = (const char *) usr;
testPass("taskNotify id='%s'", id);
}
void testTask1(void *arg)
{
taskwdInsert(0, taskNotify, NULL);
epicsThreadSleep(10.0);
taskwdInsert(0, taskNotify, "1");
epicsThreadSleep(14.0);
testDiag("Task 1 cleaning up");
taskwdRemove(0);
}
void testTask2(void *arg)
{
taskwdInsert(0, taskNotify, NULL);
testDiag("Task suspending");
taskwdInsert(0, taskNotify, "2");
epicsThreadSleep(1.0);
testDiag("Task 2 suspending");
epicsThreadSuspendSelf();
epicsThreadSleep(1.0);
testDiag("Alive again");
epicsThreadSleep(10.0);
testDiag("Task 2 alive again");
epicsThreadSleep(6.0);
testDiag("Task 2 cleaning up");
taskwdRemove(0);
}
@@ -73,12 +102,12 @@ MAIN(taskwdTest)
taskwdMonitorAdd(&monFuncs, NULL);
taskwdAnyInsert(NULL, anyNotify, NULL);
epicsThreadCreate("testTask1", epicsThreadPriorityMax,
epicsThreadCreate(baseName "1", epicsThreadPriorityMax,
epicsThreadGetStackSize(epicsThreadStackSmall),
testTask1, NULL);
epicsThreadSleep(1.0);
epicsThreadCreate("testTask2", epicsThreadPriorityMax,
epicsThreadCreate(baseName "2", epicsThreadPriorityMax,
epicsThreadGetStackSize(epicsThreadStackSmall),
testTask2, NULL);
@@ -91,4 +120,3 @@ MAIN(taskwdTest)
eltc(1);
return testDone();
}

51
test/yajlTest.plt Normal file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/perl
#
# This is a test director for running yajl JSON parser tests.
# The tests are actually defined in the yajlTestCases.pm module,
# which is generated from the yajl cases by yajlTestConverter.pl
use strict;
use Test::More;
use IO::Handle;
use IPC::Open3;
# Load test cases
use lib "..";
use yajlTestCases;
my @cases = cases();
plan tests => scalar @cases;
# The yajl_test program reads JSON from stdin and sends a description
# of what it got to stdout, with errors going to stderr. We merge the
# two output streams for the purpose of checking the test results.
my $prog = './yajl_test';
$prog .= '.exe' if ($^O eq 'MSWin32') || ($^O eq 'cygwin');
foreach my $case (@cases) {
my $name = $case->{name};
my @opts = @{$case->{opts}};
my @input = @{$case->{input}};
my @gives = @{$case->{gives}};
my ($rx, $tx);
my $pid = open3($tx, $rx, 0, $prog, @opts);
# Send the test case, then EOF
print $tx join "\n", @input;
close $tx;
# Receive the result
my @result;
while (!$rx->eof) {
chomp(my $line = <$rx>);
push @result, $line;
}
close $rx;
# Clean up the child process
waitpid $pid, 0;
# Report the result of this test case
is_deeply(\@result, \@gives, $name);
}

3069
test/yajlTestCases.pm Normal file

File diff suppressed because it is too large Load Diff

98
test/yajlTestConverter.pl Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/perl
#
# This script converts the parsing test cases from the yajl release tree
# into the yajlTestCases module as used by libCom/test/yajlTest.plt
#
# Re-do this conversion and commit after checking out a new version of yajl
# from https://github.com/lloyd/yajl as follows:
# $ cd <base>/src/libCom/test
# $ perl yajlTestConverter.pl /path/to/yajl
# The tests are saved into the file yajlTestCases.pm in the src/libCom/test
# directory which will be read by the yajlTest.t test script.
use Data::Dumper;
my $yajl = shift @ARGV
or die "Usage: $0 /path/to/yajl\n";
my @files = glob "$yajl/test/parsing/cases/*.json";
my $caseFile = 'yajlTestCases.pm';
my @cases;
for my $file (@files) {
$file =~ m|/([afn][cgmp]_)?([^/]*)\.json$|;
my $allow = $1;
my $name = $2;
next if $name eq '';
my $case = { name => $name };
if ($allow eq 'ac_') {
$case->{opts} = ['-c'];
}
elsif ($allow eq 'ag_') {
$case->{opts} = ['-g'];
}
elsif ($allow eq 'am_') {
$case->{opts} = ['-m'];
}
elsif ($allow eq 'ap_') {
$case->{opts} = ['-p'];
}
else {
$case->{opts} = [];
}
my $input = slurp($file);
my @input = split "\n", $input;
push @input, '' if $input =~ m/\n$/;
$case->{input} = \@input;
my @gives = split "\n", slurp("$file.gold");
$case->{gives} = \@gives;
push @cases, $case;
}
# Configure Dumper() output
$Data::Dumper::Pad = ' ';
$Data::Dumper::Indent = 1;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Quotekeys = 0;
$Data::Dumper::Sortkeys = sub { return ['name', 'opts', 'input', 'gives'] };
my $data = Dumper(\@cases);
open my $out, '>', $caseFile
or die "Can't open/create $caseFile: $@\n";
print $out <<"EOF";
# Parser test cases from https://github.com/lloyd/yajl
#
# This file is generated, DO NOT EDIT!
#
# See comments in yajlTestConverter.pl for instructions on
# how to regenerate this file from the original yajl sources.
sub cases {
my$data
return \@{\$VAR1};
}
1;
EOF
close $out
or die "Problem writing $caseFile: $@\n";
exit 0;
sub slurp {
my ($file) = @_;
open my $in, '<', $file
or die "Can't open file $file: $!\n";
my $contents = do { local $/; <$in> };
return $contents;
}

294
test/yajl_test.c Normal file
View File

@@ -0,0 +1,294 @@
/*
* Copyright (c) 2007-2014, Lloyd Hilaiel <me@lloyd.io>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <yajl_parse.h>
#include <yajl_gen.h>
#include <assert.h>
/* memory debugging routines */
typedef struct
{
unsigned int numFrees;
unsigned int numMallocs;
/* XXX: we really need a hash table here with per-allocation
* information */
} yajlTestMemoryContext;
/* cast void * into context */
#define TEST_CTX(vptr) ((yajlTestMemoryContext *) (vptr))
static void yajlTestFree(void * ctx, void * ptr)
{
assert(ptr != NULL);
TEST_CTX(ctx)->numFrees++;
free(ptr);
}
static void * yajlTestMalloc(void * ctx, size_t sz)
{
assert(sz != 0);
TEST_CTX(ctx)->numMallocs++;
return malloc(sz);
}
static void * yajlTestRealloc(void * ctx, void * ptr, size_t sz)
{
if (ptr == NULL) {
assert(sz != 0);
TEST_CTX(ctx)->numMallocs++;
} else if (sz == 0) {
TEST_CTX(ctx)->numFrees++;
}
return realloc(ptr, sz);
}
/* begin parsing callback routines */
#define BUF_SIZE 2048
static int test_yajl_null(void *ctx)
{
printf("null\n");
return 1;
}
static int test_yajl_boolean(void * ctx, int boolVal)
{
printf("bool: %s\n", boolVal ? "true" : "false");
return 1;
}
static int test_yajl_integer(void *ctx, long long integerVal)
{
printf("integer: %lld\n", integerVal);
return 1;
}
static int test_yajl_double(void *ctx, double doubleVal)
{
printf("double: %g\n", doubleVal);
return 1;
}
static int test_yajl_string(void *ctx, const unsigned char * stringVal,
size_t stringLen)
{
printf("string: '");
fwrite(stringVal, 1, stringLen, stdout);
printf("'\n");
return 1;
}
static int test_yajl_map_key(void *ctx, const unsigned char * stringVal,
size_t stringLen)
{
char * str = (char *) malloc(stringLen + 1);
str[stringLen] = 0;
memcpy(str, stringVal, stringLen);
printf("key: '%s'\n", str);
free(str);
return 1;
}
static int test_yajl_start_map(void *ctx)
{
printf("map open '{'\n");
return 1;
}
static int test_yajl_end_map(void *ctx)
{
printf("map close '}'\n");
return 1;
}
static int test_yajl_start_array(void *ctx)
{
printf("array open '['\n");
return 1;
}
static int test_yajl_end_array(void *ctx)
{
printf("array close ']'\n");
return 1;
}
static yajl_callbacks callbacks = {
test_yajl_null,
test_yajl_boolean,
test_yajl_integer,
test_yajl_double,
NULL,
test_yajl_string,
test_yajl_start_map,
test_yajl_map_key,
test_yajl_end_map,
test_yajl_start_array,
test_yajl_end_array
};
static void usage(const char * progname)
{
fprintf(stderr,
"usage: %s [options]\n"
"Parse input from stdin as JSON and ouput parsing details "
"to stdout\n"
" -b set the read buffer size\n"
" -c allow comments\n"
" -g allow *g*arbage after valid JSON text\n"
" -h print this help message\n"
" -m allows the parser to consume multiple JSON values\n"
" from a single string separated by whitespace\n"
" -p partial JSON documents should not cause errors\n",
progname);
exit(1);
}
int
main(int argc, char ** argv)
{
yajl_handle hand;
const char * fileName = NULL;
static unsigned char * fileData = NULL;
FILE *file;
size_t bufSize = BUF_SIZE;
yajl_status stat;
size_t rd;
int i, j;
/* memory allocation debugging: allocate a structure which collects
* statistics */
yajlTestMemoryContext memCtx = { 0,0 };
/* memory allocation debugging: allocate a structure which holds
* allocation routines */
yajl_alloc_funcs allocFuncs = {
yajlTestMalloc,
yajlTestRealloc,
yajlTestFree,
(void *) NULL
};
allocFuncs.ctx = (void *) &memCtx;
/* allocate the parser */
hand = yajl_alloc(&callbacks, &allocFuncs, NULL);
/* check arguments. We expect exactly one! */
for (i=1;i<argc;i++) {
if (!strcmp("-c", argv[i])) {
yajl_config(hand, yajl_allow_comments, 1);
} else if (!strcmp("-b", argv[i])) {
if (++i >= argc) usage(argv[0]);
/* validate integer */
for (j=0;j<(int)strlen(argv[i]);j++) {
if (argv[i][j] <= '9' && argv[i][j] >= '0') continue;
fprintf(stderr, "-b requires an integer argument. '%s' "
"is invalid\n", argv[i]);
usage(argv[0]);
}
bufSize = atoi(argv[i]);
if (!bufSize) {
fprintf(stderr, "%zu is an invalid buffer size\n",
bufSize);
}
} else if (!strcmp("-g", argv[i])) {
yajl_config(hand, yajl_allow_trailing_garbage, 1);
} else if (!strcmp("-h", argv[i])) {
usage(argv[0]);
} else if (!strcmp("-m", argv[i])) {
yajl_config(hand, yajl_allow_multiple_values, 1);
} else if (!strcmp("-p", argv[i])) {
yajl_config(hand, yajl_allow_partial_values, 1);
} else {
fileName = argv[i];
break;
}
}
fileData = (unsigned char *) malloc(bufSize);
if (fileData == NULL) {
fprintf(stderr,
"failed to allocate read buffer of %zu bytes, exiting.",
bufSize);
yajl_free(hand);
exit(2);
}
if (fileName)
{
file = fopen(fileName, "r");
}
else
{
file = stdin;
}
for (;;) {
rd = fread((void *) fileData, 1, bufSize, file);
if (rd == 0) {
if (!feof(file)) {
fprintf(stderr, "error reading from '%s'\n", fileName);
}
break;
}
/* read file data, now pass to parser */
stat = yajl_parse(hand, fileData, rd);
if (stat != yajl_status_ok) break;
}
stat = yajl_complete_parse(hand);
if (stat != yajl_status_ok)
{
unsigned char * str = yajl_get_error(hand, 0, fileData, rd);
fflush(stdout);
fprintf(stderr, "%s", (char *) str);
yajl_free_error(hand, str);
}
yajl_free(hand);
free(fileData);
if (fileName)
{
fclose(file);
}
/* finally, print out some memory statistics */
/* (lth) only print leaks here, as allocations and frees may vary depending
* on read buffer size, causing false failures.
*
* printf("allocations:\t%u\n", memCtx.numMallocs);
* printf("frees:\t\t%u\n", memCtx.numFrees);
*/
fflush(stderr);
fflush(stdout);
printf("memory leaks:\t%u\n", memCtx.numMallocs - memCtx.numFrees);
return 0;
}