Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows to encode empty tables as arrays. #6

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@ notes
packages
tags
tests/utf8.dat
*.vcproj
*.sln
CMakeCache.txt
CMakeFiles/*
cjson.def
cjson.exp
*.dll*
cmake_install.cmake
8 changes: 7 additions & 1 deletion fpconv.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@

#include "fpconv.h"

#ifdef _MSC_VER
#define snprintf _snprintf
#endif

/* Lua CJSON assumes the locale is the same for all threads within a
* process and doesn't change after initialisation.
*
Expand Down Expand Up @@ -124,7 +128,7 @@ double fpconv_strtod(const char *nptr, char **endptr)
/* Duplicate number into buffer */
if (buflen >= FPCONV_G_FMT_BUFSIZE) {
/* Handle unusually large numbers */
buf = malloc(buflen + 1);
buf = (char *)malloc(buflen + 1);
if (!buf) {
fprintf(stderr, "Out of memory");
abort();
Expand Down Expand Up @@ -196,10 +200,12 @@ int fpconv_g_fmt(char *str, double num, int precision)
return len;
}

#ifndef USE_INTERNAL_FPCONV
void fpconv_init()
{
fpconv_update_locale();
}
#endif

/* vi:ai et sw=4 ts=4:
*/
4 changes: 4 additions & 0 deletions fpconv.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
* -1.7976931348623e+308 */
# define FPCONV_G_FMT_BUFSIZE 32

#ifdef _MSC_VER
#define inline
#endif

#ifdef USE_INTERNAL_FPCONV
static inline void fpconv_init()
{
Expand Down
62 changes: 62 additions & 0 deletions lua-cjson-git-1.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package = "lua-cjson"
version = "git-1"

description = {
summary = "A fast JSON encoding/parsing module",
detailed = [[
The Lua CJSON module provides JSON support for Lua. It features:
- Fast, standards compliant encoding/parsing routines
- Full support for JSON with UTF-8, including decoding surrogate pairs
- Optional run-time support for common exceptions to the JSON specification
(infinity, NaN,..)
- No dependencies on other libraries
]],
homepage = "http://www.kyne.com.au/~mark/software/lua-cjson.php",
license = "MIT"
}

source = {
url = "https://git.inconcert/lua-libraries/lua-cjson",
dir = "lua-cjson"
}

dependencies = {
"lua >= 5.1"
}

build = {
type = "builtin",
modules = {
cjson = {
defines = { "MULTIPLE_THREADS" },
sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" },
defines = {
-- LuaRocks does not support platform specific configuration for Solaris.
-- Uncomment the line below on Solaris platforms if required.
-- "USE_INTERNAL_ISINF"
}
}
},
install = {
lua = {
["cjson.util"] = "lua/cjson/util.lua"
},
bin = {
json2lua = "lua/json2lua.lua",
lua2json = "lua/lua2json.lua"
}
},
-- Override default build options (per platform)
platforms = {
win32 = { modules = { cjson = { defines = {
"MULTIPLE_THREADS", "DISABLE_INVALID_NUMBERS"
} } } }
},
copy_directories = { "tests" }
}

-- Para compilar lua-cjson en windows:
-- luarocks make CFLAGS="/TP /MD /O2 -DMULTIPLE_THREADS -DUSE_INTERNAL_FPCONV"


-- vi:ai et sw=4 ts=4:
43 changes: 37 additions & 6 deletions lua_cjson.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@
#include <string.h>
#include <math.h>
#include <limits.h>

#ifdef __cplusplus
#include <lua.hpp>
#else
#include <lua.h>
#endif

#include <lauxlib.h>

#include "strbuf.h"
Expand All @@ -59,6 +65,14 @@
#define isinf(x) (!isnan(x) && isnan((x) - (x)))
#endif

#ifdef _MSC_VER
#define snprintf _snprintf
#define strncasecmp _strnicmp
#include <float.h>
#define isnan(x) _isnan(x)
#define isinf(x) (!isnan(x) && isnan((x) - (x)))
#endif

#define DEFAULT_SPARSE_CONVERT 0
#define DEFAULT_SPARSE_RATIO 2
#define DEFAULT_SPARSE_SAFE 10
Expand All @@ -68,6 +82,7 @@
#define DEFAULT_DECODE_INVALID_NUMBERS 1
#define DEFAULT_ENCODE_KEEP_BUFFER 1
#define DEFAULT_ENCODE_NUMBER_PRECISION 14
#define DEFAULT_ENCODE_EMPTY_TABLE_AS_ARRAY 0 /* 0 table, 1 array */

#ifdef DISABLE_INVALID_NUMBERS
#undef DEFAULT_DECODE_INVALID_NUMBERS
Expand Down Expand Up @@ -124,6 +139,7 @@ typedef struct {
int encode_invalid_numbers; /* 2 => Encode as "null" */
int encode_number_precision;
int encode_keep_buffer;
int encode_empty_table_as_array;

int decode_invalid_numbers;
int decode_max_depth;
Expand Down Expand Up @@ -193,7 +209,7 @@ static json_config_t *json_fetch_config(lua_State *l)
{
json_config_t *cfg;

cfg = lua_touserdata(l, lua_upvalueindex(1));
cfg = (json_config_t *)lua_touserdata(l, lua_upvalueindex(1));
if (!cfg)
luaL_error(l, "BUG: Unable to fetch CJSON configuration");

Expand Down Expand Up @@ -321,6 +337,13 @@ static int json_cfg_encode_keep_buffer(lua_State *l)
return 1;
}

/* Configures whether empty tables will be encoded as an object or an array */
static int json_cfg_encode_empty_tables_as_array(lua_State *l)
{
json_config_t *cfg = json_arg_init(l, 1);
return json_enum_option(l, 1, &cfg->encode_empty_table_as_array, NULL, 1);
}

#if defined(DISABLE_INVALID_NUMBERS) && !defined(USE_INTERNAL_FPCONV)
void json_verify_invalid_number_setting(lua_State *l, int *setting)
{
Expand Down Expand Up @@ -360,7 +383,7 @@ static int json_destroy_config(lua_State *l)
{
json_config_t *cfg;

cfg = lua_touserdata(l, 1);
cfg = (json_config_t *)lua_touserdata(l, 1);
if (cfg)
strbuf_free(&cfg->encode_buf);
cfg = NULL;
Expand All @@ -373,7 +396,7 @@ static void json_create_config(lua_State *l)
json_config_t *cfg;
int i;

cfg = lua_newuserdata(l, sizeof(*cfg));
cfg = (json_config_t *)lua_newuserdata(l, sizeof(*cfg));

/* Create GC method to clean up strbuf */
lua_newtable(l);
Expand All @@ -390,6 +413,7 @@ static void json_create_config(lua_State *l)
cfg->decode_invalid_numbers = DEFAULT_DECODE_INVALID_NUMBERS;
cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER;
cfg->encode_number_precision = DEFAULT_ENCODE_NUMBER_PRECISION;
cfg->encode_empty_table_as_array = DEFAULT_ENCODE_EMPTY_TABLE_AS_ARRAY;

#if DEFAULT_ENCODE_KEEP_BUFFER > 0
strbuf_init(&cfg->encode_buf, 0);
Expand Down Expand Up @@ -685,7 +709,7 @@ static void json_append_data(lua_State *l, json_config_t *cfg,
current_depth++;
json_check_encode_depth(l, cfg, current_depth, json);
len = lua_array_length(l, cfg, json);
if (len > 0)
if (len > 0 || (cfg->encode_empty_table_as_array && len == 0))
json_append_array(l, cfg, current_depth, json, len);
else
json_append_object(l, cfg, current_depth, json);
Expand Down Expand Up @@ -1359,6 +1383,7 @@ static int lua_cjson_new(lua_State *l)
{ "encode_keep_buffer", json_cfg_encode_keep_buffer },
{ "encode_invalid_numbers", json_cfg_encode_invalid_numbers },
{ "decode_invalid_numbers", json_cfg_decode_invalid_numbers },
{ "encode_empty_table_as_array", json_cfg_encode_empty_tables_as_array },
{ "new", lua_cjson_new },
{ NULL, NULL }
};
Expand Down Expand Up @@ -1407,7 +1432,13 @@ static int lua_cjson_safe_new(lua_State *l)
return 1;
}

int luaopen_cjson(lua_State *l)
#ifdef _MSC_VER
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API
#endif

int EXPORT_API luaopen_cjson(lua_State *l)
{
lua_cjson_new(l);

Expand All @@ -1421,7 +1452,7 @@ int luaopen_cjson(lua_State *l)
return 1;
}

int luaopen_cjson_safe(lua_State *l)
int EXPORT_API luaopen_cjson_safe(lua_State *l)
{
lua_cjson_safe_new(l);

Expand Down
12 changes: 6 additions & 6 deletions strbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void strbuf_init(strbuf_t *s, int len)
s->reallocs = 0;
s->debug = 0;

s->buf = malloc(size);
s->buf = (char *)malloc(size);
if (!s->buf)
die("Out of memory");

Expand All @@ -69,7 +69,7 @@ strbuf_t *strbuf_new(int len)
{
strbuf_t *s;

s = malloc(sizeof(strbuf_t));
s = (strbuf_t *)malloc(sizeof(strbuf_t));
if (!s)
die("Out of memory");

Expand Down Expand Up @@ -173,7 +173,7 @@ void strbuf_resize(strbuf_t *s, int len)
}

s->size = newsize;
s->buf = realloc(s->buf, s->size);
s->buf = (char *)realloc(s->buf, s->size);
if (!s->buf)
die("Out of memory");
s->reallocs++;
Expand Down Expand Up @@ -221,12 +221,12 @@ void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...)
void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)
{
va_list arg;
int fmt_len, try;
int fmt_len, attempt;
int empty_len;

/* If the first attempt to append fails, resize the buffer appropriately
* and try again */
for (try = 0; ; try++) {
for (attempt = 0; ; attempt++) {
va_start(arg, fmt);
/* Append the new formatted string */
/* fmt_len is the length of the string required, excluding the
Expand All @@ -238,7 +238,7 @@ void strbuf_append_fmt_retry(strbuf_t *s, const char *fmt, ...)

if (fmt_len <= empty_len)
break; /* SUCCESS */
if (try > 0)
if (attempt > 0)
die("BUG: length of formatted string changed");

strbuf_resize(s, s->length + fmt_len);
Expand Down
4 changes: 4 additions & 0 deletions strbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ typedef struct {
#define STRBUF_DEFAULT_INCREMENT -2
#endif

#ifdef _MSC_VER
#define inline
#endif

/* Initialise */
extern strbuf_t *strbuf_new(int len);
extern void strbuf_init(strbuf_t *s, int len);
Expand Down