Module Name:    src
Committed By:   agc
Date:           Sat Aug  7 04:13:57 UTC 2010

Added Files:
        src/crypto/external/bsd/netpgp/dist/src/libmj: Makefile.am defs.h
            libmj.3 mj.c mj.h

Log Message:
Move the minimalist JSON routines into their own library


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 \
    src/crypto/external/bsd/netpgp/dist/src/libmj/Makefile.am \
    src/crypto/external/bsd/netpgp/dist/src/libmj/defs.h \
    src/crypto/external/bsd/netpgp/dist/src/libmj/libmj.3 \
    src/crypto/external/bsd/netpgp/dist/src/libmj/mj.c \
    src/crypto/external/bsd/netpgp/dist/src/libmj/mj.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Added files:

Index: src/crypto/external/bsd/netpgp/dist/src/libmj/Makefile.am
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libmj/Makefile.am:1.1
--- /dev/null	Sat Aug  7 04:13:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/libmj/Makefile.am	Sat Aug  7 04:13:57 2010
@@ -0,0 +1,14 @@
+## $NetBSD: Makefile.am,v 1.1 2010/08/07 04:13:57 agc Exp $
+
+AM_CFLAGS		= $(WARNCFLAGS)
+
+lib_LTLIBRARIES		= libmj.la
+
+libmj_la_CPPFLAGS	= -I$(top_srcdir)/include
+
+libmj_la_SOURCES	= \
+	mj.c \
+
+man3_MANS		= mj.3
+
+dist_man_MANS		= mj.3
Index: src/crypto/external/bsd/netpgp/dist/src/libmj/defs.h
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libmj/defs.h:1.1
--- /dev/null	Sat Aug  7 04:13:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/libmj/defs.h	Sat Aug  7 04:13:57 2010
@@ -0,0 +1,95 @@
+/* $NetBSD: defs.h,v 1.1 2010/08/07 04:13:57 agc Exp $ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (a...@netbsd.org)
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DEFS_H_
+#define DEFS_H_
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NEWARRAY(type,ptr,size,where,action) do {			\
+	if ((ptr = calloc(sizeof(type), (unsigned)(size))) == NULL) {	\
+		(void) fprintf(stderr, "%s: can't allocate %lu bytes\n", \
+			where, (unsigned long)(size * sizeof(type)));	\
+		action;							\
+	}								\
+} while( /* CONSTCOND */ 0)
+
+#define RENEW(type, _ptr, _size, _newsize, where, action) do {		\
+	type *_newptr;							\
+	_newptr = realloc(_ptr, (size_t)(_newsize) * sizeof(type));	\
+	if (_newptr == NULL) {						\
+		(void) fprintf(stderr, "%s: can't realloc %lu bytes\n",	\
+			where, (unsigned long)((_newsize) * sizeof(type))); \
+		action;							\
+	} else {							\
+		(void) memset(&_newptr[_size], 0x0,			\
+			(_newsize - _size) * sizeof(type));		\
+		_ptr = _newptr;						\
+		_size = _newsize;					\
+	}								\
+} while( /* CONSTCOND */ 0)
+
+#define NEW(type, ptr, where, action)	NEWARRAY(type, ptr, 1, where, action)
+
+#define FREE(ptr)	free(ptr)
+
+#define ALLOC(type, v, size, c, init, incr, where, action) do {		\
+	uint32_t	_newsize = size;				\
+	if (size == 0) {						\
+		_newsize = init;					\
+		NEWARRAY(type, v, _newsize, where ": new", action);	\
+	} else if (c == size) {						\
+		_newsize = size + incr;					\
+		RENEW(type, v, size, _newsize, where ": renew", action); \
+	}								\
+	size = _newsize;						\
+} while( /* CONSTCOND */ 0)
+
+#define DEFINE_ARRAY(name, type)					\
+typedef struct name {							\
+	uint32_t	c;						\
+	uint32_t	size;						\
+	type	       *v;						\
+} name
+
+#endif /* !DEFS_H_ */
Index: src/crypto/external/bsd/netpgp/dist/src/libmj/libmj.3
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libmj/libmj.3:1.1
--- /dev/null	Sat Aug  7 04:13:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/libmj/libmj.3	Sat Aug  7 04:13:57 2010
@@ -0,0 +1,207 @@
+.\"
+.\" Copyright (c) 2010 Alistair Crooks <a...@netbsd.org>
+.\" All rights reserved.
+.\"
+.\" 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.
+.\"
+.\" 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.
+.\"
+.Dd August 5, 2010
+.Dt LIBMJ 3
+.Os
+.Sh NAME
+.Nm libmj
+.Nd minimalist JSON lightweight data interchange library
+.Sh LIBRARY
+.Lb libmj
+.Sh SYNOPSIS
+.In mj.h
+.Ft int
+.Fo mj_create
+.Fa "mj_t *atom" "const char *text" "..."
+.Fc
+.Ft int
+.Fo mj_parse
+.Fa "mj_t *atom" "const char *text" "int *tokfrom" "int *tokto" "int *toktype"
+.Fc
+.Ft int
+.Fo mj_append
+.Fa "mj_t *atom" "const char *text" "..."
+.Fc
+.Ft int
+.Fo mj_append_field
+.Fa "mj_t *atom" "const char *fieldname" "const char *text" "..."
+.Fc
+.Ft int
+.Fo mj_deepcopy
+.Fa "mj_t *dest" "mj_t *src"
+.Fc
+.Ft void
+.Fo mj_delete
+.Fa "mj_t *atom"
+.Fc
+.Pp
+Access to objects and array entries is made using the following functions:
+.Ft int
+.Fo mj_arraycount
+.Fa "mj_t *atom"
+.Fc
+.Ft int
+.Fo mj_object_find
+.Fa "mj_t *atom" "const char *name" "const unsigned startpoint"
+.Fa "const unsigned incr"
+.Fc
+.Ft mj_t *
+.Fo mj_get_atom
+.Fa "mj_t *atom" "..."
+.Fc
+.Pp
+JSON object output functions:
+.Ft int
+.Fo mj_snprint
+.Fa "char *buffer" "size_t size" "mj_t *atom"
+.Fc
+.Ft int
+.Fo mj_asprint
+.Fa "char **buffer" "mj_t *atom"
+.Fc
+.Ft int
+.Fo mj_string_size
+.Fa "mj_t *atom"
+.Fc
+.Sh DESCRIPTION
+.Nm
+is a small library interface to allow JSON text to be created and parsed.
+JSON is the Java Script Object Notation,
+a lightweight data-interchange format, standardised in the ECMA standard.
+The library name
+.Nm
+is derived from a further acronym of
+.Dq minimalist JSON .
+.\" Hey, Mary!
+.Pp
+The
+.Nm
+library can be used to create a string in memory which contains a textutal
+representation of a number of objects, arbitrarily structured.
+The library can also be used to reconstruct the structure.
+Data can thus be serialised easily and efficiently, and data structures
+rebuilt to produce the original structure of the data.
+.Pp
+JSON contains basic units called atoms, the two
+basic atoms being strings and numbers.
+Three other useful atomic values are provided,
+.Dq null ,
+.Dq false ,
+and
+.Dq true .
+Atoms can be grouped together as key/value pairs in an
+.Dq object ,
+and as individual, ordered atoms, in an
+.Dq array .
+.Pp
+To create a new object, the
+.Fn mj_create
+is used.
+It can be deleted using the
+.Fn mj_delete
+function.
+.Pp
+Atoms, objects and arrays can be appended
+to arrays and objects using the
+.Fn mj_append
+function.
+.Pp
+Objects can be printed out
+by using the
+.Fn mj_snprint
+function.
+The size of a string of JSON text can be calculated
+using the
+.Fn mj_string_size
+function.
+A utility function
+.Fn mj_asprint
+is provided which will allocate space dynamically,
+using
+.Xr calloc 3 ,
+and the JSON serialised text is copied into it.
+This memory can later be de-allocated using
+.Xr free 3 .
+.Pp
+The
+.Fa type
+argument given to the
+.Fn mj_create ,
+.Fn mj_append and
+.Fn mj_append_field
+functions is taken from a list of
+.Dq false
+.Dq true
+.Dq null
+.Dq number
+.Dq integer
+.Dq string
+.Dq array
+and
+.Dq object
+types.
+An integer differs from a number in that it cannot take on
+any floating point values.
+It is implemented internally using a signed 64-bit integer type.
+This restriction of values for an integer type may be removed at a later date.
+.Pp
+Within a JSON object, the key values can be iterated over using an integer
+index to access the individual
+JSON objects.
+The index can also be found using the
+.Fn mj_object_index
+function, and the object using
+the
+.Fn mj_object_find
+function.
+.Pp
+The way objects arrays are implemented in
+.Nm
+is by using varying-sized arrays internally.
+Objects have the field name as the even entry in this internal array,
+with the value being the odd entry.
+Arrays are implemented as a simple array.
+Thus, to find an object in an array using
+.Fn mj_object_find ,
+a value of 1 should be used as the
+increment value.
+This means that every entry in the internal array will be examined,
+and the first match after the starting point will be returned.
+For objects, an incremental value of 2 should be used,
+and an even start value should be specified.
+.Sh SEE ALSO
+.Xr calloc 3 ,
+.Xr free 3
+.Rs
+.%U http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf
+.Re
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Nx 6.0 .
+.Sh AUTHOR
+.An Alistair Crooks Aq a...@netbsd.org
+wrote this implementation and manual page.
Index: src/crypto/external/bsd/netpgp/dist/src/libmj/mj.c
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libmj/mj.c:1.1
--- /dev/null	Sat Aug  7 04:13:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/libmj/mj.c	Sat Aug  7 04:13:57 2010
@@ -0,0 +1,521 @@
+/*-
+ * Copyright (c) 2010 Alistair Crooks <a...@netbsd.org>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ */
+#include <sys/types.h>
+
+#include <inttypes.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mj.h"
+#include "defs.h"
+
+/* save 'n' chars of 's' in malloc'd memory */
+static char *
+strnsave(const char *s, int n, unsigned esc)
+{
+	char	*newc;
+	char	*cp;
+	int	 i;
+
+	if (n < 0) {
+		n = strlen(s);
+	}
+	NEWARRAY(char, cp, (n * 2) + 1, "strnsave", return NULL);
+	if (esc) {
+		newc = cp;
+		for (i = 0 ; i < n ; i++) {
+			if (*s == '\\') {
+				*newc++ = *s++;
+			} else if (*s == '"') {
+				*newc++ = '\\';
+			}
+			*newc++ = *s++;
+		}
+		*newc = 0x0;
+	} else {
+		(void) memcpy(cp, s, (unsigned)n);
+		cp[n] = 0x0;
+	}
+	return cp;
+}
+
+/* look in an object for the item */
+static int
+findentry(mj_t *atom, const char *name, const unsigned from, const unsigned incr)
+{
+	unsigned	i;
+
+	for (i = from ; i < atom->c ; i += incr) {
+		if (strcmp(name, atom->value.v[i].value.s) == 0) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+/* create a real number */
+static void
+create_number(mj_t *atom, double d)
+{
+	char	number[128];
+
+	atom->type = MJ_NUMBER;
+	atom->c = snprintf(number, sizeof(number), "%g", d);
+	atom->value.s = strnsave(number, (int)atom->c, 0);
+}
+
+/* create an integer */
+static void
+create_integer(mj_t *atom, int64_t i)
+{
+	char	number[128];
+
+	atom->type = MJ_NUMBER;
+	atom->c = snprintf(number, sizeof(number), "%" PRIi64, i);
+	atom->value.s = strnsave(number, (int)atom->c, 0);
+}
+
+/* create a string */
+static void
+create_string(mj_t *atom, const char *s)
+{
+	atom->type = MJ_STRING;
+	atom->value.s = strnsave(s, -1, 1);
+	atom->c = strlen(atom->value.s);
+}
+
+#define MJ_OPEN_BRACKET		(MJ_OBJECT + 1)		/* 8 */
+#define MJ_CLOSE_BRACKET	(MJ_OPEN_BRACKET + 1)	/* 9 */
+#define MJ_OPEN_BRACE		(MJ_CLOSE_BRACKET + 1)	/* 10 */
+#define MJ_CLOSE_BRACE		(MJ_OPEN_BRACE + 1)	/* 11 */
+#define MJ_COLON		(MJ_CLOSE_BRACE + 1)	/* 12 */
+#define MJ_COMMA		(MJ_COLON + 1)		/* 13 */
+
+/* return the token type, and start and finish locations in string */
+static int
+gettok(const char *s, int *from, int *to, int *tok)
+{
+	static regex_t	tokregex;
+	regmatch_t	matches[15];
+	static int	compiled;
+
+	if (!compiled) {
+		compiled = 1;
+		(void) regcomp(&tokregex,
+			"[ \t\r\n]*(([+-]?[0-9]{1,21}(\\.[0-9]*)?([eE][-+][0-9]+)?)|"
+			"(\"([^\"]|\\\\.)*\")|(null)|(false)|(true)|([][{}:,]))",
+			REG_EXTENDED);
+	}
+	if (regexec(&tokregex, &s[*from = *to], 15, matches, 0) != 0) {
+		return *tok = -1;
+	}
+	*to = *from + (int)(matches[1].rm_eo);
+	*tok = (matches[2].rm_so >= 0) ? MJ_NUMBER :
+		(matches[5].rm_so >= 0) ? MJ_STRING :
+		(matches[7].rm_so >= 0) ? MJ_NULL :
+		(matches[8].rm_so >= 0) ? MJ_FALSE :
+		(matches[9].rm_so >= 0) ? MJ_TRUE :
+		(matches[10].rm_so < 0) ? -1 :
+			(s[*from + (int)(matches[10].rm_so)] == '[') ? MJ_OPEN_BRACKET :
+			(s[*from + (int)(matches[10].rm_so)] == ']') ? MJ_CLOSE_BRACKET :
+			(s[*from + (int)(matches[10].rm_so)] == '{') ? MJ_OPEN_BRACE :
+			(s[*from + (int)(matches[10].rm_so)] == '}') ? MJ_CLOSE_BRACE :
+			(s[*from + (int)(matches[10].rm_so)] == ':') ? MJ_COLON :
+				MJ_COMMA;
+	*from += (int)(matches[1].rm_so);
+	return *tok;
+}
+
+/***************************************************************************/
+
+/* return the number of entries in the array */
+int
+mj_arraycount(mj_t *atom)
+{
+	return atom->c;
+}
+
+/* create a new JSON node */
+int
+mj_create(mj_t *atom, const char *type, ...)
+{
+	va_list	 args;
+
+	if (strcmp(type, "false") == 0) {
+		atom->type = MJ_FALSE;
+		atom->c = 0;
+	} else if (strcmp(type, "true") == 0) {
+		atom->type = MJ_TRUE;
+		atom->c = 1;
+	} else if (strcmp(type, "null") == 0) {
+		atom->type = MJ_NULL;
+	} else if (strcmp(type, "number") == 0) {
+		va_start(args, type);
+		create_number(atom, (double)va_arg(args, double));
+		va_end(args);
+	} else if (strcmp(type, "integer") == 0) {
+		va_start(args, type);
+		create_integer(atom, (int64_t)va_arg(args, int64_t));
+		va_end(args);
+	} else if (strcmp(type, "string") == 0) {
+		va_start(args, type);
+		create_string(atom, (char *)va_arg(args, char *));
+		va_end(args);
+	} else if (strcmp(type, "array") == 0) {
+		atom->type = MJ_ARRAY;
+	} else if (strcmp(type, "object") == 0) {
+		atom->type = MJ_OBJECT;
+	} else {
+		(void) fprintf(stderr, "weird type '%s'\n", type);
+		return 0;
+	}
+	return 1;
+}
+
+/* put a JSON tree into a text string */
+int
+mj_snprint(char *buf, size_t size, mj_t *atom)
+{
+	unsigned	i;
+	int		cc;
+
+	switch(atom->type) {
+	case MJ_NULL:
+		return snprintf(buf, size, "null");
+	case MJ_FALSE:
+		return snprintf(buf, size, "false");
+	case MJ_TRUE:
+		return snprintf(buf, size, "true");
+	case MJ_NUMBER:
+		return snprintf(buf, size, "%s", atom->value.s);
+	case MJ_STRING:
+		return snprintf(buf, size, "\"%s\"", atom->value.s);
+	case MJ_ARRAY:
+		cc = snprintf(buf, size, "[ ");
+		for (i = 0 ; i < atom->c ; i++) {
+			cc += mj_snprint(&buf[cc], size - cc, &atom->value.v[i]);
+			if (i < atom->c - 1) {
+				cc += snprintf(&buf[cc], size - cc, ", ");
+			}
+		}
+		return cc + snprintf(&buf[cc], size - cc, "]\n");
+	case MJ_OBJECT:
+		cc = snprintf(buf, size, "{ ");
+		for (i = 0 ; i < atom->c ; i += 2) {
+			cc += mj_snprint(&buf[cc], size - cc, &atom->value.v[i]);
+			cc += snprintf(&buf[cc], size - cc, ":");
+			cc += mj_snprint(&buf[cc], size - cc, &atom->value.v[i + 1]);
+			if (i + 1 < atom->c - 1) {
+				cc += snprintf(&buf[cc], size - cc, ", ");
+			}
+		}
+		return cc + snprintf(&buf[cc], size - cc, "}\n");
+	default:
+		(void) fprintf(stderr, "mj_snprint: weird type %d\n", atom->type);
+		return 0;
+	}
+}
+
+/* allocate and print the atom */
+int
+mj_asprint(char **buf, mj_t *atom)
+{
+	int	 size;
+
+	size = mj_string_size(atom);
+	if ((*buf = calloc(1, (unsigned)(size + 1))) == NULL) {
+		return -1;
+	}
+	(void) mj_snprint(*buf, (unsigned)(size + 1), atom);
+	return size + 1;
+}
+
+/* read into a JSON tree from a string */
+int
+mj_parse(mj_t *atom, const char *s, int *from, int *to, int *tok)
+{
+	int	i;
+
+	switch(atom->type = *tok = gettok(s, from, to, tok)) {
+	case MJ_NUMBER:
+		atom->value.s = strnsave(&s[*from], *to - *from, 1);
+		atom->c = atom->size = strlen(atom->value.s);
+		return gettok(s, from, to, tok);
+	case MJ_STRING:
+		atom->value.s = strnsave(&s[*from + 1], *to - *from - 2, 1);
+		atom->c = atom->size = strlen(atom->value.s);
+		return gettok(s, from, to, tok);
+	case MJ_NULL:
+	case MJ_FALSE:
+	case MJ_TRUE:
+		atom->c = (unsigned)to;
+		return gettok(s, from, to, tok);
+	case MJ_OPEN_BRACKET:
+		mj_create(atom, "array");
+		ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0);
+		while (mj_parse(&atom->value.v[atom->c++], s, from, to, tok) >= 0 && *tok != MJ_CLOSE_BRACKET) {
+			if (*tok != MJ_COMMA) {
+				(void) fprintf(stderr, "1. expected comma (got %d) at '%s'\n", *tok, &s[*from]);
+				break;
+			}
+			ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0);
+		}
+		return gettok(s, from, to, tok);
+	case MJ_OPEN_BRACE:
+		mj_create(atom, "object");
+		ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0);
+		for (i = 0 ; mj_parse(&atom->value.v[atom->c++], s, from, to, tok) >= 0 && *tok != MJ_CLOSE_BRACE ; i++) {
+			if (((i % 2) == 0 && *tok != MJ_COLON) || ((i % 2) == 1 && *tok != MJ_COMMA)) {
+				(void) fprintf(stderr, "2. expected comma (got %d) at '%s'\n", *tok, &s[*from]);
+				break;
+			}
+			ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0);
+		}
+		return gettok(s, from, to, tok);
+	default:
+		return *tok;
+	}
+}
+
+/* return the index of the item which corresponds to the name in the array */
+int
+mj_object_find(mj_t *atom, const char *name, const unsigned from, const unsigned incr)
+{
+	return findentry(atom, name, from, incr);
+}
+
+/* find an atom in a composite mj JSON node */
+mj_t *
+mj_get_atom(mj_t *atom, ...)
+{
+	unsigned	 i;
+	va_list		 args;
+	char		*name;
+	int		 n;
+
+	switch(atom->type) {
+	case MJ_ARRAY:
+		va_start(args, atom);
+		i = va_arg(args, int);
+		va_end(args);
+		return (i < atom->c) ? &atom->value.v[i] : NULL;
+	case MJ_OBJECT:
+		va_start(args, atom);
+		name = va_arg(args, char *);
+		va_end(args);
+		return ((n = findentry(atom, name, 0, 2)) >= 0) ? &atom->value.v[n + 1] : NULL;
+	default:
+		return NULL;
+	}
+}
+
+/* perform a deep copy on an mj JSON atom */
+int
+mj_deepcopy(mj_t *dst, mj_t *src)
+{
+	unsigned	i;
+
+	switch(src->type) {
+	case MJ_FALSE:
+	case MJ_TRUE:
+	case MJ_NULL:
+		(void) memcpy(dst, src, sizeof(*dst));
+		return 1;
+	case MJ_STRING:
+	case MJ_NUMBER:
+		(void) memcpy(dst, src, sizeof(*dst));
+		dst->value.s = strnsave(src->value.s, -1, 0);
+		dst->c = dst->size = strlen(dst->value.s);
+		return 1;
+	case MJ_ARRAY:
+	case MJ_OBJECT:
+		(void) memcpy(dst, src, sizeof(*dst));
+		NEWARRAY(mj_t, dst->value.v, dst->size, "mj_deepcopy()", return 0);
+		for (i = 0 ; i < src->c ; i++) {
+			if (!mj_deepcopy(&dst->value.v[i], &src->value.v[i])) {
+				return 0;
+			}
+		}
+		return 1;
+	default:
+		(void) fprintf(stderr, "weird type '%d'\n", src->type);
+		return 0;
+	}
+}
+
+/* do a deep delete on the object */
+void
+mj_delete(mj_t *atom)
+{
+	unsigned	i;
+
+	switch(atom->type) {
+	case MJ_STRING:
+	case MJ_NUMBER:
+		free(atom->value.s);
+		break;
+	case MJ_ARRAY:
+	case MJ_OBJECT:
+		for (i = 0 ; i < atom->c ; i++) {
+			mj_delete(&atom->value.v[i]);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+/* return the string size needed for the textual output of the JSON node */
+int
+mj_string_size(mj_t *atom)
+{
+	unsigned	i;
+	int		cc;
+
+	switch(atom->type) {
+	case MJ_NULL:
+	case MJ_TRUE:
+		return 4;
+	case MJ_FALSE:
+		return 5;
+	case MJ_NUMBER:
+		return atom->c;
+	case MJ_STRING:
+		return atom->c + 2;
+	case MJ_ARRAY:
+		for (cc = 2, i = 0 ; i < atom->c ; i++) {
+			cc += mj_string_size(&atom->value.v[i]);
+			if (i < atom->c - 1) {
+				cc += 2;
+			}
+		}
+		return cc + 1 + 1;
+	case MJ_OBJECT:
+		for (cc = 2, i = 0 ; i < atom->c ; i += 2) {
+			cc += mj_string_size(&atom->value.v[i]) + 1 + mj_string_size(&atom->value.v[i + 1]);
+			if (i + 1 < atom->c - 1) {
+				cc += 2;
+			}
+		}
+		return cc + 1 + 1;
+	default:
+		(void) fprintf(stderr, "mj_string_size: weird type %d\n", atom->type);
+		return 0;
+	}
+}
+
+/* create a new atom, and append it to the array or object */
+int
+mj_append(mj_t *atom, const char *type, ...)
+{
+	va_list	 args;
+
+	if (atom->type != MJ_ARRAY && atom->type != MJ_OBJECT) {
+		return 0;
+	}
+	ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_append()", return 0);
+	va_start(args, type);
+	if (strcmp(type, "string") == 0) {
+		create_string(&atom->value.v[atom->c++], (char *)va_arg(args, char *));
+	} else if (strcmp(type, "integer") == 0) {
+		create_integer(&atom->value.v[atom->c++], (int64_t)va_arg(args, int64_t));
+	} else if (strcmp(type, "object") == 0 || strcmp(type, "array") == 0) {
+		mj_deepcopy(&atom->value.v[atom->c++], (mj_t *)va_arg(args, mj_t *));
+	} else {
+		(void) fprintf(stderr, "mj_append: weird type '%s'\n", type);
+	}
+	va_end(args);
+	return 1;
+}
+
+/* append a field to an object */
+int
+mj_append_field(mj_t *atom, const char *name, const char *type, ...)
+{
+	va_list	 args;
+
+	if (atom->type != MJ_OBJECT) {
+		return 0;
+	}
+	mj_append(atom, "string", name);
+	ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_append_field()", return 0);
+	va_start(args, type);
+	if (strcmp(type, "string") == 0) {
+		create_string(&atom->value.v[atom->c++], (char *)va_arg(args, char *));
+	} else if (strcmp(type, "integer") == 0) {
+		create_integer(&atom->value.v[atom->c++], (int64_t)va_arg(args, int64_t));
+	} else if (strcmp(type, "object") == 0 || strcmp(type, "array") == 0) {
+		mj_deepcopy(&atom->value.v[atom->c++], (mj_t *)va_arg(args, mj_t *));
+	} else {
+		(void) fprintf(stderr, "mj_append_field: weird type '%s'\n", type);
+	}
+	va_end(args);
+	return 1;
+}
+
+int
+mj_lint(mj_t *obj)
+{
+	unsigned	i;
+	int		ret;
+
+	switch(obj->type) {
+	case MJ_NULL:
+	case MJ_FALSE:
+	case MJ_TRUE:
+		if (obj->value.s != NULL) {
+			(void) fprintf(stderr, "null/false/true: non zero string\n");
+			return 0;
+		}
+		return 1;
+	case MJ_NUMBER:
+	case MJ_STRING:
+		if (obj->c > obj->size) {
+			(void) fprintf(stderr, "string/number lint c (%u) > size (%u)\n", obj->c, obj->size);
+			return 0;
+		}
+		return 1;
+	case MJ_ARRAY:
+	case MJ_OBJECT:
+		if (obj->c > obj->size) {
+			(void) fprintf(stderr, "array/object lint c (%u) > size (%u)\n", obj->c, obj->size);
+			return 0;
+		}
+		for (ret = 1, i = 0 ; i < obj->c ; i++) {
+			if (!mj_lint(&obj->value.v[i])) {
+				(void) fprintf(stderr, "array/object lint found at %d of %p\n", i, obj);
+				ret = 0;
+			}
+		}
+		return ret;
+	default:
+		(void) fprintf(stderr, "problem type %d in %p\n", obj->type, obj);
+		return 0;
+	}
+}
Index: src/crypto/external/bsd/netpgp/dist/src/libmj/mj.h
diff -u /dev/null src/crypto/external/bsd/netpgp/dist/src/libmj/mj.h:1.1
--- /dev/null	Sat Aug  7 04:13:57 2010
+++ src/crypto/external/bsd/netpgp/dist/src/libmj/mj.h	Sat Aug  7 04:13:57 2010
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2010 Alistair Crooks <a...@netbsd.org>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ */
+#ifndef MJ_H_
+#define MJ_H_	20100718
+
+enum {
+	MJ_NULL		= 1,
+	MJ_FALSE	= 2,
+	MJ_TRUE		= 3,
+	MJ_NUMBER	= 4,
+	MJ_STRING	= 5,
+	MJ_ARRAY	= 6,
+	MJ_OBJECT	= 7
+};
+
+/* a minimalist JSON node */
+typedef struct mj_t {
+	unsigned	type;		/* type of JSON node */
+	unsigned	c;		/* # of chars */
+	unsigned	size;		/* size of array */
+	union {
+		struct mj_t	*v;	/* sub-objects */
+		char		*s;	/* string value */
+	} value;
+} mj_t;
+
+/* creation and deletion */
+int mj_create(mj_t *, const char *, ...);
+int mj_parse(mj_t *, const char *, int *, int *, int *);
+int mj_append(mj_t *, const char *, ...);
+int mj_append_field(mj_t *, const char *, const char *, ...);
+int mj_deepcopy(mj_t *, mj_t *);
+void mj_delete(mj_t *);
+
+/* JSON object access */
+int mj_arraycount(mj_t *);
+int mj_object_find(mj_t *, const char *, const unsigned, const unsigned);
+mj_t *mj_get_atom(mj_t *, ...);
+int mj_lint(mj_t *);
+
+/* textual output */
+int mj_snprint(char *, size_t, mj_t *);
+int mj_asprint(char **, mj_t *);
+int mj_string_size(mj_t *);
+
+#endif

Reply via email to