configure.ac | 2 debian/changelog | 10 debian/libgles2.symbols | 112 debian/watch | 3 src/EGL/libeglmapping.c | 2 src/EGL/libeglvendor.c | 1 src/GLdispatch/vnd-glapi/entry_aarch64_tsd.c | 31 src/GLdispatch/vnd-glapi/entry_armv7_tsd.c | 29 src/GLdispatch/vnd-glapi/entry_ppc64le_tls.c | 20 src/GLdispatch/vnd-glapi/entry_ppc64le_tsd.c | 91 src/GLdispatch/vnd-glapi/entry_x86_64_tls.c | 35 src/GLdispatch/vnd-glapi/entry_x86_64_tsd.c | 19 src/GLdispatch/vnd-glapi/entry_x86_tls.c | 27 src/GLdispatch/vnd-glapi/entry_x86_tsd.c | 19 src/generate/genCommon.py | 2 src/util/Makefile.am | 1 src/util/cJSON.c | 3209 +++++++++++++++++++++------ src/util/cJSON.h | 260 +- src/util/cJSON/LICENSE | 2 src/util/cJSON/README | 247 -- src/util/cJSON/test.c | 162 - src/util/cJSON/tests/test1 | 22 src/util/cJSON/tests/test2 | 11 src/util/cJSON/tests/test3 | 26 src/util/cJSON/tests/test4 | 88 src/util/cJSON/tests/test5 | 27 src/util/glvnd_genentry.c | 14 27 files changed, 3049 insertions(+), 1423 deletions(-)
New commits: commit 2068eb813498deaaa85f8934e8f9b80d2a5780c3 Author: Timo Aaltonen <[email protected]> Date: Thu Nov 9 12:14:34 2017 +0200 release to unstable diff --git a/debian/changelog b/debian/changelog index e370b66..207a54a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -libglvnd (1.0.0-1) UNRELEASED; urgency=high +libglvnd (1.0.0-1) unstable; urgency=high [ Andreas Boll ] * Add versioned libglvnd0 dependencies (Workaround for #878851). @@ -10,7 +10,7 @@ libglvnd (1.0.0-1) UNRELEASED; urgency=high * Add a watch file for uscan. * libgles2.symbols: Updated. - -- Andreas Boll <[email protected]> Fri, 20 Oct 2017 11:03:03 +0200 + -- Timo Aaltonen <[email protected]> Thu, 09 Nov 2017 12:14:14 +0200 libglvnd (0.2.999+git20170802-5) unstable; urgency=medium commit 16242887df1433ea1e659f864e440f08f7006c47 Author: Timo Aaltonen <[email protected]> Date: Thu Nov 9 12:14:08 2017 +0200 libgles2.symbols: Updated. diff --git a/debian/changelog b/debian/changelog index 18e2520..e370b66 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,7 @@ libglvnd (1.0.0-1) UNRELEASED; urgency=high [ Timo Aaltonen ] * New upstream release. * Add a watch file for uscan. + * libgles2.symbols: Updated. -- Andreas Boll <[email protected]> Fri, 20 Oct 2017 11:03:03 +0200 diff --git a/debian/libgles2.symbols b/debian/libgles2.symbols index 25df8c7..bcaab60 100644 --- a/debian/libgles2.symbols +++ b/debian/libgles2.symbols @@ -1,4 +1,5 @@ libGLESv2.so.2 libgles2 #MINVER# + glActiveShaderProgram@Base 1.0.0 glActiveTexture@Base 0 glAttachShader@Base 0 glBeginQuery@Base 0 @@ -8,16 +9,24 @@ libGLESv2.so.2 libgles2 #MINVER# glBindBufferBase@Base 0 glBindBufferRange@Base 0 glBindFramebuffer@Base 0 + glBindImageTexture@Base 1.0.0 + glBindProgramPipeline@Base 1.0.0 glBindRenderbuffer@Base 0 glBindSampler@Base 0 glBindTexture@Base 0 glBindTransformFeedback@Base 0 glBindVertexArray@Base 0 + glBindVertexBuffer@Base 1.0.0 + glBlendBarrier@Base 1.0.0 glBlendColor@Base 0 glBlendEquation@Base 0 glBlendEquationSeparate@Base 0 + glBlendEquationSeparatei@Base 1.0.0 + glBlendEquationi@Base 1.0.0 glBlendFunc@Base 0 glBlendFuncSeparate@Base 0 + glBlendFuncSeparatei@Base 1.0.0 + glBlendFunci@Base 1.0.0 glBlitFramebuffer@Base 0 glBufferData@Base 0 glBufferSubData@Base 0 @@ -32,21 +41,28 @@ libGLESv2.so.2 libgles2 #MINVER# glClearStencil@Base 0 glClientWaitSync@Base 0 glColorMask@Base 0 + glColorMaski@Base 1.0.0 glCompileShader@Base 0 glCompressedTexImage2D@Base 0 glCompressedTexImage3D@Base 0 glCompressedTexSubImage2D@Base 0 glCompressedTexSubImage3D@Base 0 glCopyBufferSubData@Base 0 + glCopyImageSubData@Base 1.0.0 glCopyTexImage2D@Base 0 glCopyTexSubImage2D@Base 0 glCopyTexSubImage3D@Base 0 glCreateProgram@Base 0 glCreateShader@Base 0 + glCreateShaderProgramv@Base 1.0.0 glCullFace@Base 0 + glDebugMessageCallback@Base 1.0.0 + glDebugMessageControl@Base 1.0.0 + glDebugMessageInsert@Base 1.0.0 glDeleteBuffers@Base 0 glDeleteFramebuffers@Base 0 glDeleteProgram@Base 0 + glDeleteProgramPipelines@Base 1.0.0 glDeleteQueries@Base 0 glDeleteRenderbuffers@Base 0 glDeleteSamplers@Base 0 @@ -61,13 +77,22 @@ libGLESv2.so.2 libgles2 #MINVER# glDetachShader@Base 0 glDisable@Base 0 glDisableVertexAttribArray@Base 0 + glDisablei@Base 1.0.0 + glDispatchCompute@Base 1.0.0 + glDispatchComputeIndirect@Base 1.0.0 glDrawArrays@Base 0 + glDrawArraysIndirect@Base 1.0.0 glDrawArraysInstanced@Base 0 glDrawBuffers@Base 0 glDrawElements@Base 0 + glDrawElementsBaseVertex@Base 1.0.0 + glDrawElementsIndirect@Base 1.0.0 glDrawElementsInstanced@Base 0 + glDrawElementsInstancedBaseVertex@Base 1.0.0 glDrawRangeElements@Base 0 + glDrawRangeElementsBaseVertex@Base 1.0.0 glEnable@Base 0 + glEnablei@Base 1.0.0 glEnableVertexAttribArray@Base 0 glEndQuery@Base 0 glEndTransformFeedback@Base 0 @@ -75,12 +100,15 @@ libGLESv2.so.2 libgles2 #MINVER# glFinish@Base 0 glFlush@Base 0 glFlushMappedBufferRange@Base 0 + glFramebufferParameteri@Base 1.0.0 glFramebufferRenderbuffer@Base 0 glFramebufferTexture2D@Base 0 + glFramebufferTexture@Base 1.0.0 glFramebufferTextureLayer@Base 0 glFrontFace@Base 0 glGenBuffers@Base 0 glGenFramebuffers@Base 0 + glGenProgramPipelines@Base 1.0.0 glGenQueries@Base 0 glGenRenderbuffers@Base 0 glGenSamplers@Base 0 @@ -95,25 +123,42 @@ libGLESv2.so.2 libgles2 #MINVER# glGetActiveUniformsiv@Base 0 glGetAttachedShaders@Base 0 glGetAttribLocation@Base 0 + glGetBooleani_v@Base 1.0.0 glGetBooleanv@Base 0 glGetBufferParameteri64v@Base 0 glGetBufferParameteriv@Base 0 glGetBufferPointerv@Base 0 + glGetDebugMessageLog@Base 1.0.0 glGetError@Base 0 glGetFloatv@Base 0 glGetFragDataLocation@Base 0 glGetFramebufferAttachmentParameteriv@Base 0 + glGetFramebufferParameteriv@Base 1.0.0 + glGetGraphicsResetStatus@Base 1.0.0 glGetInteger64i_v@Base 0 glGetInteger64v@Base 0 glGetIntegeri_v@Base 0 glGetIntegerv@Base 0 glGetInternalformativ@Base 0 + glGetMultisamplefv@Base 1.0.0 + glGetObjectLabel@Base 1.0.0 + glGetObjectPtrLabel@Base 1.0.0 + glGetPointerv@Base 1.0.0 glGetProgramBinary@Base 0 glGetProgramInfoLog@Base 0 + glGetProgramInterfaceiv@Base 1.0.0 + glGetProgramPipelineInfoLog@Base 1.0.0 + glGetProgramPipelineiv@Base 1.0.0 + glGetProgramResourceIndex@Base 1.0.0 + glGetProgramResourceLocation@Base 1.0.0 + glGetProgramResourceName@Base 1.0.0 + glGetProgramResourceiv@Base 1.0.0 glGetProgramiv@Base 0 glGetQueryObjectuiv@Base 0 glGetQueryiv@Base 0 glGetRenderbufferParameteriv@Base 0 + glGetSamplerParameterIiv@Base 1.0.0 + glGetSamplerParameterIuiv@Base 1.0.0 glGetSamplerParameterfv@Base 0 glGetSamplerParameteriv@Base 0 glGetShaderInfoLog@Base 0 @@ -123,6 +168,10 @@ libGLESv2.so.2 libgles2 #MINVER# glGetString@Base 0 glGetStringi@Base 0 glGetSynciv@Base 0 + glGetTexLevelParameterfv@Base 1.0.0 + glGetTexLevelParameteriv@Base 1.0.0 + glGetTexParameterIiv@Base 1.0.0 + glGetTexParameterIuiv@Base 1.0.0 glGetTexParameterfv@Base 0 glGetTexParameteriv@Base 0 glGetTransformFeedbackVarying@Base 0 @@ -137,13 +186,18 @@ libGLESv2.so.2 libgles2 #MINVER# glGetVertexAttribPointerv@Base 0 glGetVertexAttribfv@Base 0 glGetVertexAttribiv@Base 0 + glGetnUniformfv@Base 1.0.0 + glGetnUniformiv@Base 1.0.0 + glGetnUniformuiv@Base 1.0.0 glHint@Base 0 glInvalidateFramebuffer@Base 0 glInvalidateSubFramebuffer@Base 0 glIsBuffer@Base 0 glIsEnabled@Base 0 + glIsEnabledi@Base 1.0.0 glIsFramebuffer@Base 0 glIsProgram@Base 0 + glIsProgramPipeline@Base 1.0.0 glIsQuery@Base 0 glIsRenderbuffer@Base 0 glIsSampler@Base 0 @@ -155,18 +209,64 @@ libGLESv2.so.2 libgles2 #MINVER# glLineWidth@Base 0 glLinkProgram@Base 0 glMapBufferRange@Base 0 + glMemoryBarrier@Base 1.0.0 + glMemoryBarrierByRegion@Base 1.0.0 + glMinSampleShading@Base 1.0.0 + glObjectLabel@Base 1.0.0 + glObjectPtrLabel@Base 1.0.0 + glPatchParameteri@Base 1.0.0 glPauseTransformFeedback@Base 0 glPixelStorei@Base 0 glPolygonOffset@Base 0 + glPopDebugGroup@Base 1.0.0 + glPrimitiveBoundingBox@Base 1.0.0 glProgramBinary@Base 0 glProgramParameteri@Base 0 + glProgramUniform1f@Base 1.0.0 + glProgramUniform1fv@Base 1.0.0 + glProgramUniform1i@Base 1.0.0 + glProgramUniform1iv@Base 1.0.0 + glProgramUniform1ui@Base 1.0.0 + glProgramUniform1uiv@Base 1.0.0 + glProgramUniform2f@Base 1.0.0 + glProgramUniform2fv@Base 1.0.0 + glProgramUniform2i@Base 1.0.0 + glProgramUniform2iv@Base 1.0.0 + glProgramUniform2ui@Base 1.0.0 + glProgramUniform2uiv@Base 1.0.0 + glProgramUniform3f@Base 1.0.0 + glProgramUniform3fv@Base 1.0.0 + glProgramUniform3i@Base 1.0.0 + glProgramUniform3iv@Base 1.0.0 + glProgramUniform3ui@Base 1.0.0 + glProgramUniform3uiv@Base 1.0.0 + glProgramUniform4f@Base 1.0.0 + glProgramUniform4fv@Base 1.0.0 + glProgramUniform4i@Base 1.0.0 + glProgramUniform4iv@Base 1.0.0 + glProgramUniform4ui@Base 1.0.0 + glProgramUniform4uiv@Base 1.0.0 + glProgramUniformMatrix2fv@Base 1.0.0 + glProgramUniformMatrix2x3fv@Base 1.0.0 + glProgramUniformMatrix2x4fv@Base 1.0.0 + glProgramUniformMatrix3fv@Base 1.0.0 + glProgramUniformMatrix3x2fv@Base 1.0.0 + glProgramUniformMatrix3x4fv@Base 1.0.0 + glProgramUniformMatrix4fv@Base 1.0.0 + glProgramUniformMatrix4x2fv@Base 1.0.0 + glProgramUniformMatrix4x3fv@Base 1.0.0 + glPushDebugGroup@Base 1.0.0 glReadBuffer@Base 0 glReadPixels@Base 0 + glReadnPixels@Base 1.0.0 glReleaseShaderCompiler@Base 0 glRenderbufferStorage@Base 0 glRenderbufferStorageMultisample@Base 0 glResumeTransformFeedback@Base 0 glSampleCoverage@Base 0 + glSampleMaski@Base 1.0.0 + glSamplerParameterIiv@Base 1.0.0 + glSamplerParameterIuiv@Base 1.0.0 glSamplerParameterf@Base 0 glSamplerParameterfv@Base 0 glSamplerParameteri@Base 0 @@ -180,14 +280,20 @@ libGLESv2.so.2 libgles2 #MINVER# glStencilMaskSeparate@Base 0 glStencilOp@Base 0 glStencilOpSeparate@Base 0 + glTexBuffer@Base 1.0.0 + glTexBufferRange@Base 1.0.0 glTexImage2D@Base 0 glTexImage3D@Base 0 + glTexParameterIiv@Base 1.0.0 + glTexParameterIuiv@Base 1.0.0 glTexParameterf@Base 0 glTexParameterfv@Base 0 glTexParameteri@Base 0 glTexParameteriv@Base 0 glTexStorage2D@Base 0 + glTexStorage2DMultisample@Base 1.0.0 glTexStorage3D@Base 0 + glTexStorage3DMultisample@Base 1.0.0 glTexSubImage2D@Base 0 glTexSubImage3D@Base 0 glTransformFeedbackVaryings@Base 0 @@ -227,7 +333,9 @@ libGLESv2.so.2 libgles2 #MINVER# glUniformMatrix4x3fv@Base 0 glUnmapBuffer@Base 0 glUseProgram@Base 0 + glUseProgramStages@Base 1.0.0 glValidateProgram@Base 0 + glValidateProgramPipeline@Base 1.0.0 glVertexAttrib1f@Base 0 glVertexAttrib1fv@Base 0 glVertexAttrib2f@Base 0 @@ -236,12 +344,16 @@ libGLESv2.so.2 libgles2 #MINVER# glVertexAttrib3fv@Base 0 glVertexAttrib4f@Base 0 glVertexAttrib4fv@Base 0 + glVertexAttribBinding@Base 1.0.0 glVertexAttribDivisor@Base 0 + glVertexAttribFormat@Base 1.0.0 glVertexAttribI4i@Base 0 glVertexAttribI4iv@Base 0 glVertexAttribI4ui@Base 0 glVertexAttribI4uiv@Base 0 + glVertexAttribIFormat@Base 1.0.0 glVertexAttribIPointer@Base 0 glVertexAttribPointer@Base 0 + glVertexBindingDivisor@Base 1.0.0 glViewport@Base 0 glWaitSync@Base 0 commit f7a4e545a6a4d6e49170fc11b4f85380132ec17e Author: Timo Aaltonen <[email protected]> Date: Thu Nov 9 11:36:41 2017 +0200 Add a watch file for uscan. diff --git a/debian/changelog b/debian/changelog index b13ff7e..18e2520 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,7 @@ libglvnd (1.0.0-1) UNRELEASED; urgency=high [ Timo Aaltonen ] * New upstream release. + * Add a watch file for uscan. -- Andreas Boll <[email protected]> Fri, 20 Oct 2017 11:03:03 +0200 diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..b303a95 --- /dev/null +++ b/debian/watch @@ -0,0 +1,3 @@ +version=4 +opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%libglvnd-$1.tar.gz%" \ +https://github.com/NVIDIA/libglvnd/tags (?:.*?/)?v?(\d[\d.]*)\.tar\.gz commit 1a4ec767c2083e1efa30d2d27eca3ca2292287e3 Author: Timo Aaltonen <[email protected]> Date: Thu Nov 9 11:36:13 2017 +0200 New upstream release. diff --git a/debian/changelog b/debian/changelog index 85c22a1..b13ff7e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ -libglvnd (0.2.999+git20170802-6) UNRELEASED; urgency=high +libglvnd (1.0.0-1) UNRELEASED; urgency=high + [ Andreas Boll ] * Add versioned libglvnd0 dependencies (Workaround for #878851). * Raise Priority to optional. * Bump standards version to 4.1.1. + [ Timo Aaltonen ] + * New upstream release. + -- Andreas Boll <[email protected]> Fri, 20 Oct 2017 11:03:03 +0200 libglvnd (0.2.999+git20170802-5) unstable; urgency=medium commit 005fd3a0c449f809d0128921da8ef6762fecffc9 Author: Kyle Brenneman <[email protected]> Date: Thu Nov 2 10:58:38 2017 -0600 Set package version to 1.0.0. Now that both the EGL and GLX interfaces are defined and stable, set the package version to 1.0.0. diff --git a/configure.ac b/configure.ac index 5443734..56018aa 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl configure.ac dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.63]) -AC_INIT([libglvnd], [0.2.999], [[email protected]]) +AC_INIT([libglvnd], [1.0.0], [[email protected]]) AC_CONFIG_SRCDIR([config.h.in]) AC_CONFIG_HEADERS([config.h]) commit e3ab0a24cf35f074ff74365e3feae162c4690c16 Author: Gabríel Arthúr Pétursson <[email protected]> Date: Sat Oct 7 01:14:38 2017 +0000 Cleanup winsys dispatch index list on EGL mapping teardown This fixes a memory leak reported by both Valgrind and LeakSanitizer when libEGL is dlopen()-ed and dlclose()-ed afterwards. diff --git a/src/EGL/libeglmapping.c b/src/EGL/libeglmapping.c index d420e88..c736172 100644 --- a/src/EGL/libeglmapping.c +++ b/src/EGL/libeglmapping.c @@ -259,6 +259,8 @@ void __eglMappingTeardown(EGLBoolean doReset) /* Tear down all hashtables used in this file */ LKDHASH_TEARDOWN(__EGLdisplayInfoHash, __eglDisplayInfoHash, NULL, NULL, EGL_FALSE); + + __glvndWinsysDispatchCleanup(); } } commit c2f81ca7ce08cf8eb09f4bf0cd08b86799234843 Author: Gabríel Arthúr Pétursson <[email protected]> Date: Fri Oct 6 22:39:20 2017 +0000 Fix memory leak in LoadVendorsFromConfigDir The individual entries allocated by scandir need to be freed too. diff --git a/src/EGL/libeglvendor.c b/src/EGL/libeglvendor.c index 88ee060..7b8d6e7 100644 --- a/src/EGL/libeglvendor.c +++ b/src/EGL/libeglvendor.c @@ -121,6 +121,7 @@ void LoadVendorsFromConfigDir(const char *dirName) } else { fprintf(stderr, "ERROR: Could not allocate vendor library path name\n"); } + free(entries[i]); } free(entries); commit 6198bd6ef68f71f60a228906a5ce4c874acf760d Author: Aaron Plattner <[email protected]> Date: Wed Sep 13 12:56:57 2017 -0700 Update cJSON to version 1.5.9 Downloaded from https://github.com/DaveGamble/cJSON/releases/tag/v1.5.9 diff --git a/src/util/cJSON.c b/src/util/cJSON.c index 2bec99d..306bb5b 100644 --- a/src/util/cJSON.c +++ b/src/util/cJSON.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2009 Dave Gamble + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ /* cJSON */ /* JSON parser in C. */ +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif + #include <string.h> #include <stdio.h> #include <math.h> @@ -30,734 +34,2666 @@ #include <float.h> #include <limits.h> #include <ctype.h> +#include <locale.h> + +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + #include "cJSON.h" -static const char *ep; +/* define our own boolean type */ +#define true ((cJSON_bool)1) +#define false ((cJSON_bool)0) + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 9) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif -const char *cJSON_GetErrorPtr(void) {return ep;} +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} -static int cJSON_strcasecmp(const char *s1,const char *s2) +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) { - if (!s1) return (s1==s2)?0:1; - if (!s2) return 1; - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); } -static void *(*cJSON_malloc)(size_t sz) = malloc; -static void (*cJSON_free)(void *ptr) = free; +typedef struct internal_hooks +{ + void *(*allocate)(size_t size); + void (*deallocate)(void *pointer); + void *(*reallocate)(void *pointer, size_t size); +} internal_hooks; + +static internal_hooks global_hooks = { malloc, free, realloc }; -static char* cJSON_strdup(const char* str) +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) { - size_t len; - char* copy; + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + if (!(copy = (unsigned char*)hooks->allocate(length))) + { + return NULL; + } + memcpy(copy, string, length); - len = strlen(str) + 1; - if (!(copy = (char*)cJSON_malloc(len))) return 0; - memcpy(copy,str,len); - return copy; + return copy; } -void cJSON_InitHooks(cJSON_Hooks* hooks) +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) { - if (!hooks) { /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_free = free; + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; return; } - cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_free = (hooks->free_fn)?hooks->free_fn:free; + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } } /* Internal constructor. */ -static cJSON *cJSON_New_Item(void) +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) { - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) memset(node,0,sizeof(cJSON)); - return node; + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; } /* Delete a cJSON structure. */ -void cJSON_Delete(cJSON *c) +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) { - cJSON *next; - while (c) - { - next=c->next; - if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); - if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); - if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); - cJSON_free(c); - c=next; - } + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; } +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +#define cannot_read(buffer, size) (!can_read(buffer, size)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + /* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item,const char *num) +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) { - double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + double number = 0; + unsigned char *after_end = NULL; + unsigned char number_c_string[64]; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_c_string[i] = buffer_at_offset(input_buffer)[i]; + break; + + case '.': + number_c_string[i] = decimal_point; + break; + + default: + goto loop_end; + } + } +loop_end: + number_c_string[i] = '\0'; + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } - if (*num=='-') sign=-1,num++; /* Has sign? */ - if (*num=='0') num++; /* is zero */ - if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ - if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ - if (*num=='e' || *num=='E') /* Exponent? */ - { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ - while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ - } + item->type = cJSON_Number; - n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ - - item->valuedouble=n; - item->valueint=(int)n; - item->type=cJSON_Number; - return num; + input_buffer->offset += (size_t)(after_end - number_c_string); + return true; } -static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } -typedef struct {char *buffer; int length; int offset; } printbuffer; + return object->valuedouble = number; +} -static char* ensure(printbuffer *p,int needed) +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) { - char *newbuffer;int newsize; - if (!p || !p->buffer) return 0; - needed+=p->offset; - if (needed<=p->length) return p->buffer+p->offset; + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + if (newbuffer) + { + memcpy(newbuffer, p->buffer, p->offset + 1); + } + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; - newsize=pow2gt(needed); - newbuffer=(char*)cJSON_malloc(newsize); - if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} - if (newbuffer) memcpy(newbuffer,p->buffer,p->length); - cJSON_free(p->buffer); - p->length=newsize; - p->buffer=newbuffer; - return newbuffer+p->offset; + return newbuffer + p->offset; } -static int update(printbuffer *p) +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) { - char *str; - if (!p || !p->buffer) return 0; - str=p->buffer+p->offset; - return p->offset+strlen(str); + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); } /* Render the number nicely from the given item into a string. */ -static char *print_number(cJSON *item,printbuffer *p) -{ - char *str=0; - double d=item->valuedouble; - if (d==0) - { - if (p) str=ensure(p,2); - else str=(char*)cJSON_malloc(2); /* special case for 0. */ - if (str) strcpy(str,"0"); - } - else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) - { - if (p) str=ensure(p,21); - else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ - if (str) sprintf(str,"%d",item->valueint); - } - else - {

