RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  j...@rpm5.org
  Module: rpm                              Date:   12-Mar-2016 22:53:07
  Branch: rpm-5_4                          Handle: 2016031221530501

  Added files:              (Branch: rpm-5_4)
    rpm/rpmio               jsmn.h
  Modified files:           (Branch: rpm-5_4)
    rpm                     CHANGES INSTALL
    rpm/rpmio               Makefile.am duktape.c duktape.h jsmn.c tjsmn.c

  Log:
    - jsmn: update to latest checkout 572ace5, add to librpmio.
    - duk: update to 1.4.0, add to librpmio.

  Summary:
    Revision    Changes     Path
    1.3501.2.465+2  -1      rpm/CHANGES
    2.134.2.17  +1  -0      rpm/INSTALL
    1.293.2.60  +7  -5      rpm/rpmio/Makefile.am
    1.1.2.4     +0  -2      rpm/rpmio/duktape.c
    1.1.2.3     +35 -5      rpm/rpmio/duktape.h
    1.1.2.3     +21 -116    rpm/rpmio/jsmn.c
    1.1.2.1     +78 -0      rpm/rpmio/jsmn.h
    1.1.2.3     +283 -414   rpm/rpmio/tjsmn.c
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/CHANGES
  ============================================================================
  $ cvs diff -u -r1.3501.2.464 -r1.3501.2.465 CHANGES
  --- rpm/CHANGES       12 Mar 2016 20:31:10 -0000      1.3501.2.464
  +++ rpm/CHANGES       12 Mar 2016 21:53:05 -0000      1.3501.2.465
  @@ -1,5 +1,6 @@
   5.4.15 -> 5.4.16:
  -    - jbj: duk: update to 1.4.0.
  +    - jbj: jsmn: update to latest checkout 572ace5, add to librpmio.
  +    - jbj: duk: update to 1.4.0, add to librpmio.
       - jbj: yajl: add test cases.
       - jbj: yajl: split (amalgamated) yajl cleanly from mongo-c-driver.
       - jbj: mongoc: update to mongoc-1.3.2.
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/INSTALL
  ============================================================================
  $ cvs diff -u -r2.134.2.16 -r2.134.2.17 INSTALL
  --- rpm/INSTALL       12 Mar 2016 20:31:10 -0000      2.134.2.16
  +++ rpm/INSTALL       12 Mar 2016 21:53:05 -0000      2.134.2.17
  @@ -65,6 +65,7 @@
   libbson         bundled   1.3.3   1.3.3   https://github.com/mongodb/libbson
   mongo-c-driver  bundled   1.3.2   1.3.2   
https://github.com/mongodb/mongo-c-driver
   duktape         bundled   1.4.0   1.4.0   http://www.duktape.org/index.html
  +jsmn            bundled   -       572ace5 https://github.com/zserge/jsmn
   --------------- --------- ------- ------- 
-------------------------------------
   
   [0] m4:        NOTICE: Do not use GNU m4 1.4.10, it breaks GNU autoconf.
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/Makefile.am
  ============================================================================
  $ cvs diff -u -r1.293.2.59 -r1.293.2.60 Makefile.am
  --- rpm/rpmio/Makefile.am     12 Mar 2016 20:31:10 -0000      1.293.2.59
  +++ rpm/rpmio/Makefile.am     12 Mar 2016 21:53:06 -0000      1.293.2.60
  @@ -15,8 +15,8 @@
        rpmjsio.msg rpmtar.c rpmtar.h \
        tdir.c tfts.c tget.c tgfs.c tgit.c tglob.c thkp.c thtml.c tinv.c tkey.c 
\
        tmire.c todbc.c tput.c tpython.c trpmio.c tsexp.c tsvn.c tsw.c \
  -     lookup3.c jsmn.c tjsmn.c tjson.c yajl.c testit.sh \
  -     microjson.c duktape.c duktape.h duk.c mongoc-counters.defs
  +     lookup3.c tjsmn.c tjson.c yajl.c testit.sh \
  +     microjson.c mongoc-counters.defs
   
   EXTRA_PROGRAMS = rpmcpio rpmdpkg rpmtar rpmz
   EXTRA_PROGRAMS += bdes thtml tinv tkey tmacro tpw
  @@ -127,8 +127,8 @@
        ar.h bcon.h bson.h cpio.h crc.h envvar.h fnmatch.h fts.h glob.h iosm.h \
        blake2.h blake2-impl.h blake2-rpm.h blake2-kat.h \
        arirang.h blake.h bmw.h chi.h cubehash.h echo.h edon-r.h fugue.h \
  -     groestl.h hamsi.h jh.h keccak.h lane.h luffa.h md2.h md6.h mongoc.h \
  -     radiogatun.h \
  +     groestl.h hamsi.h jh.h jsmn.h keccak.h lane.h luffa.h md2.h md6.h \
  +     duktape.h mongoc.h radiogatun.h \
        salsa10.h salsa20.h shabal.h shavite3.h simd.h skein.h tib3.h tiger.h \
        pcrs.h poptIO.h rpmacl.h rpmasn.h rpmaug.h rpmbag.h rpmbc.h rpmbz.h \
        rpmcdsa.h rpmct.h rpmcudf.h rpmcvs.h rpmdate.h rpmdav.h rpmdir.h \
  @@ -167,6 +167,7 @@
        glob.c \
        gzdio.c \
        iosm.c \
  +     jsmn.c \
        lsyck.c \
        macro.c \
        mire.c \
  @@ -238,7 +239,8 @@
   if HAVE_LD_VERSION_SCRIPT
   librpmio_la_LDFLAGS += 
-Wl,@LD_VERSION_SCRIPT_FLAG@,@top_srcdir@/rpmio/librpmio.vers
   endif
  -librpmio_la_LIBADD = -lm
  +# XXX FIXME: error: inlining failed in call to always_inline ‘__signbit’
  +librpmio_la_LIBADD = duktape.o -lm
   if ENABLE_BUILD_INTLIBDEP
   librpmio_la_LIBADD += \
        $(top_builddir)/misc/librpmmisc.la
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/duktape.c
  ============================================================================
  $ cvs diff -u -r1.1.2.3 -r1.1.2.4 duktape.c
  --- rpm/rpmio/duktape.c       12 Mar 2016 20:31:10 -0000      1.1.2.3
  +++ rpm/rpmio/duktape.c       12 Mar 2016 21:53:06 -0000      1.1.2.4
  @@ -23254,14 +23254,12 @@
        DUK_ASSERT_CTX_VALID(ctx);
   
        DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, 
