Merge changes from 3.16 and below into libcom/master
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
17
src/yajl/RULES
Normal 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
|
||||
138
src/yajl/yajl.c
138
src/yajl/yajl.c
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
74
test/osiSockTest.c
Normal 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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
51
test/yajlTest.plt
Normal 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
3069
test/yajlTestCases.pm
Normal file
File diff suppressed because it is too large
Load Diff
98
test/yajlTestConverter.pl
Executable file
98
test/yajlTestConverter.pl
Executable 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
294
test/yajl_test.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user