DUK_STR_UNIMPLEMENTED);
  -     return 0;
   }
   
   DUK_EXTERNAL duk_bool_t duk_has_var(duk_context *ctx) {
        DUK_ASSERT_CTX_VALID(ctx);
   
        DUK_ERROR((duk_hthread *) ctx, DUK_ERR_UNIMPLEMENTED_ERROR, 
DUK_STR_UNIMPLEMENTED);
  -     return 0;
   }
   #line 1 "duk_bi_array.c"
   /*
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/duktape.h
  ============================================================================
  $ cvs diff -u -r1.1.2.2 -r1.1.2.3 duktape.h
  --- rpm/rpmio/duktape.h       12 Mar 2016 20:31:11 -0000      1.1.2.2
  +++ rpm/rpmio/duktape.h       12 Mar 2016 21:53:06 -0000      1.1.2.3
  @@ -117,6 +117,31 @@
   #ifndef DUKTAPE_H_INCLUDED
   #define DUKTAPE_H_INCLUDED
   
  +#if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
  +#define DUK_GNUC_PRINTF( format_idx, arg_idx )  \
  +  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
  +#define DUK_GNUC_SCANF( format_idx, arg_idx )   \
  +  __attribute__((__format__ (__scanf__, format_idx, arg_idx)))
  +#define DUK_GNUC_FORMAT( arg_idx )              \
  +  __attribute__((__format_arg__ (arg_idx)))
  +#define DUK_GNUC_NORETURN                       \
  +  __attribute__((__noreturn__))
  +#define DUK_GNUC_CONST                          \
  +  __attribute__((__const__))
  +#define DUK_GNUC_UNUSED                         \
  +  __attribute__((__unused__))
  +#define DUK_GNUC_NO_INSTRUMENT                  \
  +  __attribute__((__no_instrument_function__))
  +#else   /* !__GNUC__ */
  +#define DUK_GNUC_PRINTF( format_idx, arg_idx )
  +#define DUK_GNUC_SCANF( format_idx, arg_idx )
  +#define DUK_GNUC_FORMAT( arg_idx )
  +#define DUK_GNUC_NORETURN
  +#define DUK_GNUC_CONST
  +#define DUK_GNUC_UNUSED
  +#define DUK_GNUC_NO_INSTRUMENT
  +#endif  /* !__GNUC__ */
  +
   #define DUK_SINGLE_FILE
   
   /* External duk_config.h provides platform/compiler/OS dependent
  @@ -4497,8 +4522,10 @@
    */
   DUK_EXTERNAL_DECL void duk_get_var(duk_context *ctx);
   DUK_EXTERNAL_DECL void duk_put_var(duk_context *ctx);
  -DUK_EXTERNAL_DECL duk_bool_t duk_del_var(duk_context *ctx);
  -DUK_EXTERNAL_DECL duk_bool_t duk_has_var(duk_context *ctx);
  +DUK_EXTERNAL_DECL duk_bool_t duk_del_var(duk_context *ctx)
  +     DUK_GNUC_NORETURN;
  +DUK_EXTERNAL_DECL duk_bool_t duk_has_var(duk_context *ctx)
  +     DUK_GNUC_NORETURN;
   
   /*
    *  Object operations
  @@ -4721,9 +4748,12 @@
                                              duk_debug_read_flush_function 
read_flush_cb,
                                              duk_debug_write_flush_function 
write_flush_cb,
                                              duk_debug_detached_function 
detached_cb,
  -                                           void *udata);
  -DUK_EXTERNAL_DECL void duk_debugger_detach(duk_context *ctx);
  -DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx);
  +                                           void *udata)
  +     DUK_GNUC_NORETURN;
  +DUK_EXTERNAL_DECL void duk_debugger_detach(duk_context *ctx)
  +     DUK_GNUC_NORETURN;
  +DUK_EXTERNAL_DECL void duk_debugger_cooperate(duk_context *ctx)
  +     DUK_GNUC_CONST;
   
   /*
    *  Date provider related constants
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/jsmn.c
  ============================================================================
  $ cvs diff -u -r1.1.2.2 -r1.1.2.3 jsmn.c
  --- rpm/rpmio/jsmn.c  16 May 2015 23:31:18 -0000      1.1.2.2
  +++ rpm/rpmio/jsmn.c  12 Mar 2016 21:53:06 -0000      1.1.2.3
  @@ -1,107 +1,10 @@
  -#define      JSMN_PARENT_LINKS       1
  -/*==============================================================*/
  -/*
  - * Copyright (c) 2010 Serge A. Zaitsev
  - *
  - * Permission is hereby granted, free of charge, to any person obtaining a 
copy
  - * of this software and associated documentation files (the "Software"), to 
deal
  - * in the Software without restriction, including without limitation the 
rights
  - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  - * copies of the Software, and to permit persons to whom the Software is
  - * furnished to do so, subject to the following conditions:
  - *
  - * The above copyright notice and this permission notice shall be included in
  - * all copies or substantial portions of the Software.
  - *
  - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
THE
  - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
  - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  - * THE SOFTWARE.
  - */
  -/*==============================================================*/
  -/* --- jsmn.h */
  -
  -#ifdef __cplusplus
  -extern "C" {
  -#endif
  -
  -/**
  - * JSON type identifier. Basic types are:
  - *   o Object
  - *   o Array
  - *   o String
  - *   o Other primitive: number, boolean (true/false) or null
  - */
  -    typedef enum {
  -     JSMN_PRIMITIVE = 0,
  -     JSMN_OBJECT = 1,
  -     JSMN_ARRAY = 2,
  -     JSMN_STRING = 3
  -    } jsmntype_t;
  -
  -    typedef enum {
  -     /* Not enough tokens were provided */
  -     JSMN_ERROR_NOMEM = -1,
  -     /* Invalid character inside JSON string */
  -     JSMN_ERROR_INVAL = -2,
  -     /* The string is not a full JSON packet, more bytes expected */
  -     JSMN_ERROR_PART = -3
  -    } jsmnerr_t;
  -
  -/**
  - * JSON token description.
  - * @param            type    type (object, array, string etc.)
  - * @param            start   start position in JSON data string
  - * @param            end             end position in JSON data string
  - */
  -    typedef struct {
  -     jsmntype_t type;
  -     int start;
  -     int end;
  -     int size;
  -#ifdef JSMN_PARENT_LINKS
  -     int parent;
  -#endif
  -    } jsmntok_t;
  -
  -/**
  - * JSON parser. Contains an array of token blocks available. Also stores
  - * the string being parsed now and current position in that string
  - */
  -    typedef struct {
  -     unsigned int pos;       /* offset in the JSON string */
  -     unsigned int toknext;   /* next token to allocate */
  -     int toksuper;           /* superior token node, e.g parent object or 
array */
  -    } jsmn_parser;
  -
  -/**
  - * Create JSON parser over an array of tokens
  - */
  -    void jsmn_init(jsmn_parser * parser);
  -
  -/**
  - * Run JSON parser. It parses a JSON data string into and array of tokens, 
each describing
  - * a single JSON object.
  - */
  -    jsmnerr_t jsmn_parse(jsmn_parser * parser, const char *js, size_t len,
  -                      jsmntok_t * tokens, unsigned int num_tokens);
  -
  -#ifdef __cplusplus
  -}
  -#endif
  -
  -/*==============================================================*/
  -/* --- jsmn.c */
  +#include "jsmn.h"
   
   /**
    * Allocates a fresh unused token from the token pull.
    */
   static jsmntok_t *jsmn_alloc_token(jsmn_parser * parser,
  -                                    jsmntok_t * tokens,
  -                                    size_t num_tokens)
  +                                jsmntok_t * tokens, size_t num_tokens)
   {
       jsmntok_t *tok;
       if (parser->toknext >= num_tokens) {
  @@ -131,9 +34,9 @@
   /**
    * Fills next available token with JSON primitive.
    */
  -static jsmnerr_t jsmn_parse_primitive(jsmn_parser * parser, const char *js,
  -                                   size_t len, jsmntok_t * tokens,
  -                                   size_t num_tokens)
  +static int jsmn_parse_primitive(jsmn_parser * parser, const char *js,
  +                             size_t len, jsmntok_t * tokens,
  +                             size_t num_tokens)
   {
       jsmntok_t *token;
       int start;
  @@ -185,11 +88,11 @@
   }
   
   /**
  - * Filsl next token with JSON string.
  + * Fills next token with JSON string.
    */
  -static jsmnerr_t jsmn_parse_string(jsmn_parser * parser, const char *js,
  -                                size_t len, jsmntok_t * tokens,
  -                                size_t num_tokens)
  +static int jsmn_parse_string(jsmn_parser * parser, const char *js,
  +                          size_t len, jsmntok_t * tokens,
  +                          size_t num_tokens)
   {
       jsmntok_t *token;
   
  @@ -264,13 +167,13 @@
   /**
    * Parse JSON string and fill tokens.
    */
  -jsmnerr_t jsmn_parse(jsmn_parser * parser, const char *js, size_t len,
  -                  jsmntok_t * tokens, unsigned int num_tokens)
  +int jsmn_parse(jsmn_parser * parser, const char *js, size_t len,
  +            jsmntok_t * tokens, unsigned int num_tokens)
   {
  -    jsmnerr_t r;
  +    int r;
       int i;
       jsmntok_t *token;
  -    int count = 0;
  +    int count = parser->toknext;
   
       for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
        char c;
  @@ -362,7 +265,7 @@
            parser->toksuper = parser->toknext - 1;
            break;
        case ',':
  -         if (tokens != NULL &&
  +         if (tokens != NULL && parser->toksuper != -1 &&
                tokens[parser->toksuper].type != JSMN_ARRAY &&
                tokens[parser->toksuper].type != JSMN_OBJECT) {
   #ifdef JSMN_PARENT_LINKS
  @@ -397,7 +300,7 @@
        case 'f':
        case 'n':
            /* And they must not be keys of the object */
  -         if (tokens != NULL) {
  +         if (tokens != NULL && parser->toksuper != -1) {
                jsmntok_t *t = &tokens[parser->toksuper];
                if (t->type == JSMN_OBJECT ||
                    (t->type == JSMN_STRING && t->size != 0)) {
  @@ -424,10 +327,12 @@
        }
       }
   
  -    for (i = parser->toknext - 1; i >= 0; i--) {
  -     /* Unmatched opened object or array */
  -     if (tokens[i].start != -1 && tokens[i].end == -1) {
  -         return JSMN_ERROR_PART;
  +    if (tokens != NULL) {
  +     for (i = parser->toknext - 1; i >= 0; i--) {
  +         /* Unmatched opened object or array */
  +         if (tokens[i].start != -1 && tokens[i].end == -1) {
  +             return JSMN_ERROR_PART;
  +         }
        }
       }
   
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/jsmn.h
  ============================================================================
  $ cvs diff -u -r0 -r1.1.2.1 jsmn.h
  --- /dev/null 2016-03-12 22:45:37.000000000 +0100
  +++ jsmn.h    2016-03-12 22:53:07.625304380 +0100
  @@ -0,0 +1,78 @@
  +#ifndef __JSMN_H_
  +#define __JSMN_H_
  +
  +#include <stddef.h>
  +
  +#ifdef __cplusplus
  +extern "C" {
  +#endif
  +
  +#undef       JSMN_STRICT
  +#define      JSMN_PARENT_LINKS       1
  +
  +/**
  + * JSON type identifier. Basic types are:
  + *   o Object
  + *   o Array
  + *   o String
  + *   o Other primitive: number, boolean (true/false) or null
  + */
  +    typedef enum {
  +     JSMN_UNDEFINED = 0,
  +     JSMN_OBJECT = 1,
  +     JSMN_ARRAY = 2,
  +     JSMN_STRING = 3,
  +     JSMN_PRIMITIVE = 4
  +    } jsmntype_t;
  +
  +    enum jsmnerr {
  +     /* Not enough tokens were provided */
  +     JSMN_ERROR_NOMEM = -1,
  +     /* Invalid character inside JSON string */
  +     JSMN_ERROR_INVAL = -2,
  +     /* The string is not a full JSON packet, more bytes expected */
  +     JSMN_ERROR_PART = -3
  +    };
  +
  +/**
  + * JSON token description.
  + * @param            type    type (object, array, string etc.)
  + * @param            start   start position in JSON data string
  + * @param            end             end position in JSON data string
  + */
  +    typedef struct {
  +     jsmntype_t type;
  +     int start;
  +     int end;
  +     int size;
  +#ifdef JSMN_PARENT_LINKS
  +     int parent;
  +#endif
  +    } jsmntok_t;
  +
  +/**
  + * JSON parser. Contains an array of token blocks available. Also stores
  + * the string being parsed now and current position in that string
  + */
  +    typedef struct {
  +     unsigned int pos;       /* offset in the JSON string */
  +     unsigned int toknext;   /* next token to allocate */
  +     int toksuper;           /* superior token node, e.g parent object or 
array */
  +    } jsmn_parser;
  +
  +/**
  + * Create JSON parser over an array of tokens
  + */
  +    void jsmn_init(jsmn_parser * parser);
  +
  +/**
  + * Run JSON parser. It parses a JSON data string into and array of tokens, 
each describing
  + * a single JSON object.
  + */
  +    int jsmn_parse(jsmn_parser * parser, const char *js, size_t len,
  +                jsmntok_t * tokens, unsigned int num_tokens);
  +
  +#ifdef __cplusplus
  +}
  +#endif
  +#endif                               /* __JSMN_H_ */
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/tjsmn.c
  ============================================================================
  $ cvs diff -u -r1.1.2.2 -r1.1.2.3 tjsmn.c
  --- rpm/rpmio/tjsmn.c 16 May 2015 21:00:48 -0000      1.1.2.2
  +++ rpm/rpmio/tjsmn.c 12 Mar 2016 21:53:06 -0000      1.1.2.3
  @@ -1,9 +1,15 @@
   #include "system.h"
  +#include <stdarg.h>
   
   #include <rpmutil.h>
   
   #include "debug.h"
   
  +/*==============================================================*/
  +/* --- test.h */
  +#ifndef __TEST_H__
  +#define __TEST_H__
  +
   static int test_passed = 0;
   static int test_failed = 0;
   
  @@ -28,294 +34,284 @@
       }
   }
   
  -#define TOKEN_EQ(t, tok_start, tok_end, tok_type) \
  -     ((t).start == tok_start \
  -      && (t).end == tok_end  \
  -      && (t).type == (tok_type))
  -
  -#define TOKEN_STRING(js, t, s) \
  -     (strncmp(js+(t).start, s, (t).end - (t).start) == 0 \
  -      && (int)strlen(s) == (t).end - (t).start)
  -
  -#define TOKEN_PRINT(t) \
  -     printf("start: %d, end: %d, type: %d, size: %d\n", \
  -                     (t).start, (t).end, (t).type, (t).size)
  +#endif                               /* __TEST_H__ */
  +
  +/*==============================================================*/
  +/* --- testutil.h */
  +#ifndef __TEST_UTIL_H__
  +#define __TEST_UTIL_H__
   
  -#define JSMN_STRICT
   #include "jsmn.c"
   
  -int test_empty()
  +static int vtokeq(const char *s, jsmntok_t * t, int numtok, va_list ap)
   {
  -    const char *js;
  -    int r;
  -    jsmn_parser p;
  -    jsmntok_t t[10];
  -
  -    js = "{}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), t, 10);
  -    check(r >= 0);
  -    check(t[0].type == JSMN_OBJECT);
  -    check(t[0].start == 0 && t[0].end == 2);
  -
  -    js = "[]";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), t, 10);
  -    check(r >= 0);
  -    check(t[0].type == JSMN_ARRAY);
  -    check(t[0].start == 0 && t[0].end == 2);
  -
  -    js = "{\"a\":[]}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), t, 10);
  -    check(r >= 0);
  -    check(t[0].type == JSMN_OBJECT && t[0].start == 0 && t[0].end == 8);
  -    check(t[1].type == JSMN_STRING && t[1].start == 2 && t[1].end == 3);
  -    check(t[2].type == JSMN_ARRAY && t[2].start == 5 && t[2].end == 7);
  +    if (numtok > 0) {
  +     int i, start, end, size;
  +     int type;
  +     char *value;
  +
  +     size = -1;
  +     value = NULL;
  +     for (i = 0; i < numtok; i++) {
  +         type = va_arg(ap, int);
  +         if (type == JSMN_STRING) {
  +             value = va_arg(ap, char *);
  +             size = va_arg(ap, int);
  +             start = end = -1;
  +         } else if (type == JSMN_PRIMITIVE) {
  +             value = va_arg(ap, char *);
  +             start = end = size = -1;
  +         } else {
  +             start = va_arg(ap, int);
  +             end = va_arg(ap, int);
  +             size = va_arg(ap, int);
  +             value = NULL;
  +         }
  +         if ((int)t[i].type != type) {
  +             printf("token %d type is %d, not %d\n", i, t[i].type,
  +                    type);
  +             return 0;
  +         }
  +         if (start != -1 && end != -1) {
  +             if (t[i].start != start) {
  +                 printf("token %d start is %d, not %d\n", i, t[i].start,
  +                        start);
  +                 return 0;
  +             }
  +             if (t[i].end != end) {
  +                 printf("token %d end is %d, not %d\n", i, t[i].end,
  +                        end);
  +                 return 0;
  +             }
  +         }
  +         if (size != -1 && t[i].size != size) {
  +             printf("token %d size is %d, not %d\n", i, t[i].size,
  +                    size);
  +             return 0;
  +         }
  +
  +         if (s != NULL && value != NULL) {
  +             const char *p = s + t[i].start;
  +             if ((int)strlen(value) != t[i].end - t[i].start ||
  +                 strncmp(p, value, t[i].end - t[i].start) != 0) {
  +                 printf("token %d value is %.*s, not %s\n", i,
  +                        t[i].end - t[i].start, s + t[i].start, value);
  +                 return 0;
  +             }
  +         }
  +     }
  +    }
  +    return 1;
  +}
   
  -    js = "[{},{}]";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), t, 10);
  -    check(r >= 0);
  -    check(t[0].type == JSMN_ARRAY && t[0].start == 0 && t[0].end == 7);
  -    check(t[1].type == JSMN_OBJECT && t[1].start == 1 && t[1].end == 3);
  -    check(t[2].type == JSMN_OBJECT && t[2].start == 4 && t[2].end == 6);
  -    return 0;
  +static int tokeq(const char *s, jsmntok_t * tokens, int numtok, ...)
  +{
  +    int ok;
  +    va_list args;
  +    va_start(args, numtok);
  +    ok = vtokeq(s, tokens, numtok, args);
  +    va_end(args);
  +    return ok;
   }
   
  -int test_simple()
  +static int parse(const char *s, int status, int numtok, ...)
   {
  -    const char *js;
       int r;
  +    int ok = 1;
  +    va_list args;
       jsmn_parser p;
  -    jsmntok_t tokens[10];
  -
  -    js = "{\"a\": 0}";
  +    jsmntok_t *t = malloc(numtok * sizeof(jsmntok_t));
   
       jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  -    check(TOKEN_EQ(tokens[0], 0, 8, JSMN_OBJECT));
  -    check(TOKEN_EQ(tokens[1], 2, 3, JSMN_STRING));
  -    check(TOKEN_EQ(tokens[2], 6, 7, JSMN_PRIMITIVE));
  -
  -    check(TOKEN_STRING(js, tokens[0], js));
  -    check(TOKEN_STRING(js, tokens[1], "a"));
  -    check(TOKEN_STRING(js, tokens[2], "0"));
  +    r = jsmn_parse(&p, s, strlen(s), t, numtok);
  +    if (r != status) {
  +     printf("status is %d, not %d\n", r, status);
  +     return 0;
  +    }
   
  -    jsmn_init(&p);
  -    js = "[\"a\":{},\"b\":{}]";
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  +    if (status >= 0) {
  +     va_start(args, numtok);
  +     ok = vtokeq(s, t, numtok, args);
  +     va_end(args);
  +    }
  +    free(t);
  +    return ok;
  +}
   
  -    jsmn_init(&p);
  -    js = "{\n \"Day\": 26,\n \"Month\": 9,\n \"Year\": 12\n }";
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  +#endif                               /* __TEST_UTIL_H__ */
   
  +/*==============================================================*/
  +/* --- tests.c */
  +int test_empty(void)
  +{
  +    check(parse("{}", 1, 1, JSMN_OBJECT, 0, 2, 0));
  +    check(parse("[]", 1, 1, JSMN_ARRAY, 0, 2, 0));
  +    check(parse("[{},{}]", 3, 3,
  +             JSMN_ARRAY, 0, 7, 2,
  +             JSMN_OBJECT, 1, 3, 0, JSMN_OBJECT, 4, 6, 0));
       return 0;
   }
   
  -RPM_GNUC_CONST
  -int test_primitive()
  -{
  -#ifndef JSMN_STRICT
  -    int r;
  -    jsmn_parser p;
  -    jsmntok_t tok[10];
  -    const char *js;
  -    js = "\"boolVar\" : true";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_PRIMITIVE);
  -    check(TOKEN_STRING(js, tok[0], "boolVar"));
  -    check(TOKEN_STRING(js, tok[1], "true"));
  -
  -    js = "\"boolVar\" : false";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_PRIMITIVE);
  -    check(TOKEN_STRING(js, tok[0], "boolVar"));
  -    check(TOKEN_STRING(js, tok[1], "false"));
  -
  -    js = "\"intVar\" : 12345";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_PRIMITIVE);
  -    check(TOKEN_STRING(js, tok[0], "intVar"));
  -    check(TOKEN_STRING(js, tok[1], "12345"));
  -
  -    js = "\"floatVar\" : 12.345";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_PRIMITIVE);
  -    check(TOKEN_STRING(js, tok[0], "floatVar"));
  -    check(TOKEN_STRING(js, tok[1], "12.345"));
  -
  -    js = "\"nullVar\" : null";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_PRIMITIVE);
  -    check(TOKEN_STRING(js, tok[0], "nullVar"));
  -    check(TOKEN_STRING(js, tok[1], "null"));
  +int test_object(void)
  +{
  +    check(parse("{\"a\":0}", 3, 3,
  +             JSMN_OBJECT, 0, 7, 1,
  +             JSMN_STRING, "a", 1, JSMN_PRIMITIVE, "0"));
  +    check(parse("{\"a\":[]}", 3, 3,
  +             JSMN_OBJECT, 0, 8, 1,
  +             JSMN_STRING, "a", 1, JSMN_ARRAY, 5, 7, 0));
  +    check(parse("{\"a\":{},\"b\":{}}", 5, 5,
  +             JSMN_OBJECT, -1, -1, 2,
  +             JSMN_STRING, "a", 1,
  +             JSMN_OBJECT, -1, -1, 0,
  +             JSMN_STRING, "b", 1, JSMN_OBJECT, -1, -1, 0));
  +    check(parse
  +       ("{\n \"Day\": 26,\n \"Month\": 9,\n \"Year\": 12\n }", 7, 7,
  +        JSMN_OBJECT, -1, -1, 3, JSMN_STRING, "Day", 1, JSMN_PRIMITIVE,
  +        "26", JSMN_STRING, "Month", 1, JSMN_PRIMITIVE, "9", JSMN_STRING,
  +        "Year", 1, JSMN_PRIMITIVE, "12"));
  +    check(parse
  +       ("{\"a\": 0, \"b\": \"c\"}", 5, 5, JSMN_OBJECT, -1, -1, 2,
  +        JSMN_STRING, "a", 1, JSMN_PRIMITIVE, 0, JSMN_STRING, "b", 1,
  +        JSMN_STRING, "c", 0));
  +
  +#ifdef JSMN_STRICT
  +    check(parse("{\"a\"\n0}", JSMN_ERROR_INVAL, 3));
  +    check(parse("{\"a\", 0}", JSMN_ERROR_INVAL, 3));
  +    check(parse("{\"a\": {2}}", JSMN_ERROR_INVAL, 3));
  +    check(parse("{\"a\": {2: 3}}", JSMN_ERROR_INVAL, 3));
  +    check(parse("{\"a\": {\"a\": 2 3}}", JSMN_ERROR_INVAL, 5));
  +    /* FIXME */
  +    /*check(parse("{\"a\"}", JSMN_ERROR_INVAL, 2)); */
  +    /*check(parse("{\"a\": 1, \"b\"}", JSMN_ERROR_INVAL, 4)); */
  +    /*check(parse("{\"a\",\"b\":1}", JSMN_ERROR_INVAL, 4)); */
  +    /*check(parse("{\"a\":1,}", JSMN_ERROR_INVAL, 4)); */
  +    /*check(parse("{\"a\":\"b\":\"c\"}", JSMN_ERROR_INVAL, 4)); */
  +    /*check(parse("{,}", JSMN_ERROR_INVAL, 4)); */
   #endif
       return 0;
   }
   
  -int test_string()
  +int test_array(void)
   {
  -    int r;
  -    jsmn_parser p;
  -    jsmntok_t tok[10];
  -    const char *js;
  -
  -    js = "\"strVar\" : \"hello world\"";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "strVar"));
  -    check(TOKEN_STRING(js, tok[1], "hello world"));
  -
  -    js = "\"strVar\" : \"escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\\"";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "strVar"));
  -    check(TOKEN_STRING(js, tok[1], "escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\"));
  -
  -    js = "\"strVar\" : \"\"";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "strVar"));
  -    check(TOKEN_STRING(js, tok[1], ""));
  -
  +    /* FIXME */
  +    /*check(parse("[10}", JSMN_ERROR_INVAL, 3)); */
  +    /*check(parse("[1,,3]", JSMN_ERROR_INVAL, 3) */
  +    check(parse("[10]", 2, 2,
  +             JSMN_ARRAY, -1, -1, 1, JSMN_PRIMITIVE, "10"));
  +    check(parse("{\"a\": 1]", JSMN_ERROR_INVAL, 3));
  +    /* FIXME */
  +    /*check(parse("[\"a\": 1]", JSMN_ERROR_INVAL, 3)); */
  +    return 0;
  +}
  +
  +int test_primitive(void)
  +{
  +    check(parse("{\"boolVar\" : true }", 3, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "boolVar", 1, JSMN_PRIMITIVE, "true"));
  +    check(parse("{\"boolVar\" : false }", 3, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "boolVar", 1, JSMN_PRIMITIVE, "false"));
  +    check(parse("{\"nullVar\" : null }", 3, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "nullVar", 1, JSMN_PRIMITIVE, "null"));
  +    check(parse("{\"intVar\" : 12}", 3, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "intVar", 1, JSMN_PRIMITIVE, "12"));
  +    check(parse("{\"floatVar\" : 12.345}", 3, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "floatVar", 1, JSMN_PRIMITIVE, "12.345"));
  +    return 0;
  +}
  +
  +int test_string(void)
  +{
  +    check(parse("{\"strVar\" : \"hello world\"}", 3, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "strVar", 1, JSMN_STRING, "hello world", 0));
  +    check(parse
  +       ("{\"strVar\" : \"escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\\"}", 3, 3,
  +        JSMN_OBJECT, -1, -1, 1, JSMN_STRING, "strVar", 1, JSMN_STRING,
  +        "escapes: \\/\\r\\n\\t\\b\\f\\\"\\\\", 0));
  +    check(parse
  +       ("{\"strVar\": \"\"}", 3, 3, JSMN_OBJECT, -1, -1, 1, JSMN_STRING,
  +        "strVar", 1, JSMN_STRING, "", 0));
  +    check(parse
  +       ("{\"a\":\"\\uAbcD\"}", 3, 3, JSMN_OBJECT, -1, -1, 1,
  +        JSMN_STRING, "a", 1, JSMN_STRING, "\\uAbcD", 0));
  +    check(parse
  +       ("{\"a\":\"str\\u0000\"}", 3, 3, JSMN_OBJECT, -1, -1, 1,
  +        JSMN_STRING, "a", 1, JSMN_STRING, "str\\u0000", 0));
  +    check(parse
  +       ("{\"a\":\"\\uFFFFstr\"}", 3, 3, JSMN_OBJECT, -1, -1, 1,
  +        JSMN_STRING, "a", 1, JSMN_STRING, "\\uFFFFstr", 0));
  +    check(parse
  +       ("{\"a\":[\"\\u0280\"]}", 4, 4, JSMN_OBJECT, -1, -1, 1,
  +        JSMN_STRING, "a", 1, JSMN_ARRAY, -1, -1, 1, JSMN_STRING,
  +        "\\u0280", 0));
  +
  +    check(parse("{\"a\":\"str\\uFFGFstr\"}", JSMN_ERROR_INVAL, 3));
  +    check(parse("{\"a\":\"str\\u@FfF\"}", JSMN_ERROR_INVAL, 3));
  +    check(parse("{{\"a\":[\"\\u028\"]}", JSMN_ERROR_INVAL, 4));
       return 0;
   }
   
  -int test_partial_string()
  +int test_partial_string(void)
   {
  +    int i;
       int r;
       jsmn_parser p;
  -    jsmntok_t tok[10];
  -    const char *js;
  -
  -    jsmn_init(&p);
  -    js = "\"x\": \"va";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r == JSMN_ERROR_PART && tok[0].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "x"));
  -    check(p.toknext == 1);
  -
  -    jsmn_init(&p);
  -    char js_slash[9] = "\"x\": \"va\\";
  -    r = jsmn_parse(&p, js_slash, sizeof(js_slash), tok, 10);
  -    check(r == JSMN_ERROR_PART);
  +    jsmntok_t tok[5];
  +    const char *js = "{\"x\": \"va\\\\ue\", \"y\": \"value y\"}";
   
       jsmn_init(&p);
  -    char js_unicode[10] = "\"x\": \"va\\u";
  -    r = jsmn_parse(&p, js_unicode, sizeof(js_unicode), tok, 10);
  -    check(r == JSMN_ERROR_PART);
  -
  -    js = "\"x\": \"valu";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r == JSMN_ERROR_PART && tok[0].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "x"));
  -    check(p.toknext == 1);
  -
  -    js = "\"x\": \"value\"";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "x"));
  -    check(TOKEN_STRING(js, tok[1], "value"));
  -
  -    js = "\"x\": \"value\", \"y\": \"value y\"";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_STRING
  -       && tok[1].type == JSMN_STRING && tok[2].type == JSMN_STRING
  -       && tok[3].type == JSMN_STRING);
  -    check(TOKEN_STRING(js, tok[0], "x"));
  -    check(TOKEN_STRING(js, tok[1], "value"));
  -    check(TOKEN_STRING(js, tok[2], "y"));
  -    check(TOKEN_STRING(js, tok[3], "value y"));
  -
  +    for (i = 1; i <= (int)strlen(js); i++) {
  +     r = jsmn_parse(&p, js, i, tok, sizeof(tok) / sizeof(tok[0]));
  +     if (i == (int)strlen(js)) {
  +         check(r == 5);
  +         check(tokeq(js, tok, 5,
  +                     JSMN_OBJECT, -1, -1, 2,
  +                     JSMN_STRING, "x", 1,
  +                     JSMN_STRING, "va\\\\ue", 0,
  +                     JSMN_STRING, "y", 1, JSMN_STRING, "value y", 0));
  +     } else {
  +         check(r == JSMN_ERROR_PART);
  +     }
  +    }
       return 0;
   }
   
   RPM_GNUC_CONST
  -int test_unquoted_keys()
  +int test_partial_array(void)
   {
  -#ifndef JSMN_STRICT
  +#ifdef JSMN_STRICT
       int r;
  +    int i;
       jsmn_parser p;
       jsmntok_t tok[10];
  -    const char *js;
  +    const char *js = "[ 1, true, [123, \"hello\"]]";
   
       jsmn_init(&p);
  -    js = "key1: \"value\"\nkey2 : 123";
  -
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_PRIMITIVE
  -       && tok[1].type == JSMN_STRING && tok[2].type == JSMN_PRIMITIVE
  -       && tok[3].type == JSMN_PRIMITIVE);
  -    check(TOKEN_STRING(js, tok[0], "key1"));
  -    check(TOKEN_STRING(js, tok[1], "value"));
  -    check(TOKEN_STRING(js, tok[2], "key2"));
  -    check(TOKEN_STRING(js, tok[3], "123"));
  +    for (i = 1; i <= strlen(js); i++) {
  +     r = jsmn_parse(&p, js, i, tok, sizeof(tok) / sizeof(tok[0]));
  +     if (i == strlen(js)) {
  +         check(r == 6);
  +         check(tokeq(js, tok, 6,
  +                     JSMN_ARRAY, -1, -1, 3,
  +                     JSMN_PRIMITIVE, "1",
  +                     JSMN_PRIMITIVE, "true",
  +                     JSMN_ARRAY, -1, -1, 2,
  +                     JSMN_PRIMITIVE, "123", JSMN_STRING, "hello", 0));
  +     } else {
  +         check(r == JSMN_ERROR_PART);
  +     }
  +    }
   #endif
       return 0;
   }
   
  -int test_partial_array()
  -{
  -    int r;
  -    jsmn_parser p;
  -    jsmntok_t tok[10];
  -    const char *js;
  -
  -    jsmn_init(&p);
  -    js = "  [ 1, true, ";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r == JSMN_ERROR_PART && tok[0].type == JSMN_ARRAY
  -       && tok[1].type == JSMN_PRIMITIVE
  -       && tok[2].type == JSMN_PRIMITIVE);
  -
  -    js = "  [ 1, true, [123, \"hello";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r == JSMN_ERROR_PART && tok[0].type == JSMN_ARRAY
  -       && tok[1].type == JSMN_PRIMITIVE && tok[2].type == JSMN_PRIMITIVE
  -       && tok[3].type == JSMN_ARRAY && tok[4].type == JSMN_PRIMITIVE);
  -
  -    js = "  [ 1, true, [123, \"hello\"]";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r == JSMN_ERROR_PART && tok[0].type == JSMN_ARRAY
  -       && tok[1].type == JSMN_PRIMITIVE && tok[2].type == JSMN_PRIMITIVE
  -       && tok[3].type == JSMN_ARRAY && tok[4].type == JSMN_PRIMITIVE
  -       && tok[5].type == JSMN_STRING);
  -    /* check child nodes of the 2nd array */
  -    check(tok[3].size == 2);
  -
  -    js = "  [ 1, true, [123, \"hello\"]]";
  -    r = jsmn_parse(&p, js, strlen(js), tok, 10);
  -    check(r >= 0 && tok[0].type == JSMN_ARRAY
  -       && tok[1].type == JSMN_PRIMITIVE && tok[2].type == JSMN_PRIMITIVE
  -       && tok[3].type == JSMN_ARRAY && tok[4].type == JSMN_PRIMITIVE
  -       && tok[5].type == JSMN_STRING);
  -    check(tok[3].size == 2);
  -    check(tok[0].size == 3);
  -    return 0;
  -}
  -
  -int test_array_nomem()
  +int test_array_nomem(void)
   {
       int i;
       int r;
  @@ -336,44 +332,38 @@
   
        r = jsmn_parse(&p, js, strlen(js), toklarge, 10);
        check(r >= 0);
  -
  -     check(toklarge[0].type == JSMN_ARRAY && toklarge[0].size == 3);
  -     check(toklarge[3].type == JSMN_ARRAY && toklarge[3].size == 2);
  +     check(tokeq(js, toklarge, 4,
  +                 JSMN_ARRAY, -1, -1, 3,
  +                 JSMN_PRIMITIVE, "1",
  +                 JSMN_PRIMITIVE, "true",
  +                 JSMN_ARRAY, -1, -1, 2,
  +                 JSMN_PRIMITIVE, "123", JSMN_STRING, "hello", 0));
       }
       return 0;
   }
   
  -int test_objects_arrays()
  +int test_unquoted_keys(void)
   {
  +#ifndef JSMN_STRICT
       int r;
       jsmn_parser p;
  -    jsmntok_t tokens[10];
  +    jsmntok_t tok[10];
       const char *js;
   
  -    js = "[10}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -    js = "[10]";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  -
  -    js = "{\"a\": 1]";
       jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  +    js = "key1: \"value\"\nkey2 : 123";
   
  -    js = "{\"a\": 1}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  +    r = jsmn_parse(&p, js, strlen(js), tok, 10);
       check(r >= 0);
  -
  +    check(tokeq(js, tok, 4,
  +             JSMN_PRIMITIVE, "key1",
  +             JSMN_STRING, "value", 0,
  +             JSMN_PRIMITIVE, "key2", JSMN_PRIMITIVE, "123"));
  +#endif
       return 0;
   }
   
  -int test_issue_22()
  +int test_issue_22(void)
   {
       int r;
       jsmn_parser p;
  @@ -391,70 +381,18 @@
       jsmn_init(&p);
       r = jsmn_parse(&p, js, strlen(js), tokens, 128);
       check(r >= 0);
  -#if 0
  -    for (i = 1; tokens[i].end < tokens[0].end; i++) {
  -     if (tokens[i].type == JSMN_STRING
  -         || tokens[i].type == JSMN_PRIMITIVE) {
  -         printf("%.*s\n", tokens[i].end - tokens[i].start,
  -                js + tokens[i].start);
  -     } else if (tokens[i].type == JSMN_ARRAY) {
  -         printf("[%d elems]\n", tokens[i].size);
  -     } else if (tokens[i].type == JSMN_OBJECT) {
  -         printf("{%d elems}\n", tokens[i].size);
  -     } else {
  -         TOKEN_PRINT(tokens[i]);
  -     }
  -    }
  -#endif
       return 0;
   }
   
  -int test_unicode_characters()
  +int test_issue_27(void)
   {
  -    jsmn_parser p;
  -    jsmntok_t tokens[10];
  -    const char *js;
  -
  -    int r;
  -    js = "{\"a\":\"\\uAbcD\"}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  -
  -    js = "{\"a\":\"str\\u0000\"}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  -
  -    js = "{\"a\":\"\\uFFFFstr\"}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  -
  -    js = "{\"a\":\"str\\uFFGFstr\"}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -    js = "{\"a\":\"str\\u@FfF\"}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -    js = "{\"a\":[\"\\u028\"]}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -    js = "{\"a\":[\"\\u0280\"]}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r >= 0);
  -
  +    const char *js =
  +     "{ \"name\" : \"Jack\", \"age\" : 27 } { \"name\" : \"Anna\", ";
  +    check(parse(js, JSMN_ERROR_PART, 8));
       return 0;
   }
   
  -int test_input_length()
  +int test_input_length(void)
   {
       const char *js;
       int r;
  @@ -466,14 +404,13 @@
       jsmn_init(&p);
       r = jsmn_parse(&p, js, 8, tokens, 10);
       check(r == 3);
  -    check(TOKEN_STRING(js, tokens[0], "{\"a\": 0}"));
  -    check(TOKEN_STRING(js, tokens[1], "a"));
  -    check(TOKEN_STRING(js, tokens[2], "0"));
  -
  +    check(tokeq(js, tokens, 3,
  +             JSMN_OBJECT, -1, -1, 1,
  +             JSMN_STRING, "a", 1, JSMN_PRIMITIVE, "0"));
       return 0;
   }
   
  -int test_count()
  +int test_count(void)
   {
       jsmn_parser p;
       const char *js;
  @@ -521,112 +458,44 @@
       return 0;
   }
   
  -int test_keyvalue()
  -{
  -    const char *js;
  -    int r;
  -    jsmn_parser p;
  -    jsmntok_t tokens[10];
  -
  -    js = "{\"a\": 0, \"b\": \"c\"}";
  -
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == 5);
  -    check(tokens[0].size == 2);      /* two keys */
  -    check(tokens[1].size == 1 && tokens[3].size == 1);       /* one value 
per key */
  -    check(tokens[2].size == 0 && tokens[4].size == 0);       /* values have 
zero size */
  -
  -    js = "{\"a\"\n0}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
   
  -    js = "{\"a\", 0}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -    js = "{\"a\": {2}}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -    js = "{\"a\": {2: 3}}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -
  -
  -    js = "{\"a\": {\"a\": 2 3}}";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == JSMN_ERROR_INVAL);
  -    return 0;
  -}
  -
  -/** A huge redefinition of everything to include jsmn in non-script mode */
  -#define jsmn_init jsmn_init_nonstrict
  -#define jsmn_parse jsmn_parse_nonstrict
  -#define jsmn_parser jsmn_parser_nonstrict
  -#define jsmn_alloc_token jsmn_alloc_token_nonstrict
  -#define jsmn_fill_token jsmn_fill_token_nonstrict
  -#define jsmn_parse_primitive jsmn_parse_primitive_nonstrict
  -#define jsmn_parse_string jsmn_parse_string_nonstrict
  -#define jsmntype_t jsmntype_nonstrict_t
  -#define jsmnerr_t jsmnerr_nonstrict_t
  -#define jsmntok_t jsmntok_nonstrict_t
  -#define JSMN_PRIMITIVE JSMN_PRIMITIVE_NONSTRICT
  -#define JSMN_OBJECT JSMN_OBJECT_NONSTRICT
  -#define JSMN_ARRAY JSMN_ARRAY_NONSTRICT
  -#define JSMN_STRING JSMN_STRING_NONSTRICT
  -#define JSMN_ERROR_NOMEM JSMN_ERROR_NOMEM_NONSTRICT
  -#define JSMN_ERROR_INVAL JSMN_ERROR_INVAL_NONSTRICT
  -#define JSMN_ERROR_PART JSMN_ERROR_PART_NONSTRICT
  -#undef __JSMN_H_
  -#undef JSMN_STRICT
  -#include "jsmn.c"
  -
  -int test_nonstrict()
  +int test_nonstrict(void)
   {
  +#ifndef JSMN_STRICT
       const char *js;
  -    int r;
  -    jsmn_parser p;
  -    jsmntok_t tokens[10];
  -
       js = "a: 0garbage";
  -
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, 4, tokens, 10);
  -    check(r == 2);
  -    check(TOKEN_STRING(js, tokens[0], "a"));
  -    check(TOKEN_STRING(js, tokens[1], "0"));
  +    check(parse(js, 2, 2,
  +             JSMN_PRIMITIVE, "a", JSMN_PRIMITIVE, "0garbage"));
   
       js = "Day : 26\nMonth : Sep\n\nYear: 12";
  -    jsmn_init(&p);
  -    r = jsmn_parse(&p, js, strlen(js), tokens, 10);
  -    check(r == 6);
  +    check(parse(js, 6, 6,
  +             JSMN_PRIMITIVE, "Day",
  +             JSMN_PRIMITIVE, "26",
  +             JSMN_PRIMITIVE, "Month",
  +             JSMN_PRIMITIVE, "Sep",
  +             JSMN_PRIMITIVE, "Year", JSMN_PRIMITIVE, "12"));
  +#endif
       return 0;
   }
   
  -int main()
  +int main(void)
   {
  -    test(test_empty, "general test for a empty JSON objects/arrays");
  -    test(test_simple, "general test for a simple JSON string");
  +    test(test_empty, "test for a empty JSON objects/arrays");
  +    test(test_object, "test for a JSON objects");
  +    test(test_array, "test for a JSON arrays");
       test(test_primitive, "test primitive JSON data types");
       test(test_string, "test string JSON data types");
  +
       test(test_partial_string, "test partial JSON string parsing");
       test(test_partial_array, "test partial array reading");
       test(test_array_nomem,
         "test array reading with a smaller number of tokens");
       test(test_unquoted_keys, "test unquoted keys (like in JavaScript)");
  -    test(test_objects_arrays, "test objects and arrays");
  -    test(test_unicode_characters, "test unicode characters");
       test(test_input_length, "test strings that are not null-terminated");
       test(test_issue_22, "test issue #22");
  +    test(test_issue_27, "test issue #27");
       test(test_count, "test tokens count estimation");
       test(test_nonstrict, "test for non-strict mode");
  -    test(test_keyvalue, "test for keys/values");
       printf("\nPASSED: %d\nFAILED: %d\n", test_passed, test_failed);
  -    return 0;
  +    return (test_failed > 0);
   }
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to