├── ServerCode ├── IoT.zip └── README.txt ├── Makefile ├── inc ├── TargConfig.h ├── BaAtoi.h ├── AllocatorIntf.h ├── JDecoder.h ├── JEncoder.h ├── BufPrint.h ├── JParser.h └── JVal.h ├── examples ├── ledctrl.h ├── solib.c ├── solib.h └── StaticAllocatorEx.cpp ├── src ├── AllocatorIntf.c ├── BaAtoi.c ├── JDecoder.c ├── JEncoder.c └── JVal.c ├── README.md ├── VcMake ├── test1.vcxproj ├── staticalloc.vcxproj ├── m2mled.vcxproj ├── JDecoder.vcxproj ├── ValFact.vcxproj ├── JSON.vcxproj └── examples.sln ├── test └── test1.cpp └── LICENSE /ServerCode/IoT.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RealTimeLogic/JSON/HEAD/ServerCode/IoT.zip -------------------------------------------------------------------------------- /ServerCode/README.txt: -------------------------------------------------------------------------------- 1 | 2 | IoT.zip includes the server side code for the m2m-led.c example program. 3 | 4 | The code is designed for the Mako Server: https://makoserver.net/ 5 | 6 | You may connect m2m-led.c to your own server as follows: 7 | 1: edit m2m-led.c and set the address macro to "localhost" 8 | 2: Compile the m2mled example 9 | 3: Download and unpack the Mako Server in any directory 10 | 4: Start the server example as follows: path2mako/mako -lIoT::IoT.zip 11 | 5: Start m2mled 12 | 13 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | VPATH := src:test:examples 3 | #CFLAGS += -g 4 | CFLAGS += -Wall -Iinc $(EXCFLAGS) 5 | 6 | #Set the following for cross compilation 7 | ifndef RANLIB 8 | CXX=g++ 9 | CC=gcc 10 | AR=ar 11 | RANLIB=ranlib 12 | endif 13 | 14 | ifndef ARFLAGS 15 | ARFLAGS=rv 16 | endif 17 | 18 | ifndef ODIR 19 | ODIR = ./ 20 | endif 21 | 22 | $(ODIR)/%.o : %.c 23 | $(CC) -c $(CFLAGS) -o $@ $< 24 | $(ODIR)/%.o : %.cpp 25 | $(CXX) -c $(CFLAGS) -o $@ $< 26 | 27 | # Three libs: One with all source code (large), one with 28 | # JParserValFact (medium), and one with JDecoder.c (small) 29 | 30 | CORESRC = BaAtoi.c BufPrint.c JEncoder.c JParser.c 31 | JSONSRC = AllocatorIntf.c JVal.c JDecoder.c $(CORESRC) 32 | VALFACTSRC = AllocatorIntf.c JVal.c $(CORESRC) 33 | DECODERSRC = JDecoder.c $(CORESRC) 34 | 35 | 36 | .PHONY: all libs examples c_example clean 37 | 38 | #All examples: C and C++ 39 | all: libs 40 | $(MAKE) examples 41 | 42 | #Example using C only (no C++) 43 | c_example: libs 44 | $(MAKE) m2mled$(EXT) 45 | 46 | libs: obj 47 | $(MAKE) ODIR=obj/jd EXCFLAGS=-DNO_JVAL_DEPENDENCY libJDecoder.a 48 | $(MAKE) ODIR=obj libJSON.a libValFact.a 49 | 50 | obj: 51 | mkdir obj 52 | cd obj&&mkdir jd 53 | 54 | libJSON.a: $(JSONSRC:%.c=$(ODIR)/%.o) 55 | $(AR) $(ARFLAGS) $@ $^ 56 | $(RANLIB) $@ 57 | 58 | libValFact.a: $(VALFACTSRC:%.c=$(ODIR)/%.o) 59 | $(AR) $(ARFLAGS) $@ $^ 60 | $(RANLIB) $@ 61 | 62 | libJDecoder.a: $(DECODERSRC:%.c=$(ODIR)/%.o) 63 | $(AR) $(ARFLAGS) $@ $^ 64 | $(RANLIB) $@ 65 | 66 | examples: test1$(EXT) staticalloc$(EXT) m2mled$(EXT) 67 | 68 | test1$(EXT): test1.o 69 | $(CXX) -o $@ $^ -L. -lJSON $(EXTRALIBS) 70 | 71 | staticalloc$(EXT): StaticAllocatorEx.o 72 | $(CXX) -o $@ $^ -L. -lValFact $(EXTRALIBS) 73 | 74 | m2mled$(EXT): m2m-led.o solib.o 75 | $(CC) -o $@ $^ -L. -lJDecoder $(EXTRALIBS) 76 | 77 | clean: 78 | rm -rf obj *.a *.o 79 | -------------------------------------------------------------------------------- /inc/TargConfig.h: -------------------------------------------------------------------------------- 1 | 2 | /* Configuration header file. 3 | Modify as needed 4 | */ 5 | 6 | #ifndef _TargConfig_h 7 | #define _TargConfig_h 8 | 9 | /* Define one of B_LITTLE_ENDIAN or B_BIG_ENDIAN */ 10 | #if !defined(B_LITTLE_ENDIAN) && !defined(B_BIG_ENDIAN) 11 | #define B_LITTLE_ENDIAN 12 | #endif 13 | 14 | #ifndef TRUE 15 | #define TRUE 1 16 | #endif 17 | 18 | #ifndef FALSE 19 | #define FALSE 0 20 | #endif 21 | 22 | /* Must return 32-bit aligned address */ 23 | #define baMalloc(s) malloc(s) 24 | #define baRealloc(m, s) realloc(m, s) /* as above */ 25 | #define baFree(m) free(m) 26 | 27 | #ifdef _WIN32 28 | #ifndef _CRT_SECURE_NO_WARNINGS 29 | #define _CRT_SECURE_NO_WARNINGS 30 | #define _CRT_NONSTDC_NO_WARNINGS 31 | #endif 32 | #ifndef WIN32_LEAN_AND_MEAN 33 | #define WIN32_LEAN_AND_MEAN 1 34 | #endif 35 | #include 36 | #include 37 | #define millisleep(milliseconds) Sleep(milliseconds) 38 | #else 39 | #ifndef millisleep 40 | #define millisleep(ms) do { \ 41 | struct timespec tp; \ 42 | tp.tv_sec = (ms)/1000; \ 43 | tp.tv_nsec = ((ms) % 1000) * 1000000; \ 44 | nanosleep(&tp,0); \ 45 | } while(0) 46 | #endif 47 | #endif 48 | 49 | 50 | #ifndef INTEGRAL_TYPES 51 | #define INTEGRAL_TYPES 52 | #if (__STDC_VERSION__ >= 199901L) || defined( __GNUC__) 53 | #include 54 | typedef uint8_t U8; 55 | typedef int8_t S8; 56 | typedef uint16_t U16; 57 | typedef int16_t S16; 58 | typedef uint32_t U32; 59 | typedef int32_t S32; 60 | typedef uint64_t U64; 61 | typedef int64_t S64; 62 | #else 63 | typedef unsigned char U8; 64 | typedef signed char S8; 65 | typedef unsigned short U16; 66 | typedef signed short S16; 67 | typedef unsigned long U32; 68 | typedef signed long S32; 69 | typedef unsigned long long U64; 70 | typedef signed long long S64; 71 | #endif 72 | #endif 73 | 74 | #ifndef BaBool 75 | #define BaBool U8 76 | #endif 77 | 78 | 79 | #define BA_API 80 | 81 | #include 82 | #include 83 | #include 84 | #include 85 | 86 | #ifndef NDEBUG 87 | #include 88 | #define baAssert assert 89 | #else 90 | #define baAssert(x) 91 | #endif 92 | 93 | 94 | #endif /* _TargConfig_h */ 95 | -------------------------------------------------------------------------------- /examples/ledctrl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * SharkSSL Embedded SSL/TLS Stack 10 | **************************************************************************** 11 | * PROGRAM MODULE 12 | * 13 | * $Id$ 14 | * 15 | * COPYRIGHT: Real Time Logic LLC, 2014 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | 37 | #ifndef _ledctrl_h 38 | #define _ledctrl_h 39 | 40 | #include 41 | 42 | 43 | /* Each LED is registered with the following information */ 44 | typedef struct { 45 | const char* name; /* LED name shown in the browser */ 46 | const char* color; /* The color of this particular LED */ 47 | int id; /* A unique ID for the LED. */ 48 | } LedInfo; 49 | 50 | 51 | void mainTask(void); /* Ref-Ta */ 52 | const LedInfo* getLedInfo(int* len); 53 | const char* getDevName(void); 54 | void setLed(int ledId, int on); 55 | int setLedFromDevice(int* ledId, int* on); 56 | 57 | 58 | typedef enum { 59 | ProgramStatus_Starting, 60 | ProgramStatus_Restarting, 61 | ProgramStatus_Connecting, 62 | ProgramStatus_SslHandshake, 63 | ProgramStatus_DeviceReady, 64 | ProgramStatus_CloseCommandReceived, 65 | 66 | ProgramStatus_SocketError, 67 | ProgramStatus_DnsError, 68 | ProgramStatus_ConnectionError, 69 | ProgramStatus_CertificateNotTrustedError, 70 | ProgramStatus_SslHandshakeError, 71 | ProgramStatus_WebServiceNotAvailError, 72 | ProgramStatus_PongResponseError, 73 | ProgramStatus_InvalidCommandError, 74 | ProgramStatus_MemoryError 75 | } ProgramStatus; 76 | 77 | 78 | void setProgramStatus(ProgramStatus s); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/AllocatorIntf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Embedded Web-Server 10 | **************************************************************************** 11 | * PROGRAM MODULE 12 | * 13 | * $Id: AllocatorIntf.c 4914 2021-12-01 18:24:30Z wini $ 14 | * 15 | * COPYRIGHT: Real Time Logic, 2014 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | #ifndef BA_LIB 37 | #define BA_LIB 1 38 | #endif 39 | 40 | #include 41 | #include 42 | 43 | static void* 44 | AllocatorIntf_defaultMalloc(AllocatorIntf* o, size_t* size) 45 | { 46 | (void)o; 47 | return baMalloc(*size); 48 | } 49 | 50 | 51 | static void* 52 | AllocatorIntf_defaultRealloc(AllocatorIntf* o, void* memblock, size_t* size) 53 | { 54 | (void)o; 55 | return baRealloc(memblock, *size); 56 | } 57 | 58 | 59 | static void 60 | AllocatorIntf_defaultFree(AllocatorIntf* o, void* memblock) 61 | { 62 | (void)o; 63 | baFree(memblock); 64 | } 65 | 66 | 67 | BA_API AllocatorIntf* 68 | AllocatorIntf_getDefault(void) 69 | { 70 | static AllocatorIntf alloc = { 71 | AllocatorIntf_defaultMalloc, 72 | AllocatorIntf_defaultRealloc, 73 | AllocatorIntf_defaultFree 74 | }; 75 | 76 | return &alloc; 77 | } 78 | 79 | 80 | BA_API char* 81 | baStrdup2(struct AllocatorIntf* a, const char* str) 82 | { 83 | char* dup; 84 | size_t size; 85 | if(!str) return 0; 86 | size = strlen(str)+1; 87 | dup = (char*)AllocatorIntf_malloc(a, &size); 88 | if(dup) 89 | strcpy(dup, str); 90 | return dup; 91 | } 92 | -------------------------------------------------------------------------------- /inc/BaAtoi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Embedded Web-Server 10 | * 11 | **************************************************************************** 12 | * HEADER 13 | * 14 | * $Id: BaAtoi.h 4915 2021-12-01 18:26:55Z wini $ 15 | * 16 | * COPYRIGHT: Real Time Logic LLC, 2014 17 | * 18 | * This software is copyrighted by and is the sole property of Real 19 | * Time Logic LLC. All rights, title, ownership, or other interests in 20 | * the software remain the property of Real Time Logic LLC. This 21 | * software may only be used in accordance with the terms and 22 | * conditions stipulated in the corresponding license agreement under 23 | * which the software has been supplied. Any unauthorized use, 24 | * duplication, transmission, distribution, or disclosure of this 25 | * software is expressly forbidden. 26 | * 27 | * This Copyright notice may not be removed or modified without prior 28 | * written consent of Real Time Logic LLC. 29 | * 30 | * Real Time Logic LLC. reserves the right to modify this software 31 | * without notice. 32 | * 33 | * http://www.realtimelogic.com 34 | **************************************************************************** 35 | * 36 | * 37 | */ 38 | 39 | 40 | #ifndef __BaAtoi_h 41 | #define __BaAtoi_h 42 | 43 | #include 44 | 45 | #ifndef BA_API 46 | #define BA_API 47 | #endif 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | /** Converts characters of s to type U64. The number is negated if 54 | preceded by '-'. Returns 0 if unable to convert or s is NULL. 55 | */ 56 | BA_API U64 U64_atoll(const char* s); 57 | BA_API U64 U64_atoll2(const char* s, const char* e); 58 | 59 | #define S64_atoll(s) ((S64)U64_atoll(s)) 60 | 61 | 62 | /** Negates a 32 bit number. 63 | */ 64 | BA_API U32 U32_negate(U32 n); 65 | 66 | /** Converts characters of s to type U32. The number is negated if 67 | preceded by '-'. Returns 0 if unable to convert or s is NULL. 68 | */ 69 | BA_API U32 U32_atoi(const char* s); 70 | 71 | /** Works like U32_atoi, but converts from start of string 's' to end 'e'. 72 | */ 73 | BA_API U32 U32_atoi2(const char* s, const char* e); 74 | 75 | /** Converts hex characters of s to type U32. 76 | Returns 0 if unable to convert or s is NULL. 77 | */ 78 | BA_API U32 U32_hextoi(const char *s); 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JSON C/C++ Library for IoT Communication 2 | 3 | The JSON C library is designed for use in resource constrained micro controllers such as the Cortex-M0. See the [JSON C/C++ Library home page](https://realtimelogic.com/products/json/) for details. 4 | 5 | This standalone version of the JSON library is also embedded in the [Barracuda App Server (repository)](https://github.com/RealTimeLogic/BAS), which provides a Lua API via the [Lua Server Pages Engine](https://realtimelogic.com/products/lua-server-pages/). 6 | 7 | **The library can be used in three modes:** 8 | 9 | * Using dynamic allocation (Complexity level: easy) 10 | * Using static allocation based on the [JSON Parser Value Factory](https://realtimelogic.com/ba/doc/en/C/reference/html/structJParserValFact.html) (Complexity level: moderate) 11 | * Using static allocation based on the [JSON Decoder](https://realtimelogic.com/ba/doc/en/C/reference/html/structJDecoder.html) class (Complexity level: advanced) 12 | 13 | A detailed explanation on the three different modes can be found in the [reference manual](https://realtimelogic.com/ba/doc/en/C/reference/html/md_en_C_md_JSON.html) . 14 | 15 | # Included JSON Examples 16 | 17 | * The m2m-led.c IoT example is using the JSON parser in continuous stream parser mode and is using the more complex JSON Decoder setup. This setup is explained in the online [M2M LED JSON Client Documentation](https://realtimelogic.com/ba/doc/en/C/reference/html/md_en_C_md_JSON.html#M2MLED). 18 | * The StaticAllocatorEx.cpp shows how to use a static allocator with the [JSON Parser Value Factory](https://realtimelogic.com/ba/doc/en/C/reference/html/structJParserValFact.html). 19 | * Generic test/example program: test/test1.cpp 20 | 21 | # Additional JSON IoT Examples 22 | * The [Minnow WebSocket Server's Reference Example](https://realtimelogic.com/articles/Creating-SinglePage-Apps-with-the-Minnow-Server) uses JSON for messages sent over WebSockets. 23 | * The [SMQ IoT Protocol](https://realtimelogic.com/products/simplemq/)'s [publisher and subscriber examples](https://github.com/RealTimeLogic/SMQ#1-introductory-smq-examples) send and receive JSON encoded messages. The readme file includes [additional information](https://github.com/RealTimeLogic/SMQ#simplified-cc-design) on how to use this JSON library for sending a large JSON message as chunks and how to parse the chunks as they trickle in. 24 | 25 | # Compiling 26 | 27 | Decide if you want to use the more complex JDecoder with static allocation or the easier to use JSON Parser Value Factory (JParserValFact) with dynamic allocation or static allocation. See the documentation for details regarding these two classes. 28 | 29 | * If using JParserValFact, include all C files in the build, except JDecoder.c 30 | * If using JDecoder, include all C files in the build, except JVal.c and define the macro NO_JVAL_DEPENDENCY when compiling the code. See the comment at the top of the source file JEncoder.c for details. 31 | 32 | The included example Makefile, which is configured for GCC, builds 3 libraries. See the Makefile for details. 33 | 34 | NOTE: The C files in the src directory MUST be compiled by a C compiler and not by a C++ compiler. Files ending with .c must be compiled by a C compiler and files ending with .cpp must be compiled by a C++ compiler. 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/BaAtoi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Embedded Web-Server 10 | **************************************************************************** 11 | * PROGRAM MODULE 12 | * 13 | * $Id: BaServerLib.c 3455 2014-08-18 21:22:21Z wini $ 14 | * 15 | * COPYRIGHT: Real Time Logic, 2002 - 2014 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://www.realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | 37 | #ifndef BA_LIB 38 | #define BA_LIB 1 39 | #endif 40 | 41 | #include 42 | #include 43 | 44 | 45 | BA_API U32 46 | U32_negate(U32 n) 47 | { 48 | return (U32)(-(S32)n); 49 | } 50 | 51 | 52 | BA_API U32 53 | U32_atoi2(const char* s, const char* e) 54 | { 55 | U32 n = 0; 56 | BaBool isNegative; 57 | if(!s) return 0; 58 | if(*s == '-') 59 | { 60 | ++s; 61 | isNegative = TRUE; 62 | } 63 | else 64 | isNegative = FALSE; 65 | for ( ; s < e && *s != '.' ; ++s ) /* '.' for floating point */ 66 | n = 10 * n + (*s-'0'); 67 | if(*s == '.' && s[1]) 68 | { 69 | if(s[1] >= '5') 70 | n++; 71 | } 72 | return isNegative ? U32_negate(n) : n; 73 | } 74 | 75 | 76 | BA_API U32 77 | U32_atoi(const char* s) 78 | { 79 | if(!s) return 0; 80 | return U32_atoi2(s, s+strlen(s)); 81 | } 82 | 83 | BA_API U32 84 | U32_hextoi(const char *str) 85 | { 86 | U32 number = 0; 87 | U32 i; 88 | if(!str) return 0; 89 | for(i = 0 ; i<8 && *str!=0 ; i++) 90 | { 91 | U8 c = *str++ ; 92 | if(c>='0' && c<='9') c -= '0' ; /* 0..9 */ 93 | else if(c>='a' && c<='f') c = c-'a'+10 ; /* 10..15 */ 94 | else if(c>='A' && c<='F') c = c-'A'+10 ; /* 10..15 */ 95 | else break; /* Invalid character. */ 96 | number = (number << 4) | c ; 97 | } 98 | return *str==0 ? number : 0 ; 99 | } 100 | 101 | 102 | BA_API U64 103 | U64_atoll2(const char* s, const char* e) 104 | { 105 | U64 n = 0; 106 | BaBool isNegative; 107 | if(!s) return 0; 108 | if(*s == '-') 109 | { 110 | ++s; 111 | isNegative = TRUE; 112 | } 113 | else 114 | isNegative = FALSE; 115 | for ( ; s < e ; ++s ) 116 | n = 10 * n + (*s-'0'); 117 | return isNegative ? (U64)(-(S64)n) : n; 118 | } 119 | 120 | 121 | BA_API U64 122 | U64_atoll(const char* s) 123 | { 124 | if(!s) return 0; 125 | return U64_atoll2(s, s+strlen(s)); 126 | } 127 | -------------------------------------------------------------------------------- /VcMake/test1.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | {45F1316D-58EA-434C-90DD-286FCBA95F31} 18 | m2m-led 19 | 20 | 21 | 22 | Application 23 | MultiByte 24 | v143 25 | 26 | 27 | v143 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | <_ProjectFileVersion>10.0.30128.1 39 | $(SolutionDir)$(Configuration)\ 40 | $(Configuration)\ 41 | 42 | 43 | 44 | Disabled 45 | ..\inc 46 | 47 | 48 | true 49 | EnableFastChecks 50 | MultiThreadedDebugDLL 51 | Level4 52 | EditAndContinue 53 | 4996;4127;%(DisableSpecificWarnings) 54 | 55 | 56 | JSON.lib;ws2_32.lib;%(AdditionalDependencies) 57 | true 58 | false 59 | 60 | 61 | MachineX86 62 | Debug 63 | 64 | 65 | 66 | 67 | ..\inc 68 | 69 | 70 | Size 71 | true 72 | Full 73 | true 74 | 75 | 76 | JSON.lib;ws2_32.lib;%(AdditionalDependencies) 77 | false 78 | Release 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /VcMake/staticalloc.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A} 18 | m2m-led 19 | 20 | 21 | 22 | Application 23 | MultiByte 24 | v143 25 | 26 | 27 | v143 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | <_ProjectFileVersion>10.0.30128.1 39 | $(SolutionDir)$(Configuration)\ 40 | $(Configuration)\ 41 | 42 | 43 | 44 | Disabled 45 | ..\inc 46 | 47 | 48 | true 49 | EnableFastChecks 50 | MultiThreadedDebugDLL 51 | Level4 52 | EditAndContinue 53 | 4996;4127;%(DisableSpecificWarnings) 54 | 55 | 56 | ValFact.lib;ws2_32.lib;%(AdditionalDependencies) 57 | true 58 | false 59 | 60 | 61 | MachineX86 62 | Debug 63 | 64 | 65 | 66 | 67 | ..\inc 68 | 69 | 70 | Size 71 | true 72 | Full 73 | true 74 | 75 | 76 | ValFact.lib;ws2_32.lib;%(AdditionalDependencies) 77 | false 78 | Release 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /VcMake/m2mled.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB} 19 | m2m-led 20 | 21 | 22 | 23 | Application 24 | MultiByte 25 | v143 26 | 27 | 28 | v143 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | <_ProjectFileVersion>10.0.30128.1 40 | $(SolutionDir)$(Configuration)\ 41 | $(Configuration)\ 42 | 43 | 44 | 45 | Disabled 46 | ..\inc 47 | 48 | 49 | true 50 | EnableFastChecks 51 | MultiThreadedDebugDLL 52 | Level4 53 | EditAndContinue 54 | 4996;4127;%(DisableSpecificWarnings) 55 | 56 | 57 | JDecoder.lib;ws2_32.lib;%(AdditionalDependencies) 58 | true 59 | false 60 | 61 | 62 | MachineX86 63 | Debug 64 | 65 | 66 | 67 | 68 | ..\inc 69 | 70 | 71 | Size 72 | true 73 | Full 74 | true 75 | 76 | 77 | JDecoder.lib;ws2_32.lib;%(AdditionalDependencies) 78 | false 79 | Release 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /examples/solib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | **************************************************************************** 10 | * PROGRAM MODULE 11 | * 12 | * $Id$ 13 | * 14 | * COPYRIGHT: Real Time Logic LLC, 2014 15 | * 16 | * This software is copyrighted by and is the sole property of Real 17 | * Time Logic LLC. All rights, title, ownership, or other interests in 18 | * the software remain the property of Real Time Logic LLC. This 19 | * software may only be used in accordance with the terms and 20 | * conditions stipulated in the corresponding license agreement under 21 | * which the software has been supplied. Any unauthorized use, 22 | * duplication, transmission, distribution, or disclosure of this 23 | * software is expressly forbidden. 24 | * 25 | * This Copyright notice may not be removed or modified without prior 26 | * written consent of Real Time Logic LLC. 27 | * 28 | * Real Time Logic LLC. reserves the right to modify this software 29 | * without notice. 30 | * 31 | * http://realtimelogic.com 32 | **************************************************************************** 33 | * 34 | */ 35 | 36 | 37 | #include "solib.h" 38 | 39 | 40 | #ifndef NO_BSD_SOCK 41 | 42 | #ifndef _WIN32 43 | #define INVALID_SOCKET -1 44 | #define closesocket close 45 | #endif 46 | 47 | 48 | /* Wait 'tmo' milliseconds for socket 'read' activity. 49 | Returns 0 on pending data and -1 on timeout. 50 | */ 51 | static int readtmo(SOCKET sock, U32 tmo) 52 | { 53 | fd_set recSet; 54 | struct timeval tv; 55 | tv.tv_sec = tmo / 1000; 56 | tv.tv_usec = (tmo % 1000) * 1000; 57 | FD_ZERO(&recSet); 58 | FD_SET(sock, &recSet); 59 | return select(sock+1, &recSet, 0, 0, &tv) > 0 ? 0 : -1; 60 | } 61 | 62 | 63 | int so_connect(SOCKET* sock, const char* address, U16 port) 64 | { 65 | struct sockaddr_in addr; 66 | struct hostent* hostInfo = gethostbyname(address); 67 | *sock=-1; 68 | if(!hostInfo) 69 | return -2; 70 | 71 | addr.sin_family = AF_INET; 72 | addr.sin_port = htons(port); 73 | addr.sin_addr.s_addr = ((struct in_addr *)hostInfo->h_addr)->s_addr; 74 | if ((*sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 75 | return -1; 76 | 77 | if(connect(*sock, (struct sockaddr*)&addr, sizeof(addr)) != INVALID_SOCKET) 78 | return 0; 79 | 80 | so_close(sock); 81 | return -3; 82 | } 83 | 84 | 85 | /* 86 | Extract the first connection on the queue of pending connections, 87 | create a new socket, and allocate a new file descriptor for that 88 | socket. 89 | 90 | Returns: 91 | 1: Success 92 | 0: timeout 93 | -1: error 94 | 95 | */ 96 | int so_accept(SOCKET* listenSock, U32 timeout, SOCKET* outSock) 97 | { 98 | if(timeout != INFINITE_TMO) 99 | { 100 | *outSock = -1; 101 | if(readtmo(*listenSock,timeout)) 102 | return 0; 103 | } 104 | if( (*outSock=accept(*listenSock, 0, 0)) < 0 ) 105 | return -1; 106 | return 1; 107 | } 108 | 109 | 110 | void so_close(SOCKET* sock) 111 | { 112 | closesocket(*sock); 113 | *sock=-1; 114 | } 115 | 116 | 117 | int so_sockValid(SOCKET* sock) 118 | { 119 | return *sock > 0 ? 1 : 0; 120 | } 121 | 122 | 123 | S32 so_send(SOCKET* sock, const void* buf, U32 len) 124 | { 125 | return send(*sock,buf,len,0); 126 | } 127 | 128 | 129 | S32 so_recv(SOCKET* sock, void* buf, U32 len, U32 timeout) 130 | { 131 | int recLen; 132 | if(timeout != INFINITE_TMO) 133 | { 134 | if(readtmo(*sock,timeout)) 135 | return 0; 136 | } 137 | 138 | recLen = recv(*sock,buf,len,0); 139 | if (recLen <= 0) 140 | { 141 | /* If the virtual circuit was closed gracefully, and 142 | * all data was received, then a recv will return 143 | * immediately with zero bytes read. 144 | * We return -1 for above i.e. if(recLen == 0) return -1; 145 | * Note: this construction does not work with non blocking sockets. 146 | */ 147 | return -1; 148 | } 149 | return recLen; 150 | } 151 | 152 | 153 | 154 | #endif /* NO_BSD_SOCK */ 155 | -------------------------------------------------------------------------------- /VcMake/JDecoder.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {75262908-FF79-4187-9902-34CD3A887CEB} 22 | m2m-led 23 | 24 | 25 | 26 | StaticLibrary 27 | MultiByte 28 | v143 29 | 30 | 31 | StaticLibrary 32 | v143 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | <_ProjectFileVersion>10.0.30128.1 44 | $(SolutionDir)$(Configuration)\ 45 | $(Configuration)\jd\ 46 | $(Configuration)\jd\ 47 | 48 | 49 | 50 | Disabled 51 | ..\inc 52 | NO_JVAL_DEPENDENCY 53 | true 54 | EnableFastChecks 55 | MultiThreadedDebugDLL 56 | Level4 57 | EditAndContinue 58 | 4996;4127;%(DisableSpecificWarnings) 59 | 60 | 61 | minnow.lib;ws2_32.lib;%(AdditionalDependencies) 62 | true 63 | false 64 | 65 | 66 | MachineX86 67 | Debug 68 | 69 | 70 | 71 | 72 | ..\inc 73 | NO_JVAL_DEPENDENCY 74 | Size 75 | true 76 | Full 77 | true 78 | 79 | 80 | minnow.lib;ws2_32.lib;%(AdditionalDependencies) 81 | false 82 | Release 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /VcMake/ValFact.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {13DF4164-3E75-49F3-A257-64F88265C0C0} 23 | m2m-led 24 | 25 | 26 | 27 | StaticLibrary 28 | MultiByte 29 | v143 30 | 31 | 32 | StaticLibrary 33 | v143 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | <_ProjectFileVersion>10.0.30128.1 45 | $(SolutionDir)$(Configuration)\ 46 | $(Configuration)\ 47 | $(Configuration)\ 48 | 49 | 50 | 51 | Disabled 52 | ..\inc 53 | 54 | 55 | true 56 | EnableFastChecks 57 | MultiThreadedDebugDLL 58 | Level4 59 | EditAndContinue 60 | 4996;4127;%(DisableSpecificWarnings) 61 | 62 | 63 | minnow.lib;ws2_32.lib;%(AdditionalDependencies) 64 | true 65 | false 66 | 67 | 68 | MachineX86 69 | Debug 70 | 71 | 72 | 73 | 74 | ..\inc 75 | 76 | 77 | Size 78 | true 79 | Full 80 | true 81 | 82 | 83 | minnow.lib;ws2_32.lib;%(AdditionalDependencies) 84 | false 85 | Release 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /VcMake/JSON.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {6991B964-4C52-4096-A2E9-F852355ACCCB} 24 | m2m-led 25 | 26 | 27 | 28 | StaticLibrary 29 | MultiByte 30 | v143 31 | 32 | 33 | StaticLibrary 34 | v143 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | <_ProjectFileVersion>10.0.30128.1 46 | $(SolutionDir)$(Configuration)\ 47 | $(Configuration)\ 48 | $(Configuration)\ 49 | 50 | 51 | 52 | Disabled 53 | ..\inc 54 | 55 | 56 | true 57 | EnableFastChecks 58 | MultiThreadedDebugDLL 59 | Level4 60 | EditAndContinue 61 | 4996;4127;%(DisableSpecificWarnings) 62 | 63 | 64 | minnow.lib;ws2_32.lib;%(AdditionalDependencies) 65 | true 66 | false 67 | 68 | 69 | MachineX86 70 | Debug 71 | 72 | 73 | 74 | 75 | ..\inc 76 | 77 | 78 | Size 79 | true 80 | Full 81 | true 82 | 83 | 84 | minnow.lib;ws2_32.lib;%(AdditionalDependencies) 85 | false 86 | Release 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/solib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | **************************************************************************** 10 | * PROGRAM MODULE 11 | * 12 | * $Id$ 13 | * 14 | * COPYRIGHT: Real Time Logic LLC, 2014 15 | * 16 | * This software is copyrighted by and is the sole property of Real 17 | * Time Logic LLC. All rights, title, ownership, or other interests in 18 | * the software remain the property of Real Time Logic LLC. This 19 | * software may only be used in accordance with the terms and 20 | * conditions stipulated in the corresponding license agreement under 21 | * which the software has been supplied. Any unauthorized use, 22 | * duplication, transmission, distribution, or disclosure of this 23 | * software is expressly forbidden. 24 | * 25 | * This Copyright notice may not be removed or modified without prior 26 | * written consent of Real Time Logic LLC. 27 | * 28 | * Real Time Logic LLC. reserves the right to modify this software 29 | * without notice. 30 | * 31 | * http://realtimelogic.com 32 | **************************************************************************** 33 | * 34 | */ 35 | 36 | #ifndef _solib_h 37 | #define _solib_h 38 | 39 | #include 40 | 41 | #ifndef HOST_PLATFORM 42 | #if defined(__GNUC__) || defined(_WIN32) 43 | /** Assume it's running on a host with a std in/out console for VC++ and GCC 44 | */ 45 | #define HOST_PLATFORM 1 46 | #ifndef XPRINTF 47 | #define XPRINTF 1 48 | #endif 49 | #else 50 | #define HOST_PLATFORM 0 51 | #ifndef XPRINTF 52 | #define XPRINTF 0 53 | #endif 54 | #endif 55 | #endif 56 | 57 | #ifdef __CODEWARRIOR__ 58 | /* Assume MQX */ 59 | #include 60 | #include 61 | #else /* ! __CODEWARRIOR__ */ 62 | #include 63 | #include 64 | #include 65 | 66 | #ifdef __GNUC__ 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | #include 77 | #include 78 | #elif defined(SharkSSLNetX) 79 | #include 80 | typedef struct { 81 | NX_TCP_SOCKET nxSock; 82 | NX_PACKET* nxFirstPacket; 83 | NX_PACKET* nxPacket; 84 | UCHAR* nxPktOffs; 85 | } SOCKET; 86 | #define NO_BSD_SOCK 87 | #endif /* __GNUC__ */ 88 | 89 | #endif /* __CODEWARRIOR__ */ 90 | 91 | #include 92 | 93 | /** Infinite wait time option for socket read functions. 94 | */ 95 | #define INFINITE_TMO (~((U32)0)) 96 | 97 | #ifndef NO_BSD_SOCK 98 | /** The SOCKET object/handle is an 'int' when using a BSD compatible 99 | TCP/IP stack. Non BSD compatible TCP IP stacks must set the macro 100 | NO_BSD_SOCK and define the SOCKET object. See the header file 101 | solib.h for details. 102 | */ 103 | #define SOCKET int 104 | #endif 105 | 106 | 107 | #ifdef __cplusplus 108 | extern "C" { 109 | #endif 110 | 111 | /** Initializes a SOCKET object connected to a remote host/address at 112 | * a given port. 113 | \return Zero on success. 114 | Error codes returned: 115 | \li \c -1 Cannot create socket: Fatal 116 | \li \c -2 Cannot resolve 'address' 117 | \li \c -3 Cannot connect 118 | */ 119 | int so_connect(SOCKET* sock, const char* address, U16 port); 120 | 121 | /** Waits for remote connections on the server SOCKET object 122 | 'listenSock', initialized by function so_bind, and initializes 123 | socket object 'outSock' to represent the new connection. 124 | 125 | \return 126 | \li \c 1 Success 127 | \li \c 0 timeout 128 | \li \c -1 error 129 | */ 130 | int so_accept(SOCKET* listenSock, U32 timeout, SOCKET* outSock); 131 | 132 | /** Close a connected socket connection. 133 | */ 134 | void so_close(SOCKET* sock); 135 | 136 | /** Returns TRUE if socket is valid (connected). 137 | */ 138 | int so_sockValid(SOCKET* sock); 139 | 140 | /** Sends data to the connected peer. 141 | */ 142 | S32 so_send(SOCKET* sock, const void* buf, U32 len); 143 | 144 | /** Waits for data sent by peer. 145 | 146 | \param sock the SOCKET object. 147 | \param buf is the data to send. 148 | \param len is the 'buf' length. 149 | \param timeout in milliseconds. The timeout can be set to #INFINITE_TMO. 150 | \returns the length of the data read, zero on timeout, or a 151 | negative value on error. 152 | */ 153 | S32 so_recv(SOCKET* sock, void* buf, U32 len, U32 timeout); 154 | 155 | #if XPRINTF == 1 156 | /** The macro xprintf expands to function _xprintf if the code is 157 | compiled with XPRINTF set to 1. 158 | \param data is standard printf arguments enclosed in parenthesis; 159 | thus you must use double parenthesis when using macro xprintf. 160 | */ 161 | #define xprintf(data) _xprintf data 162 | /** The example code and macro xprintf requires this function when the 163 | code is compiled with macro XPRINTF set to 1. 164 | \param fmt the format string. 165 | \param ... variable arguments. 166 | */ 167 | void _xprintf(const char* fmt, ...); 168 | #else 169 | #define xprintf(data) 170 | #endif 171 | 172 | #ifdef __cplusplus 173 | } 174 | #endif 175 | 176 | 177 | /** @} */ /* end group solib */ 178 | /** @} */ /* end group Examples */ 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /inc/AllocatorIntf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | * 11 | **************************************************************************** 12 | * HEADER 13 | * 14 | * $Id: AllocatorIntf.h 4914 2021-12-01 18:24:30Z wini $ 15 | * 16 | * COPYRIGHT: Real Time Logic LLC, 2014 17 | * 18 | * This software is copyrighted by and is the sole property of Real 19 | * Time Logic LLC. All rights, title, ownership, or other interests in 20 | * the software remain the property of Real Time Logic LLC. This 21 | * software may only be used in accordance with the terms and 22 | * conditions stipulated in the corresponding license agreement under 23 | * which the software has been supplied. Any unauthorized use, 24 | * duplication, transmission, distribution, or disclosure of this 25 | * software is expressly forbidden. 26 | * 27 | * This Copyright notice may not be removed or modified without prior 28 | * written consent of Real Time Logic LLC. 29 | * 30 | * Real Time Logic LLC. reserves the right to modify this software 31 | * without notice. 32 | * 33 | * http://realtimelogic.com 34 | **************************************************************************** 35 | * 36 | */ 37 | 38 | #ifndef __AllocatorIntf_h 39 | #define __AllocatorIntf_h 40 | 41 | #include 42 | #include 43 | 44 | #ifndef BA_API 45 | #define BA_API 46 | #endif 47 | 48 | 49 | struct AllocatorIntf; 50 | 51 | /** Malloc prototype. 52 | \param size the size required. The allocator can change the 53 | size to a size larger than the one requested. 54 | \sa AllocatorIntf::AllocatorIntf 55 | */ 56 | typedef void* (*AllocatorIntf_Malloc)(struct AllocatorIntf* o, size_t* size); 57 | 58 | /** Realloc prototype. 59 | \param size the size required. The allocator can change the 60 | size to a size larger than the one requested. 61 | \sa AllocatorIntf::AllocatorIntf 62 | */ 63 | typedef void* (*AllocatorIntf_Realloc)( 64 | struct AllocatorIntf* o, void* memblock, size_t* size); 65 | 66 | /** Free prototype. 67 | \sa AllocatorIntf::AllocatorIntf 68 | */ 69 | typedef void (*AllocatorIntf_Free)(struct AllocatorIntf* o, void* memblock); 70 | 71 | /** Memory allocation and deallocation Interface class. 72 | 73 | This abstract interface class is used by some of the Barracuda 74 | classes when allocating memory. The reason for using an interface 75 | class and not directly calling the global functions baMalloc(), 76 | baRealloc() and baFree() is to provide a finer control of 77 | allocated memory. For example, an implementation of the 78 | AllocatorIntf can work with blocks of memory allocated 79 | from static memory. Implementing realloc is optional and can be 80 | set to NULL if not implemented. 81 | */ 82 | typedef struct AllocatorIntf 83 | { 84 | #ifdef __cplusplus 85 | AllocatorIntf() {} 86 | /** Create an instance of a memory allocation class. 87 | This is an abstract base class and should, therefore, be sub-classed. 88 | \param malloc Pointer to memory allocation method. 89 | \param realloc Pointer to memory reallocation method. This 90 | method is optional and the argument can be set to NULL if not 91 | implemented. 92 | \param free Pointer to a memory deallocation method. 93 | */ 94 | AllocatorIntf(AllocatorIntf_Malloc malloc, 95 | AllocatorIntf_Realloc realloc, 96 | AllocatorIntf_Free free); 97 | 98 | /** Returns a pointer to a predefined AllocatorIntf class. The 99 | default implementation uses method baMalloc(), baRealloc() and 100 | baFree(). 101 | */ 102 | static AllocatorIntf* getDefault(void); 103 | 104 | /** Returns pointer to uninitialized newly-allocated space for 105 | an object of size "size", or NULL on error. 106 | \param size the size required. The allocator can change the 107 | size to a size larger than the one requested. 108 | */ 109 | void* malloc(size_t* size); 110 | void* malloc(size_t size) { return malloc(&size); } 111 | 112 | /** Returns pointer to newly-allocated space for an object of 113 | size "size", initialized, to minimum of old and new sizes, to 114 | existing contents of p (if non-null), or NULL on error. On 115 | success, old object deallocated; otherwise unchanged. 116 | */ 117 | void* realloc(void* p, size_t* size); 118 | void* realloc(void* p, size_t size) { return realloc(p, &size); } 119 | 120 | /** Deallocates space to which it points. 121 | */ 122 | void free(void* p); 123 | #endif 124 | AllocatorIntf_Malloc mallocCB; 125 | AllocatorIntf_Realloc reallocCB; /* optional */ 126 | AllocatorIntf_Free freeCB; 127 | } AllocatorIntf; 128 | 129 | #define AllocatorIntf_constructor(o, m, r, f) do { \ 130 | (o)->mallocCB=m; \ 131 | (o)->reallocCB=r; \ 132 | (o)->freeCB=f; \ 133 | } while(0) 134 | 135 | #define AllocatorIntf_malloc(o, size) (o)->mallocCB(o, size) 136 | #define AllocatorIntf_realloc(o, memblock, size) \ 137 | ((o)->reallocCB ? (o)->reallocCB(o,memblock,size) : 0) 138 | #define AllocatorIntf_free(o, memblock) (o)->freeCB(o,memblock) 139 | 140 | #ifdef __cplusplus 141 | extern "C" { 142 | #endif 143 | BA_API AllocatorIntf* AllocatorIntf_getDefault(void); 144 | 145 | /** Calls method malloc in the allocator to allocate storage space for 146 | a copy of str and then copies src to the allocated space. 147 | */ 148 | BA_API char* baStrdup2(struct AllocatorIntf* a, const char* str); 149 | 150 | #ifdef __cplusplus 151 | } 152 | inline AllocatorIntf::AllocatorIntf(AllocatorIntf_Malloc malloc, 153 | AllocatorIntf_Realloc realloc, 154 | AllocatorIntf_Free free) { 155 | AllocatorIntf_constructor(this, malloc,realloc,free); } 156 | inline AllocatorIntf* AllocatorIntf::getDefault(void) { 157 | return AllocatorIntf_getDefault(); } 158 | inline void* AllocatorIntf::malloc(size_t* size) { 159 | return AllocatorIntf_malloc(this, size); } 160 | inline void* AllocatorIntf::realloc(void* memblock, size_t* size) { 161 | return AllocatorIntf_realloc(this, memblock, size); } 162 | inline void AllocatorIntf::free(void* memblock) { 163 | AllocatorIntf_free(this, memblock); } 164 | #endif 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /VcMake/examples.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33213.308 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "m2mled", "m2mled.vcxproj", "{E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {75262908-FF79-4187-9902-34CD3A887CEB} = {75262908-FF79-4187-9902-34CD3A887CEB} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1", "test1.vcxproj", "{45F1316D-58EA-434C-90DD-286FCBA95F31}" 12 | ProjectSection(ProjectDependencies) = postProject 13 | {6991B964-4C52-4096-A2E9-F852355ACCCB} = {6991B964-4C52-4096-A2E9-F852355ACCCB} 14 | EndProjectSection 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "staticalloc", "staticalloc.vcxproj", "{A7EEDFC3-F122-4568-B804-BD16D8946A2A}" 17 | ProjectSection(ProjectDependencies) = postProject 18 | {13DF4164-3E75-49F3-A257-64F88265C0C0} = {13DF4164-3E75-49F3-A257-64F88265C0C0} 19 | EndProjectSection 20 | EndProject 21 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JDecoder", "JDecoder.vcxproj", "{75262908-FF79-4187-9902-34CD3A887CEB}" 22 | EndProject 23 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSON", "JSON.vcxproj", "{6991B964-4C52-4096-A2E9-F852355ACCCB}" 24 | EndProject 25 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ValFact", "ValFact.vcxproj", "{13DF4164-3E75-49F3-A257-64F88265C0C0}" 26 | EndProject 27 | Global 28 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 29 | Debug|Mixed Platforms = Debug|Mixed Platforms 30 | Debug|Win32 = Debug|Win32 31 | Debug|x64 = Debug|x64 32 | Release|Mixed Platforms = Release|Mixed Platforms 33 | Release|Win32 = Release|Win32 34 | Release|x64 = Release|x64 35 | EndGlobalSection 36 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 37 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 38 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Debug|Mixed Platforms.Build.0 = Debug|Win32 39 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Debug|Win32.ActiveCfg = Debug|Win32 40 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Debug|Win32.Build.0 = Debug|Win32 41 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Debug|x64.ActiveCfg = Debug|Win32 42 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Release|Mixed Platforms.ActiveCfg = Release|Win32 43 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Release|Mixed Platforms.Build.0 = Release|Win32 44 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Release|Win32.ActiveCfg = Release|Win32 45 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Release|Win32.Build.0 = Release|Win32 46 | {E3E3815A-82F3-4AC4-BDA1-4D744F7CBDFB}.Release|x64.ActiveCfg = Release|Win32 47 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 48 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Debug|Mixed Platforms.Build.0 = Debug|Win32 49 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Debug|Win32.ActiveCfg = Debug|Win32 50 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Debug|Win32.Build.0 = Debug|Win32 51 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Debug|x64.ActiveCfg = Debug|Win32 52 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Release|Mixed Platforms.ActiveCfg = Release|Win32 53 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Release|Mixed Platforms.Build.0 = Release|Win32 54 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Release|Win32.ActiveCfg = Release|Win32 55 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Release|Win32.Build.0 = Release|Win32 56 | {45F1316D-58EA-434C-90DD-286FCBA95F31}.Release|x64.ActiveCfg = Release|Win32 57 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 58 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 59 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Debug|Win32.ActiveCfg = Debug|Win32 60 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Debug|Win32.Build.0 = Debug|Win32 61 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Debug|x64.ActiveCfg = Debug|Win32 62 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 63 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Release|Mixed Platforms.Build.0 = Release|Win32 64 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Release|Win32.ActiveCfg = Release|Win32 65 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Release|Win32.Build.0 = Release|Win32 66 | {A7EEDFC3-F122-4568-B804-BD16D8946A2A}.Release|x64.ActiveCfg = Release|Win32 67 | {75262908-FF79-4187-9902-34CD3A887CEB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 68 | {75262908-FF79-4187-9902-34CD3A887CEB}.Debug|Mixed Platforms.Build.0 = Debug|Win32 69 | {75262908-FF79-4187-9902-34CD3A887CEB}.Debug|Win32.ActiveCfg = Debug|Win32 70 | {75262908-FF79-4187-9902-34CD3A887CEB}.Debug|Win32.Build.0 = Debug|Win32 71 | {75262908-FF79-4187-9902-34CD3A887CEB}.Debug|x64.ActiveCfg = Debug|Win32 72 | {75262908-FF79-4187-9902-34CD3A887CEB}.Release|Mixed Platforms.ActiveCfg = Release|Win32 73 | {75262908-FF79-4187-9902-34CD3A887CEB}.Release|Mixed Platforms.Build.0 = Release|Win32 74 | {75262908-FF79-4187-9902-34CD3A887CEB}.Release|Win32.ActiveCfg = Release|Win32 75 | {75262908-FF79-4187-9902-34CD3A887CEB}.Release|Win32.Build.0 = Release|Win32 76 | {75262908-FF79-4187-9902-34CD3A887CEB}.Release|x64.ActiveCfg = Release|Win32 77 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 78 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Debug|Mixed Platforms.Build.0 = Debug|Win32 79 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Debug|Win32.ActiveCfg = Debug|Win32 80 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Debug|Win32.Build.0 = Debug|Win32 81 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Debug|x64.ActiveCfg = Debug|Win32 82 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Release|Mixed Platforms.ActiveCfg = Release|Win32 83 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Release|Mixed Platforms.Build.0 = Release|Win32 84 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Release|Win32.ActiveCfg = Release|Win32 85 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Release|Win32.Build.0 = Release|Win32 86 | {6991B964-4C52-4096-A2E9-F852355ACCCB}.Release|x64.ActiveCfg = Release|Win32 87 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 88 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Debug|Mixed Platforms.Build.0 = Debug|Win32 89 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Debug|Win32.ActiveCfg = Debug|Win32 90 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Debug|Win32.Build.0 = Debug|Win32 91 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Debug|x64.ActiveCfg = Debug|Win32 92 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Release|Mixed Platforms.ActiveCfg = Release|Win32 93 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Release|Mixed Platforms.Build.0 = Release|Win32 94 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Release|Win32.ActiveCfg = Release|Win32 95 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Release|Win32.Build.0 = Release|Win32 96 | {13DF4164-3E75-49F3-A257-64F88265C0C0}.Release|x64.ActiveCfg = Release|Win32 97 | EndGlobalSection 98 | GlobalSection(SolutionProperties) = preSolution 99 | HideSolutionNode = FALSE 100 | EndGlobalSection 101 | GlobalSection(ExtensibilityGlobals) = postSolution 102 | SolutionGuid = {5CF7B18E-EF0A-437B-A67C-4AD67C0B143E} 103 | EndGlobalSection 104 | EndGlobal 105 | -------------------------------------------------------------------------------- /inc/JDecoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | * 11 | **************************************************************************** 12 | * HEADER 13 | * 14 | * $Id: JDecoder.h 4914 2021-12-01 18:24:30Z wini $ 15 | * 16 | * COPYRIGHT: Real Time Logic LLC, 2014 17 | * 18 | * This software is copyrighted by and is the sole property of Real 19 | * Time Logic LLC. All rights, title, ownership, or other interests in 20 | * the software remain the property of Real Time Logic LLC. This 21 | * software may only be used in accordance with the terms and 22 | * conditions stipulated in the corresponding license agreement under 23 | * which the software has been supplied. Any unauthorized use, 24 | * duplication, transmission, distribution, or disclosure of this 25 | * software is expressly forbidden. 26 | * 27 | * This Copyright notice may not be removed or modified without prior 28 | * written consent of Real Time Logic LLC. 29 | * 30 | * Real Time Logic LLC. reserves the right to modify this software 31 | * without notice. 32 | * 33 | * http://realtimelogic.com 34 | **************************************************************************** 35 | */ 36 | 37 | #ifndef __jdecode_h 38 | #define __jdecode_h 39 | 40 | #include 41 | 42 | /** @addtogroup JSONCB 43 | @{ 44 | */ 45 | 46 | #ifndef J_ALIGNMT 47 | #define J_ALIGNMT uintptr_t 48 | #endif 49 | #define J_POINTER_NOT_ALIGNED(p) (0 != ((uintptr_t)p & (sizeof(J_ALIGNMT)-1))) 50 | 51 | 52 | /** JDecoder Status 53 | */ 54 | typedef enum { 55 | /** Parsed data does not match the value tree that was created when 56 | method JDecoder::get was called 57 | */ 58 | JDecoderS_FormatErr = -100, 59 | 60 | /** Parsed data includes a member whose name is not in value tree. */ 61 | JDecoderS_NameNotFound, 62 | 63 | /** Received more array or object member values from parsed data than 64 | * found in value tree. 65 | */ 66 | JDecoderS_Overflow, 67 | 68 | /** Parsed string longer than buffer provided */ 69 | JDecoderS_StringOverflow, 70 | 71 | /** Incorrect use of '{', '}', '[', or '[' in JDecoder::get */ 72 | JDecoderS_Unbalanced, 73 | 74 | /** Received less array or object member values from parsed data than 75 | * found in value tree. 76 | */ 77 | JDecoderS_Underflow, 78 | 79 | /** Unkown error */ 80 | JDecoderS_Unknown, 81 | 82 | /** Memory buffer(s) provided in JDecoder constructor must be word aligned */ 83 | JDecoderS_BufNotAligned, 84 | 85 | /** A chained parser callback, provided via the 'X' format flag in 86 | * JDecoder::get, reported an error. 87 | */ 88 | JDecoderS_ChainedErr, 89 | 90 | /** OK, no errors 91 | */ 92 | JDecoderS_OK = 0 93 | } JDecoderS; 94 | 95 | 96 | /** Used internally in JDecoder for nested data structures */ 97 | typedef struct 98 | { 99 | U16 contIx; /* container (object or array) index */ 100 | U8 isObj; /* 1 if object, 0 if array */ 101 | } JDecoderStackNode; 102 | 103 | 104 | /** Used internally in JDecoder, where one instance represents one 105 | node in the pointer value tree. 106 | */ 107 | typedef struct 108 | { 109 | union 110 | { 111 | U8* b; 112 | S32* d; 113 | S64* l; 114 | #ifndef NO_DOUBLE 115 | double* f; 116 | #endif 117 | char* s; 118 | struct /* For obj/array */ 119 | { 120 | U16 firstIx; 121 | U16 lastIx; /* used via JDecoder_vget only */ 122 | } child; /* if t == container (object or array) */ 123 | JParserIntf* pIntf; /* for 'X' */ 124 | } u; 125 | const char* name; /* Member name, if parent is an object */ 126 | S32 sSize; /* Size (len+1) of s buffer ( if t == s ) */ 127 | U16 nextIx; 128 | U8 t; /* JVType */ 129 | } JDecoderV; 130 | 131 | 132 | /** JDecoder implements the parser callback API JParserIntf and builds 133 | a pointer value tree when JDecoder::get is called. The pointer 134 | value tree is used by the parser callback when the parser feeds the 135 | callback with parsed data. 136 | 137 | See the [JSON and UBJSON tutorial](@ref JDecoderUBJDecoder) for more 138 | information on using JDecoder. 139 | */ 140 | typedef struct JDecoder 141 | #ifdef __cplusplus 142 | : public JParserIntf 143 | { 144 | /** See JDecoder::get for details */ 145 | int vget(const char* fmt, va_list* argList); 146 | 147 | /** Build a pointer value tree that is used by the integrated 148 | parser callback function when the parser feeds elements to the 149 | JDecoder instance. 150 | 151 | \param fmt format flags: 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 |
JSON typeFormat flagC type
Number d S32*
Number l S64*
Number f double*
boolean b BaBool* or U8*
string s char**
Start object { n/a
End object } n/a
Start array [ n/a
End array ] n/a
N/A X JParserIntf*
165 | 166 | See the [JSON and UBJSON tutorial](@ref JDecoderUBJDecoder) for more 167 | information on using this method. 168 | 169 | \sa JD_MNUM 170 | \sa JD_MSTR 171 | \sa JD_ASTR 172 | \sa JEncoder::set 173 | */ 174 | int get(const char* fmt, ...); 175 | 176 | /** Create/initialize a JDecoder instance. 177 | 178 | \param buf is a pointer to a buffer used internally for memory 179 | storage when building the pointer value tree. The minimum size 180 | must be sizeof(JDecoderV) * N, where N is the number of format 181 | flags minus the end of array/object flags (] or }). 182 | 183 | \param bufSize the size of 'buf' 184 | 185 | \param extraStackLen is a non documented value and must be set to 0. 186 | */ 187 | JDecoder(U8* buf, int bufSize, int extraStackLen=0); 188 | #if 0 189 | } 190 | #endif 191 | #else 192 | { 193 | JParserIntf super; /* Inherits from JParserIntf */ 194 | #endif 195 | JDecoderS status; 196 | JParserIntf* pIntf; 197 | int startServiceLevel; 198 | U8* buf; 199 | int bufIx; 200 | int bufSize; 201 | int stacklen; 202 | JDecoderStackNode stack[JPARSER_STACK_LEN]; 203 | } JDecoder; 204 | 205 | 206 | /** JDecoder::get helper macro, used when setting a number pointer in an object. 207 | encoder.set("{d}", JD_MNUM(structval, membername)); 208 | */ 209 | #define JD_MNUM(o, m) #m, &(o)->m 210 | 211 | /** JDecoder::get helper macro, used when setting a string pointer in an object. 212 | encoder.set("{s}", JD_MSTR(structval, membername)); 213 | */ 214 | #define JD_MSTR(o, m) #m, &(o)->m, sizeof((o)->m) 215 | 216 | /** JDecoder::get helper macro, used when setting a string pointer in an array. 217 | encoder.set("[s]", JD_ASTR(structval, membername)); 218 | */ 219 | #define JD_ASTR(o, m) &(o)->m, sizeof((o)->m) 220 | 221 | #ifdef __cplusplus 222 | extern "C" { 223 | #endif 224 | 225 | int JDecoder_vget(JDecoder* o, const char* fmt, va_list* argList); 226 | int JDecoder_get(JDecoder* o, const char* fmt, ...); 227 | void JDecoder_constructor( 228 | JDecoder* o, U8* buf, int bufSize, int extraStackLen); 229 | #ifdef __cplusplus 230 | } 231 | inline int JDecoder::vget(const char* fmt, va_list* argList){ 232 | return JDecoder_vget(this, fmt, argList); 233 | } 234 | inline int JDecoder::get(const char* fmt, ...){ 235 | int stat; 236 | va_list argList; 237 | va_start(argList, fmt); 238 | stat = JDecoder_vget(this, fmt, &argList); 239 | va_end(argList); 240 | return stat; 241 | } 242 | inline JDecoder::JDecoder(U8* buf, int bufSize, int extraStackLen){ 243 | JDecoder_constructor(this, buf, bufSize, extraStackLen); 244 | } 245 | #endif 246 | 247 | /** @} */ /* end of JSONCB */ 248 | 249 | 250 | #endif 251 | -------------------------------------------------------------------------------- /examples/StaticAllocatorEx.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | **************************************************************************** 10 | * PROGRAM MODULE 11 | * 12 | * $Id$ 13 | * 14 | * COPYRIGHT: Real Time Logic LLC, 2014 15 | * 16 | * This software is copyrighted by and is the sole property of Real 17 | * Time Logic LLC. All rights, title, ownership, or other interests in 18 | * the software remain the property of Real Time Logic LLC. This 19 | * software may only be used in accordance with the terms and 20 | * conditions stipulated in the corresponding license agreement under 21 | * which the software has been supplied. Any unauthorized use, 22 | * duplication, transmission, distribution, or disclosure of this 23 | * software is expressly forbidden. 24 | * 25 | * This Copyright notice may not be removed or modified without prior 26 | * written consent of Real Time Logic LLC. 27 | * 28 | * Real Time Logic LLC. reserves the right to modify this software 29 | * without notice. 30 | * 31 | * http://realtimelogic.com 32 | **************************************************************************** 33 | * 34 | */ 35 | 36 | /* 37 | Static (buffer) allocator when using JParser and JParserValFact. 38 | For systems with no dynamic memory. 39 | */ 40 | 41 | #include 42 | #include 43 | 44 | 45 | /* JParser allocates one buffer only. 46 | */ 47 | 48 | #define MAX_STRING_LEN 1024 49 | 50 | class JParserAllocator : public AllocatorIntf 51 | { 52 | U8 buf[MAX_STRING_LEN]; 53 | 54 | static void* malloc(AllocatorIntf* o, size_t* size); 55 | static void* realloc(AllocatorIntf* o, void* memblock, size_t* size); 56 | static void free(AllocatorIntf* o, void* memblock); 57 | 58 | public: 59 | JParserAllocator(); 60 | }; 61 | 62 | 63 | void* JParserAllocator::malloc(AllocatorIntf* super, size_t* size) 64 | { 65 | JParserAllocator* o = (JParserAllocator*)super; 66 | return *size < MAX_STRING_LEN ? o->buf : 0; 67 | } 68 | 69 | 70 | //Called when the one and only string buffer must grow. 71 | void* JParserAllocator::realloc( 72 | AllocatorIntf* super, void* memblock, size_t* size) 73 | { 74 | JParserAllocator* o = (JParserAllocator*)super; 75 | baAssert(memblock == o->buf); 76 | return *size < MAX_STRING_LEN ? o->buf : 0; 77 | } 78 | 79 | 80 | //Called when JParser terminates 81 | void JParserAllocator::free(AllocatorIntf* super, void* memblock) 82 | { 83 | // Do nothing 84 | (void)super; 85 | (void)memblock; 86 | } 87 | 88 | JParserAllocator::JParserAllocator() : AllocatorIntf(malloc,realloc,free) 89 | { 90 | } 91 | 92 | 93 | /* JParserValFact allocator 94 | */ 95 | 96 | class JPValFactAllocator : public AllocatorIntf 97 | { 98 | U8* buf; 99 | size_t bufsize; 100 | size_t cursor; 101 | 102 | static void* malloc(AllocatorIntf* o, size_t* size); 103 | static void* realloc(AllocatorIntf* o, void* memblock, size_t* size); 104 | static void free(AllocatorIntf* o, void* memblock); 105 | 106 | public: 107 | JPValFactAllocator(void* buf, size_t bufsize); 108 | void reset() { cursor = 0; } 109 | }; 110 | 111 | 112 | void* JPValFactAllocator::malloc(AllocatorIntf* super, size_t* size) 113 | { 114 | JPValFactAllocator* o = (JPValFactAllocator*)super; 115 | if(*size + o->cursor < o->bufsize) 116 | { 117 | void* buf = o->buf+o->cursor; 118 | o->cursor += *size; 119 | return buf; 120 | } 121 | return 0; // Memory exhausted 122 | } 123 | 124 | 125 | //Not used by JParserValFact 126 | void* JPValFactAllocator::realloc( 127 | AllocatorIntf* super, void* memblock, size_t* size) 128 | { 129 | (void)super; 130 | (void)memblock; 131 | (void)size; 132 | baAssert(0); 133 | return 0; 134 | } 135 | 136 | 137 | // Called when JParserValFact terminates or when 138 | // JParserValFact::termFirstVal is called. 139 | void JPValFactAllocator::free(AllocatorIntf* super, void* memblock) 140 | { 141 | // Do nothing 142 | (void)super; 143 | (void)memblock; 144 | } 145 | 146 | JPValFactAllocator::JPValFactAllocator(void* b, size_t bsize) : 147 | AllocatorIntf(malloc,realloc,free) 148 | { 149 | buf =(U8*)b; 150 | bufsize = bsize; 151 | reset(); 152 | } 153 | 154 | 155 | 156 | typedef struct { 157 | S8 s8; 158 | char buf[20]; 159 | } T2; 160 | 161 | typedef struct { 162 | T2 member1; 163 | T2 member2; 164 | } T3; 165 | 166 | 167 | typedef struct { 168 | T3 x1; 169 | T3 x2; 170 | } T4; 171 | 172 | 173 | static void 174 | printPadChars(int pad) 175 | { 176 | int i; 177 | for(i = 0 ; i < pad; i++) 178 | putchar(' '); 179 | } 180 | 181 | 182 | static void 183 | printJVal(JVal* v, int recCntr) 184 | { 185 | for( ; v ; v = JVal_getNextElem(v) ) 186 | { 187 | const char* m; 188 | printPadChars(recCntr * 4); 189 | m = v->getName(); 190 | if(m) 191 | printf("%-10s : ", m); /* v is a struct member */ 192 | /* else: v is an array member */ 193 | 194 | switch(v->getType()) 195 | { 196 | case JVType_String: 197 | printf("%s\n", v->getString(0)); 198 | break; 199 | case JVType_Double: 200 | printf("%g\n", v->getDouble(0)); 201 | break; 202 | case JVType_Int: 203 | printf("%d\n", (int)v->getInt(0)); 204 | break; 205 | case JVType_Long: 206 | #ifdef _WIN32 207 | printf("%I64d\n", v->getLong(0)); 208 | #else 209 | /* Assume GCC */ 210 | printf("%lld\n", (long long)v->getLong(0)); 211 | #endif 212 | break; 213 | case JVType_Boolean: 214 | printf("%s\n", v->getBoolean(0) ? "true" : "false"); 215 | break; 216 | case JVType_Null: 217 | printf("NULL\n"); 218 | break; 219 | 220 | case JVType_Object: 221 | case JVType_Array: 222 | if(m) 223 | putchar('\n'); 224 | printJVal(v->getJ(0), recCntr+1); 225 | break; 226 | 227 | default: 228 | baAssert(0); 229 | } 230 | } 231 | } 232 | 233 | /* 64 bit requires more memory for pointers */ 234 | #ifdef __LP64__ 235 | #define XSIZE 2 236 | #else 237 | #define XSIZE 1 238 | #endif 239 | 240 | 241 | // Using lots of stack space since all objects are on the 'main' stack. 242 | int main() 243 | { 244 | char memberName[10]; 245 | U8 buf[1024]; 246 | T4 t4 = {{{1,"t4.one"}, {2,"t4.two"}},{{3,"t4.three"}, {4,"t4.four"}}}; 247 | 248 | U8 vBuf[380*XSIZE]; 249 | U8 dBuf[360]; 250 | JPValFactAllocator vAlloc(vBuf,sizeof(vBuf)); 251 | JPValFactAllocator dAlloc(dBuf,sizeof(dBuf)); 252 | JParserValFact vFact(&vAlloc, &dAlloc); 253 | JParserAllocator jpa; 254 | JParser parser(&vFact, memberName, sizeof(memberName),&jpa); 255 | 256 | BufPrint out; 257 | out.setBuf((char*)buf,sizeof(buf)); 258 | JErr err; 259 | JEncoder enc(&err, &out); 260 | 261 | T2* t4_x1_m1 = &t4.x1.member1; 262 | T2* t4_x1_m2 = &t4.x1.member2; 263 | T2* t4_x2_m1 = &t4.x2.member1; 264 | T2* t4_x2_m2 = &t4.x2.member2; 265 | 266 | for(int i=0 ; i < 2 ; i++) 267 | { 268 | if(enc.set("{{{ds}{ds}}{{ds}{ds}}}", 269 | "x1", 270 | "member1", 271 | JE_MEMBER(t4_x1_m1, s8), 272 | JE_MEMBER(t4_x1_m1, buf), 273 | "member2", 274 | JE_MEMBER(t4_x1_m2, s8), 275 | JE_MEMBER(t4_x1_m2, buf), 276 | "x2", 277 | "member1", 278 | JE_MEMBER(t4_x2_m1, s8), 279 | JE_MEMBER(t4_x2_m1, buf), 280 | "member2", 281 | JE_MEMBER(t4_x2_m2, s8), 282 | JE_MEMBER(t4_x2_m2, buf))) 283 | return 1; // Failed 284 | 285 | if(parser.parse((U8*)out.buf, out.cursor) != 1) 286 | return 1; //Failed 287 | 288 | enc.commit(); // Ready for next object 289 | 290 | printf("-----------------------------\n"); 291 | printJVal(vFact.getFirstVal(), 0); 292 | 293 | /* Must reset JParserValFact. Note: termFirstVal calls our 294 | * allocator::free, which is not doing anything. 295 | */ 296 | vFact.termFirstVal(); 297 | //Make allocators ready for next object 298 | vAlloc.reset(); 299 | dAlloc.reset(); 300 | } 301 | 302 | printf("OK\n"); 303 | return 0; 304 | } 305 | -------------------------------------------------------------------------------- /test/test1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * SharkSSL Embedded SSL/TLS Stack 10 | **************************************************************************** 11 | * PROGRAM MODULE 12 | * 13 | * $Id$ 14 | * 15 | * COPYRIGHT: Real Time Logic LLC, 2014 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | 37 | #include 38 | #include 39 | 40 | typedef struct { 41 | S32 s32Var; 42 | S64 s64Var; 43 | char buf[20]; 44 | double dVar; 45 | } T1; 46 | 47 | typedef struct { 48 | S8 s8; 49 | char buf[20]; 50 | } T2; 51 | 52 | typedef struct { 53 | T2 member1; 54 | T2 member2; 55 | } T3; 56 | 57 | 58 | typedef struct { 59 | T3 x1; 60 | T3 x2; 61 | } T4; 62 | 63 | JParser* p; 64 | 65 | 66 | 67 | int 68 | write2file(const char* fn, void* data, int len) 69 | { 70 | FILE* fp = fopen(fn,"wb"); 71 | if(!fp) 72 | return -1; 73 | fwrite(data, 1, len, fp); 74 | fclose(fp); 75 | return 0; 76 | } 77 | 78 | 79 | int parse(const char* fn) 80 | { 81 | size_t size; 82 | U8 buf[1024]; 83 | FILE* fp = fopen(fn,"rb"); 84 | if(!fp) 85 | return -1; 86 | size=fread(buf, 1, sizeof(buf), fp); 87 | fclose(fp); 88 | if(size == 0) 89 | return -1; 90 | if(p->parse(buf, size) != 1 || p->getStatus() != JParsStat_DoneEOS) 91 | { 92 | printf("Parse err\n"); 93 | return -1; 94 | } 95 | return 0; 96 | } 97 | 98 | 99 | 100 | /* Parser callback */ 101 | static int 102 | buildValCB(JParserIntf* super, JParserVal* v, int recLevel) 103 | { 104 | int i; 105 | for(i=0 ; i < recLevel ; i++) putchar('\t'); 106 | if(*v->memberName) /* if parent is an object */ 107 | printf("Name: %s, ", v->memberName); 108 | switch(v->t) 109 | { 110 | case JParserT_Boolean: 111 | printf("Boolean %s",v->v.b ? "TRUE" : "FALSE"); 112 | break; 113 | case JParserT_Double: 114 | printf("Float64 %f",v->v.f); 115 | break; 116 | case JParserT_Int: 117 | printf("Int32 %d (%X)",(unsigned int)v->v.d,(unsigned int)v->v.d); 118 | break; 119 | case JParserT_Long: 120 | #ifdef _WIN32 121 | printf("Int64 %I64d (%I64X)",v->v.l,v->v.l); 122 | #else 123 | printf("Int64 %lld (%llX)",(long long)v->v.l,(long long)v->v.l); 124 | #endif 125 | break; 126 | 127 | case JParserT_Null: 128 | printf("Null"); 129 | break; 130 | 131 | case JParserT_String: 132 | printf("String: "); 133 | printf("%s",v->v.s); 134 | break; 135 | 136 | case JParserT_BeginObject: 137 | printf("BeginObject: level: %d",recLevel); 138 | break; 139 | case JParserT_BeginArray: 140 | printf("BeginArray: level: %d",recLevel); 141 | break; 142 | case JParserT_EndObject: 143 | printf("EndObject"); 144 | break; 145 | case JParserT_EndArray: 146 | printf("EndArray"); 147 | break; 148 | 149 | default: 150 | baAssert(0); 151 | 152 | } 153 | printf("\n"); 154 | return 0; 155 | } 156 | 157 | 158 | T1 t1Out = { 159 | 1234556335, 160 | 6434523484939242478, 161 | "hello", 162 | 1.2345 163 | }; 164 | 165 | 166 | T2 t2Out[2] = {{125,"Hello"}, {-125,"World"}}; 167 | T3 t3Out = {{1,"t3.one"}, {2,"t3.two"}}; 168 | T4 t4Out = {{{1,"t4.one"}, {2,"t4.two"}},{{3,"t4.three"}, {4,"t4.four"}}}; 169 | 170 | T1 t1In; 171 | T2 t2In[2]; 172 | T3 t3In; 173 | T4 t4In; 174 | 175 | 176 | 177 | int main() 178 | { 179 | static char memberName[10]; 180 | 181 | static U8 buf[1024]; 182 | 183 | T2* t3_m1 = &t3Out.member1; 184 | T2* t3_m2 = &t3Out.member2; 185 | 186 | T2* t4_x1_m1 = &t4Out.x1.member1; 187 | T2* t4_x1_m2 = &t4Out.x1.member2; 188 | T2* t4_x2_m1 = &t4Out.x2.member1; 189 | T2* t4_x2_m2 = &t4Out.x2.member2; 190 | 191 | JParserIntf pintf(buildValCB); 192 | 193 | JDecoder dec(buf, sizeof(buf)); 194 | JParser parser(&dec, memberName, sizeof(memberName), AllocatorIntf_getDefault()); 195 | p = &parser; 196 | 197 | memset(&t1In, 0, sizeof(t1In)); 198 | memset(&t2In, 0, sizeof(t2In)); 199 | memset(&t3In, 0, sizeof(t3In)); 200 | memset(&t4In, 0, sizeof(t4In)); 201 | 202 | BufPrint out; 203 | out.setBuf((char*)buf,sizeof(buf)); 204 | JErr err; 205 | JEncoder enc(&err, &out); 206 | 207 | if(enc.set("{dlsf}", 208 | JE_MEMBER(&t1Out, s32Var), 209 | JE_MEMBER(&t1Out, s64Var), 210 | JE_MEMBER(&t1Out, buf), 211 | JE_MEMBER(&t1Out, dVar))) 212 | return 1; 213 | enc.commit(); 214 | write2file("t1.json", buf, out.cursor); 215 | out.erase(); 216 | 217 | if(dec.get("{dlsf}", 218 | JD_MNUM(&t1In, s32Var), 219 | JD_MNUM(&t1In, s64Var), 220 | JD_MSTR(&t1In, buf), 221 | JD_MNUM(&t1In, dVar))) 222 | return 1; 223 | if(parse("t1.json")) 224 | return 1; 225 | if( memcmp(&t1Out, &t1In, sizeof(t1In)) ) 226 | return 1; 227 | 228 | if(enc.set("[{ds}{ds}]", 229 | JE_MEMBER(&t2Out[0], s8), 230 | JE_MEMBER(&t2Out[0], buf), 231 | JE_MEMBER(&t2Out[1], s8), 232 | JE_MEMBER(&t2Out[1], buf))) 233 | return 1; 234 | enc.commit(); 235 | write2file("t2.json", buf, out.cursor); 236 | out.erase(); 237 | 238 | if(dec.get("[{ds}{ds}]", 239 | JD_MNUM(&t2In[0], s8), 240 | JD_MSTR(&t2In[0], buf), 241 | JD_MNUM(&t2In[1], s8), 242 | JD_MSTR(&t2In[1], buf))) 243 | return 1; 244 | if(parse("t2.json")) 245 | return 1; 246 | if( memcmp(&t2Out, &t2In, sizeof(t2In)) ) 247 | return 1; 248 | 249 | if(enc.set("{{ds}{ds}}", 250 | "member1", 251 | JE_MEMBER(t3_m1, s8), 252 | JE_MEMBER(t3_m1, buf), 253 | "member2", 254 | JE_MEMBER(t3_m2, s8), 255 | JE_MEMBER(t3_m2, buf))) 256 | return 1; 257 | enc.commit(); 258 | write2file("t3.json", buf, out.cursor); 259 | out.erase(); 260 | 261 | t3_m1 = &t3In.member1; 262 | t3_m2 = &t3In.member2; 263 | if(dec.get("{{ds}{ds}}", 264 | "member1", 265 | JD_MNUM(t3_m1, s8), 266 | JD_MSTR(t3_m1, buf), 267 | "member2", 268 | JD_MNUM(t3_m2, s8), 269 | JD_MSTR(t3_m2, buf))) 270 | return 1; 271 | if(parse("t3.json")) 272 | return 1; 273 | if( memcmp(&t3Out, &t3In, sizeof(t3In)) ) 274 | return 1; 275 | 276 | if(enc.set("{{{ds}{ds}}{{ds}{ds}}}", 277 | "x1", 278 | "member1", 279 | JE_MEMBER(t4_x1_m1, s8), 280 | JE_MEMBER(t4_x1_m1, buf), 281 | "member2", 282 | JE_MEMBER(t4_x1_m2, s8), 283 | JE_MEMBER(t4_x1_m2, buf), 284 | "x2", 285 | "member1", 286 | JE_MEMBER(t4_x2_m1, s8), 287 | JE_MEMBER(t4_x2_m1, buf), 288 | "member2", 289 | JE_MEMBER(t4_x2_m2, s8), 290 | JE_MEMBER(t4_x2_m2, buf))) 291 | return 1; 292 | enc.commit(); 293 | write2file("t4.json", buf, out.cursor); 294 | out.erase(); 295 | 296 | t4_x1_m1 = &t4In.x1.member1; 297 | t4_x1_m2 = &t4In.x1.member2; 298 | t4_x2_m1 = &t4In.x2.member1; 299 | t4_x2_m2 = &t4In.x2.member2; 300 | 301 | if(dec.get("{{{ds}{ds}}{{ds}{ds}}}", 302 | "x1", 303 | "member1", 304 | JD_MNUM(t4_x1_m1, s8), 305 | JD_MSTR(t4_x1_m1, buf), 306 | "member2", 307 | JD_MNUM(t4_x1_m2, s8), 308 | JD_MSTR(t4_x1_m2, buf), 309 | "x2", 310 | "member1", 311 | JD_MNUM(t4_x2_m1, s8), 312 | JD_MSTR(t4_x2_m1, buf), 313 | "member2", 314 | JD_MNUM(t4_x2_m2, s8), 315 | JD_MSTR(t4_x2_m2, buf))) 316 | return 1; 317 | if(parse("t4.json")) 318 | return 1; 319 | if( memcmp(&t4Out, &t4In, sizeof(t4In)) ) 320 | return 1; 321 | 322 | if(dec.get("{{X}{X}}", 323 | "x1", 324 | &pintf, 325 | "x2", 326 | &pintf)) 327 | return 1; 328 | 329 | if(parse("t4.json")) 330 | return 1; 331 | 332 | 333 | enc.beginObject(); 334 | enc.setName("array"); 335 | enc.beginArray(); 336 | for(int i = 0 ; i < 20 ; i++) 337 | enc.setInt(1+i*10); 338 | enc.endArray(); 339 | if(enc.endObject()) 340 | return 1; 341 | write2file("array.json", buf, out.cursor); 342 | 343 | 344 | if(dec.get("{[X]}", 345 | "array", 346 | &pintf)) 347 | return 1; 348 | if(parse("array.json")) 349 | return 1; 350 | 351 | printf("\n\nOK\n"); 352 | return 0; 353 | } 354 | -------------------------------------------------------------------------------- /src/JDecoder.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | **************************************************************************** 10 | * PROGRAM MODULE 11 | * 12 | * $Id: JDecoder.c 4914 2021-12-01 18:24:30Z wini $ 13 | * 14 | * COPYRIGHT: Real Time Logic LLC, 2014 15 | * 16 | * This software is copyrighted by and is the sole property of Real 17 | * Time Logic LLC. All rights, title, ownership, or other interests in 18 | * the software remain the property of Real Time Logic LLC. This 19 | * software may only be used in accordance with the terms and 20 | * conditions stipulated in the corresponding license agreement under 21 | * which the software has been supplied. Any unauthorized use, 22 | * duplication, transmission, distribution, or disclosure of this 23 | * software is expressly forbidden. 24 | * 25 | * This Copyright notice may not be removed or modified without prior 26 | * written consent of Real Time Logic LLC. 27 | * 28 | * Real Time Logic LLC. reserves the right to modify this software 29 | * without notice. 30 | * 31 | * http://realtimelogic.com 32 | **************************************************************************** 33 | 34 | */ 35 | 36 | #include "JDecoder.h" 37 | #include 38 | 39 | #define JDecoderV_val2Ix(o, val) (U16)(((U8*)val) - o->buf) 40 | #define JDecoderV_ix2Val(o, ix) (JDecoderV*)(o->buf + ix) 41 | 42 | 43 | static int 44 | JDecoder_setStatus(JDecoder* o, JDecoderS s) 45 | { 46 | o->status = s; 47 | return -1; 48 | } 49 | 50 | 51 | static int 52 | JDecoder_buildValCB(JParserIntf* super, JParserVal* v, int reclevel) 53 | { 54 | JDecoderV* dvp; /* parent */ 55 | JDecoderV* dv; /* child */ 56 | JDecoder* o = (JDecoder*)super; 57 | JDecoderStackNode* sn; 58 | int len; 59 | if(o->status) 60 | return o->status; 61 | if(o->pIntf) 62 | { 63 | baAssert(reclevel >= o->startServiceLevel); 64 | if(JParserIntf_serviceCB(o->pIntf, v, reclevel - o->startServiceLevel)) 65 | return JDecoder_setStatus(o, JDecoderS_ChainedErr); 66 | if((v->t == JParserT_EndObject || v->t == JParserT_EndArray) && 67 | reclevel == o->startServiceLevel) 68 | { 69 | o->pIntf = 0; 70 | } 71 | return 0; 72 | } 73 | if(v->t == JParserT_EndObject || v->t == JParserT_EndArray) 74 | { 75 | sn = o->stack + reclevel; 76 | dvp = JDecoderV_ix2Val(o, sn->contIx); 77 | if(dvp->u.child.firstIx) 78 | return JDecoder_setStatus(o, JDecoderS_Overflow); 79 | return 0; 80 | } 81 | else 82 | { 83 | if( ! reclevel ) 84 | { 85 | baAssert(v->t == JParserT_BeginObject || v->t == JParserT_BeginArray); 86 | return 0; 87 | } 88 | sn = o->stack + reclevel - 1; 89 | dvp = JDecoderV_ix2Val(o, sn->contIx); /* parent */ 90 | if( ! dvp->u.child.firstIx ) 91 | return JDecoder_setStatus(o, JDecoderS_Underflow); 92 | } 93 | dv = JDecoderV_ix2Val(o, dvp->u.child.firstIx); /* first child */ 94 | if(*v->memberName) /* if member in object */ 95 | { 96 | baAssert(sn->isObj); 97 | dvp=0; 98 | while( strcmp(v->memberName, dv->name) ) 99 | { 100 | if( ! dv->nextIx ) 101 | return JDecoder_setStatus(o, JDecoderS_NameNotFound); 102 | dvp = dv; 103 | dv = JDecoderV_ix2Val(o, dv->nextIx); 104 | } 105 | } 106 | else 107 | { 108 | baAssert( ! sn->isObj || reclevel == 0 ); 109 | } 110 | switch(v->t) 111 | { 112 | case JParserT_BeginObject: 113 | case JParserT_BeginArray: 114 | if(dv->t != v->t) 115 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 116 | baAssert(reclevel < o->stacklen); 117 | if(dv->u.child.firstIx) 118 | { 119 | JDecoderV* child = JDecoderV_ix2Val(o, dv->u.child.firstIx); 120 | if(child->t == 'X') 121 | { 122 | o->pIntf = child->u.pIntf; 123 | o->startServiceLevel = reclevel; 124 | if(JParserIntf_serviceCB(o->pIntf, v, 0)) 125 | return JDecoder_setStatus(o, JDecoderS_ChainedErr); 126 | } 127 | } 128 | o->stack[reclevel].contIx = JDecoderV_val2Ix(o, dv); 129 | o->stack[reclevel].isObj = v->t == JParserT_BeginObject; 130 | break; 131 | 132 | case JParserT_Boolean: 133 | if(dv->t != JParserT_Boolean) 134 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 135 | *dv->u.b = v->v.b; 136 | break; 137 | 138 | #ifdef NO_DOUBLE 139 | case JParserT_Double: 140 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 141 | #else 142 | case JParserT_Double: 143 | if(dv->t == JParserT_Double) 144 | *dv->u.f = (double)v->v.f; 145 | else 146 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 147 | break; 148 | 149 | #endif 150 | case JParserT_Int: 151 | if(dv->t == JParserT_Int) 152 | *dv->u.d = v->v.d; 153 | else if(dv->t == JParserT_Long) 154 | *dv->u.l = v->v.d; 155 | #ifndef NO_DOUBLE 156 | else if(dv->t == JParserT_Double) 157 | *dv->u.f = v->v.d; 158 | #endif 159 | else 160 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 161 | break; 162 | 163 | case JParserT_Long: 164 | if(dv->t != JParserT_Long) 165 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 166 | *dv->u.l = v->v.l; 167 | break; 168 | 169 | case JParserT_Null: 170 | if(dv->t != JParserT_String) 171 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 172 | *dv->u.s = 0; 173 | break; 174 | 175 | case JParserT_String: /* Fall through */ 176 | len = strlen(v->v.s); 177 | if( (len + 1) >= dv->sSize) 178 | return JDecoder_setStatus(o, JDecoderS_StringOverflow); 179 | strcpy(dv->u.s, v->v.s); 180 | break; 181 | 182 | default: 183 | baAssert(0); 184 | } 185 | 186 | /* unlink 'dv' */ 187 | if(*v->memberName) 188 | { 189 | if(dvp) 190 | dvp->nextIx = dv->nextIx; 191 | else 192 | { 193 | dvp = JDecoderV_ix2Val(o, sn->contIx); /* parent */ 194 | dvp->u.child.firstIx = dv->nextIx; 195 | } 196 | } 197 | else 198 | { 199 | dvp->u.child.firstIx = dv->nextIx; 200 | } 201 | return 0; 202 | } 203 | 204 | 205 | static int 206 | JDecoder_expandBuf(JDecoder* o) 207 | { 208 | (void)o; 209 | return -1; /* not implemented */ 210 | } 211 | 212 | 213 | static void 214 | JDecoder_link(JDecoder* o, JDecoderStackNode* sn, JDecoderV* v) 215 | { 216 | JDecoderV* parent = JDecoderV_ix2Val(o, sn->contIx); 217 | baAssert(parent->t == '{' || parent->t == '['); 218 | if(parent->u.child.firstIx) 219 | { 220 | JDecoderV* vtmp = JDecoderV_ix2Val(o, parent->u.child.lastIx); 221 | parent->u.child.lastIx = vtmp->nextIx = JDecoderV_val2Ix(o,v); 222 | } 223 | else 224 | parent->u.child.firstIx = parent->u.child.lastIx = JDecoderV_val2Ix(o,v); 225 | } 226 | 227 | 228 | 229 | int 230 | JDecoder_vget(JDecoder* o, const char* fmt, va_list* argList) 231 | { 232 | int stackIx = -1; 233 | JDecoderV* v; 234 | JDecoderStackNode* sn = o->stack; 235 | o->status = JDecoderS_OK; 236 | o->pIntf=0; 237 | o->bufIx=0; 238 | 239 | if(J_POINTER_NOT_ALIGNED(o->buf)) 240 | return JDecoder_setStatus(o, JDecoderS_BufNotAligned); 241 | 242 | if(*fmt != '{' && *fmt != '[') 243 | return JDecoder_setStatus(o, JDecoderS_Unbalanced); 244 | sn->isObj = *fmt == '{'; 245 | while(*fmt) 246 | { 247 | if(*fmt == '}' || *fmt == ']') 248 | { 249 | if(stackIx == 0) 250 | { 251 | if(fmt[1]) 252 | return JDecoder_setStatus(o, JDecoderS_Unbalanced); 253 | break; 254 | } 255 | stackIx--; 256 | sn--; 257 | fmt++; 258 | continue; 259 | } 260 | v = JDecoderV_ix2Val(o, o->bufIx); 261 | o->bufIx += sizeof(JDecoderV); 262 | if(o->bufIx >= o->bufSize) 263 | { 264 | if(stackIx == 0 && (*fmt == '}' || *fmt == ']')) 265 | return JDecoder_setStatus(o, JDecoderS_Unbalanced); 266 | if(JDecoder_expandBuf(o)) 267 | return -1; 268 | sn = o->stack+stackIx; 269 | } 270 | v->t = *fmt; 271 | v->name = stackIx >= 0 && sn->isObj && *fmt != 'X' ? 272 | va_arg(*argList, const char*) : ""; 273 | v->nextIx = 0; 274 | switch(*fmt) 275 | { 276 | case 'X': /* A child JParserIntf_Service */ 277 | if(fmt[1] != '}' && fmt[1] != ']') 278 | return JDecoder_setStatus(o, JDecoderS_FormatErr); 279 | case 'b': /* bool */ 280 | case 'd': /* d */ 281 | case 'l': /* l */ 282 | case 'f': /* f */ 283 | case 's': /* s */ 284 | v->u.b = va_arg(*argList, U8*); 285 | if(v->t == 's') 286 | v->sSize = (S32)va_arg(*argList, size_t); 287 | JDecoder_link(o, sn, v); 288 | break; 289 | 290 | case '{': 291 | case '[': 292 | if(stackIx >= 0) 293 | JDecoder_link(o, sn, v); 294 | if(++stackIx >= o->stacklen) 295 | return JDecoder_setStatus(o, JDecoderS_Overflow); 296 | v->u.child.firstIx = 0; 297 | sn = o->stack+stackIx; 298 | sn->isObj = *fmt == '{'; 299 | sn->contIx = JDecoderV_val2Ix(o, v); 300 | break; 301 | 302 | default: 303 | return JDecoder_setStatus(o, JDecoderS_Unknown); 304 | } 305 | fmt++; 306 | } 307 | if( stackIx || fmt[1] ) 308 | return JDecoder_setStatus(o, JDecoderS_Unbalanced); 309 | return 0; 310 | } 311 | 312 | 313 | 314 | int 315 | JDecoder_get(JDecoder* o, const char* fmt, ...) 316 | { 317 | int status; 318 | va_list argList; 319 | va_start(argList, fmt); 320 | status = JDecoder_vget(o, fmt, &argList); 321 | va_end(argList); 322 | return status; 323 | } 324 | 325 | 326 | void 327 | JDecoder_constructor(JDecoder* o, U8* buf, int bufSize, int extraStackLen) 328 | { 329 | JParserIntf_constructor((JParserIntf*)o, JDecoder_buildValCB); 330 | o->buf=buf; 331 | o->bufSize = bufSize; 332 | o->stacklen = JPARSER_STACK_LEN + extraStackLen; 333 | } 334 | -------------------------------------------------------------------------------- /inc/JEncoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | * 11 | **************************************************************************** 12 | * HEADER 13 | * 14 | * $Id: JEncoder.h 5029 2022-01-16 21:32:09Z wini $ 15 | * 16 | * COPYRIGHT: Real Time Logic LLC, 2006-2022 17 | * 18 | * This software is copyrighted by and is the sole property of Real 19 | * Time Logic LLC. All rights, title, ownership, or other interests in 20 | * the software remain the property of Real Time Logic LLC. This 21 | * software may only be used in accordance with the terms and 22 | * conditions stipulated in the corresponding license agreement under 23 | * which the software has been supplied. Any unauthorized use, 24 | * duplication, transmission, distribution, or disclosure of this 25 | * software is expressly forbidden. 26 | * 27 | * This Copyright notice may not be removed or modified without prior 28 | * written consent of Real Time Logic LLC. 29 | * 30 | * Real Time Logic LLC. reserves the right to modify this software 31 | * without notice. 32 | * 33 | * http://realtimelogic.com 34 | **************************************************************************** 35 | * 36 | */ 37 | 38 | #ifndef __JEncoder_h 39 | #define __JEncoder_h 40 | 41 | #include "JVal.h" 42 | #include "BufPrint.h" 43 | 44 | /** @addtogroup JSONRef 45 | @{ 46 | */ 47 | 48 | 49 | /** The JEncoder can serialize a JSON JVAL syntax tree to the JSON 50 | text format. The JEncoder can also be used for assembling JSON 51 | text from calling the primitive methods in this class. 52 | 53 | Example: 54 | \code 55 | JErr err; 56 | char buf[40]; //Must be sufficiently large for the JSON string 57 | BufPrint jBuf(buf,sizeof(buf)); 58 | JEncoder jEnc(&err,&jBuf); 59 | jEnc.set("{d}", "The number of the day is", 5); 60 | //jBuf.buf == buf 61 | buf[jBuf.cursor]=0; // So we can use printf 62 | printf("%s\n",buf); // Prints: {"The number of the day is":5} 63 | \endcode 64 | */ 65 | typedef struct JEncoder 66 | { 67 | #ifdef __cplusplus 68 | /** Create an instance of the JEncoder class. 69 | */ 70 | JEncoder(JErr* err, BufPrint* out); 71 | ~JEncoder(); 72 | 73 | /** Format an integer value. 74 | */ 75 | int setInt(S32 val); 76 | 77 | /** Format a long integer value. 78 | */ 79 | int setLong(S64 val); 80 | #ifndef NO_DOUBLE 81 | 82 | /** Format a double value. 83 | */ 84 | int setDouble(double val); 85 | #endif 86 | 87 | /** Format a string value. The method is internally using 88 | BufPrint::jsonString. 89 | */ 90 | int setString(const char* val); 91 | 92 | /** Encode and emit (binary) data using B64 encoding 93 | */ 94 | int b64enc(const void* source, S32 slen); 95 | 96 | /** Converts (according to format 'fmt') and writes to stream. 97 | The method is internally using BufPrint::vprintf, which 98 | means that you can use the specialized format flags such as 99 | %%j. 100 | */ 101 | int fmtString(const char* fmt,...); 102 | 103 | /** Equivalent to fmtString with variable argument list replaced 104 | by argList. 105 | */ 106 | int vFmtString(const char* fmt,va_list argList); 107 | 108 | /** Format a boolean value. 109 | */ 110 | int setBoolean(bool val); 111 | 112 | /** Set a JSON null value. 113 | */ 114 | int setNull(); 115 | 116 | /** Format a node or a tree of JVal nodes. 117 | */ 118 | int setJV(struct JVal* val, bool iterateNext=false); 119 | 120 | /** Encode/serialize C structs/data to JSON using formatted output. 121 | 122 | The set method works in a similar fashion to the ANSII C 123 | function printf; thus, it performs formatted output conversion. 124 | 125 | The method internally uses the 'setXXX' methods in this class 126 | for setting the actual value(s), where XXX is setInt, setLong, etc.. The 127 | following table shows the relationship between the format flags and 128 | the JSON value: 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 |
JSON typeFormat flagC typeMethod
Number d S32JVal::setInt
Number l S64JVal::setLong
Number f doubleJVal::setDouble
boolean b BaBoolJVal::setBoolean
string s const char*JVal::setString
Any type J JVal*All methods
Start object { n/aJVal::beginObject
End object } n/aJVal::endObject
Start array [ n/aJVal::beginArray
End array ] n/aJVal::endArray
JVal[size] A Array of JValAll setXXX methods
156 | 157 | \sa JE_MEMBER 158 | \sa JVal::get 159 | \sa JDecoder::get 160 | */ 161 | int set(const char* fmt, ...); 162 | 163 | /** Set the member name before calling any of the set members 164 | if formatting an object. 165 | \param name the object member name. 166 | \sa beginObject 167 | */ 168 | int setName(const char* name); 169 | 170 | /** Begin object formatting. 171 | 172 | All calls to the the set members must be proceeded by 173 | a call to JEncoder::name after you call 174 | beginObject. This condition is terminated if you call 175 | JEncoder::endObject or call 176 | JEncoder::beginArray. 177 | */ 178 | 179 | /** Begin object formatting 180 | */ 181 | int beginObject(); 182 | 183 | /** End object formatting. 184 | */ 185 | int endObject(); 186 | 187 | /** Begin array formatting. 188 | */ 189 | int beginArray(); 190 | 191 | /** End array formatting. 192 | */ 193 | int endArray(); 194 | 195 | /** Returns the JErr object. 196 | */ 197 | JErr* getErr(); 198 | 199 | /** Flush JEncoder data to the output stream. 200 | */ 201 | int flush(); 202 | 203 | /** Calls flush and enables the construction of a new object 204 | */ 205 | int commit(); 206 | 207 | /** Fetch the internal BufPrint object. 208 | */ 209 | BufPrint* getBufPrint(); 210 | 211 | #endif 212 | JErr* err; 213 | struct 214 | { 215 | S32 level; 216 | U8 data[64]; 217 | }objectStack; 218 | BufPrint* out; 219 | BaBool objectMember; 220 | BaBool startNewObj; 221 | } JEncoder; 222 | #ifdef __cplusplus 223 | extern "C" { 224 | #endif 225 | BA_API void JEncoder_constructor(JEncoder* o, JErr* err, BufPrint* out); 226 | #define JEncoder_destructor(o) JEncoder_flush(o) 227 | BA_API int JEncoder_flush(JEncoder* o); 228 | BA_API int JEncoder_commit(JEncoder* o); 229 | #define JEncoder_getErr(o) (o)->err 230 | BA_API int JEncoder_setInt(JEncoder* o, S32 val); 231 | BA_API int JEncoder_setLong(JEncoder* o, S64 val); 232 | #ifdef NO_DOUBLE 233 | #define JEncoder_setDouble JEncoder_setInt 234 | #else 235 | BA_API int JEncoder_setDouble(JEncoder* o, double val); 236 | #endif 237 | 238 | BA_API int JEncoder_fmtString(JEncoder* o, const char* fmt,...); 239 | BA_API int JEncoder_vFmtString( 240 | JEncoder* o, const char* fmt,va_list argList); 241 | BA_API int JEncoder_setString(JEncoder* o, const char* val); 242 | BA_API int JEncoder_b64enc(JEncoder* o, const void* source, S32 slen); 243 | BA_API int JEncoder_setBoolean(JEncoder* o, BaBool val); 244 | BA_API int JEncoder_setNull(JEncoder* o); 245 | BA_API int JEncoder_setJV( 246 | JEncoder* o, struct JVal* val, BaBool iterateNext); 247 | BA_API int JEncoder_vSetJV( 248 | JEncoder* o,const char** fmt,va_list* argList); 249 | BA_API int JEncoder_set(JEncoder* o, const char* fmt, ...); 250 | BA_API int JEncoder_setName(JEncoder* o, const char* name); 251 | BA_API int JEncoder_beginObject(JEncoder* o); 252 | BA_API int JEncoder_endObject(JEncoder* o); 253 | BA_API int JEncoder_beginArray(JEncoder* o); 254 | BA_API int JEncoder_endArray(JEncoder* o); 255 | #define JEncoder_getBufPrint(o) (o)->out 256 | #ifdef __cplusplus 257 | } 258 | inline JEncoder::JEncoder(JErr* err, BufPrint* out) { 259 | JEncoder_constructor(this,err, out); } 260 | inline JEncoder::~JEncoder() { 261 | JEncoder_destructor(this); } 262 | inline int JEncoder::setInt(S32 val) { 263 | return JEncoder_setInt(this, val); } 264 | inline int JEncoder::setLong(S64 val) { 265 | return JEncoder_setLong(this, val); } 266 | #ifndef NO_DOUBLE 267 | inline int JEncoder::setDouble(double val) { 268 | return JEncoder_setDouble(this, val); } 269 | #endif 270 | inline int JEncoder::fmtString(const char* fmt,...) { 271 | int retv; va_list argList; 272 | va_start(argList, fmt); 273 | retv = JEncoder_fmtString(this, fmt, argList); 274 | va_end(argList); 275 | return retv; 276 | } 277 | inline int JEncoder::vFmtString(const char* fmt,va_list argList) { 278 | return JEncoder_vFmtString(this, fmt, argList); } 279 | inline int JEncoder::setString(const char* val) { 280 | return JEncoder_setString(this, val); } 281 | inline int JEncoder::b64enc(const void* source, S32 slen) { 282 | return JEncoder_b64enc(this, source, slen); } 283 | inline int JEncoder::setBoolean(bool val) { 284 | return JEncoder_setBoolean(this, val ? TRUE : FALSE); } 285 | inline int JEncoder::setNull() { 286 | return JEncoder_setNull(this); } 287 | inline int JEncoder::setJV(struct JVal* val, bool iterateNext) { 288 | return JEncoder_setJV(this,val,iterateNext?TRUE:FALSE); } 289 | inline int JEncoder::set(const char* fmt, ...) { 290 | int retv; va_list argList; 291 | va_start(argList, fmt); 292 | retv=JEncoder_vSetJV(this,&fmt,&argList); 293 | va_end(argList); 294 | return retv; 295 | } 296 | inline int JEncoder::setName(const char* name) { 297 | return JEncoder_setName(this, name); } 298 | inline int JEncoder::beginObject() { 299 | return JEncoder_beginObject(this); } 300 | inline int JEncoder::endObject() { 301 | return JEncoder_endObject(this); } 302 | inline int JEncoder::beginArray() { 303 | return JEncoder_beginArray(this); } 304 | inline int JEncoder::endArray() { 305 | return JEncoder_endArray(this); } 306 | inline JErr* JEncoder::getErr() { 307 | return JEncoder_getErr(this); } 308 | inline int JEncoder::flush() { 309 | return JEncoder_flush(this); } 310 | inline int JEncoder::commit() { 311 | return JEncoder_commit(this); } 312 | inline BufPrint* JEncoder::getBufPrint() { 313 | return JEncoder_getBufPrint(this); } 314 | #endif 315 | 316 | /** JEncoder::set helper macro, used when setting a value for an object. 317 | encoder.set("{d}", JE_MEMBER(structval, membername)); 318 | */ 319 | #define JE_MEMBER(o, m) #m, (o)->m 320 | 321 | 322 | /** @} */ /* end of JSONRef */ 323 | 324 | #endif 325 | -------------------------------------------------------------------------------- /inc/BufPrint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Embedded Web-Server 10 | **************************************************************************** 11 | * HEADER 12 | * 13 | * $Id: BufPrint.h 5355 2022-11-16 10:33:45Z wini $ 14 | * 15 | * COPYRIGHT: Real Time Logic LLC, 2008 - 2022 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://www.realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | 37 | #ifndef __BufPrint_h 38 | #define __BufPrint_h 39 | 40 | #include 41 | 42 | #ifndef BA_API 43 | #define BA_API 44 | #endif 45 | 46 | #include 47 | #include 48 | 49 | struct BufPrint; 50 | 51 | #ifdef __cplusplus 52 | extern "C" { 53 | #endif 54 | 55 | /** This function is similar to sprintf, but uses much less stack and 56 | is more suitable for a real time operating system with limited 57 | stack size. 58 | 59 | \param buf The buffer to where the data is formatted. 60 | \param fmt See BufPrint::printf 61 | */ 62 | BA_API int basprintf(char* buf, const char* fmt, ...); 63 | 64 | /** A safe version of sprintf. This function is similar to 65 | snprintf. The second argument specifies the buffer length and 66 | basnprintf returns -1 if the buffer being formatted should exceed 67 | that length. 68 | 69 | \param buf The buffer to where the data is formatted. 70 | \param len length of the buffer. 71 | \param fmt See BufPrint::printf 72 | */ 73 | BA_API int basnprintf(char* buf, int len, const char* fmt, ...); 74 | 75 | #ifdef __cplusplus 76 | #undef printf 77 | } 78 | #endif 79 | 80 | /** @defgroup BufPrint printf compatible function 81 | @{ 82 | 83 | \sa Barracuda Introduction 84 | */ 85 | 86 | /** BufPrint flush callback function. 87 | 88 | A BufPrint instance calls the flush callback function when the buffer 89 | is full or when #BufPrint::flush is called. The callback can either 90 | extend the buffer or flush and reset the buffer. 91 | 92 | The following default callback is set if no callback is installed when 93 | calling the BufPrint constructor: 94 | 95 | \code 96 | BufPrint_defaultFlush(struct BufPrint* bp, int sizeRequired) 97 | { 98 | bp->cursor=0; // Reset 99 | baAssert(sizeRequired == 0); // Program error in code calling BufPrint_xxx 100 | return sizeRequired ? -1 : 0; 101 | } 102 | \endcode 103 | 104 | \param o the object. BufPrint is typically upcasted to the derived object. 105 | \param sizeRequired the minimum size the buffer must expand. Note that 106 | sizeRequired will be zero when the callback is called via 107 | BufPrint::flush 108 | 109 | */ 110 | typedef int (*BufPrint_Flush)(struct BufPrint* o, int sizeRequired); 111 | 112 | /** The BufPrint class, which implements an ANSI compatible printf 113 | method, is a base class used by several other classes. 114 | 115 | This class does not allocate memory for the buffer. Thus, any 116 | class using BufPrint must provide a buffer BufPrint can use. The 117 | output from printf is formatted in the buffer passed into the 118 | constructor. BufPrint calls the callback function BufPrint_Flush 119 | when the buffer is full. See #BufPrint_Flush for additional details. 120 | */ 121 | typedef struct BufPrint 122 | { 123 | #ifdef __cplusplus 124 | 125 | /** BufPrint constructor. When using this constructor, make sure 126 | to also call setBuf(). C constructor name: BufPrint_constructor 127 | 128 | \param userData an optional argument stored in the BufPrint 129 | object and accessible in the flush callback. 130 | \param flush a pointer to the flush callback function. See 131 | #BufPrint_Flush for details. 132 | 133 | \sa setBuf(), getUserData() 134 | */ 135 | BufPrint(void* userData=0, BufPrint_Flush flush=0); 136 | 137 | /** BufPrint constructor. When using this constructor, make sure 138 | to also call setBuf(). C constructor name: BufPrint_constructor2 139 | 140 | \param buf the buffer 141 | \param size the buffer size 142 | \param userData an optional argument stored in the BufPrint 143 | object and accessible in the flush callback. 144 | \param flush a pointer to the flush callback function. See 145 | #BufPrint_Flush for details. 146 | 147 | \sa setBuf(), getUserData() 148 | */ 149 | BufPrint(char* buf,int size,void* userData=0,BufPrint_Flush flush=0); 150 | 151 | /** Returns the user data pointer set in the constructor. 152 | */ 153 | void* getUserData(); 154 | 155 | /** The printf function's format is identical to the standard 156 | ANSI vprintf function. See BufPrint::printf for the format flags. 157 | \param fmt See vprintf in the 158 | 159 | C Standard Library for more information. 160 | \param argList See vprintf in the C Standard Library for 161 | more information. 162 | */ 163 | int vprintf(const char* fmt, va_list argList); 164 | 165 | /** The printf function's format is identical to the standard 166 | ANSI printf function, but with the following extensions: 167 | 168 | \li %%lld is for printing S64 or a signed representation of a U64. 169 | \li %%llu is for printing an unsigned U64. 170 | \li %%j is similar to %%s, but the string is encoded by using 171 | BufPrint::jsonString 172 | 173 | \param fmt See vprintf in the 174 | 175 | C Standard Library for more information. 176 | */ 177 | int printf(const char* fmt, ...); 178 | 179 | /** print character (wrapper for BufPrint_putc) */ 180 | int baputc(int c); 181 | 182 | /** Write data to the buffer. 183 | * \param data pointer to data. 184 | * \param len size of data. 185 | */ 186 | int write(const void* data, int len); 187 | 188 | /** Used for sending a zero terminated string to the client. 189 | C method name is BufPrint_write2. 190 | \param buf a reference to the string. 191 | */ 192 | int write(const char* buf); 193 | 194 | 195 | /** Set the buffer used by BufPrint 196 | \param buf the buffer 197 | \param size the buffer size 198 | */ 199 | void setBuf(char* buf, int size); 200 | 201 | 202 | /** Returns a pointer to the internal buffer. Please note that 203 | * the buffer returned by this method is not zero terminated. 204 | * \sa BufPrint::getBufSize 205 | */ 206 | char* getBuf(); 207 | 208 | /** Returns current size of internal formatted data */ 209 | U32 getBufSize(); 210 | 211 | 212 | /** resets the cursor, thus erasing the data in the buffer */ 213 | void erase(); 214 | 215 | /** Flush buffer */ 216 | int flush(); 217 | 218 | /** Encode binary data as Base64. 219 | \sa baB64Decode 220 | \param data binary data or string to be encoded as B64. 221 | \param slen the data size. 222 | */ 223 | int b64Encode(const void* data, S32 slen); 224 | 225 | /** Encode binary data as Base64url. 226 | \sa baB64Decode 227 | \param data binary data or string to be encoded as B64. 228 | \param slen the data size. 229 | \param padding add padding characters. 230 | */ 231 | int b64urlEncode(const void* source, S32 slen, bool padding); 232 | 233 | /** Print and escape a string such that a browser can run the 234 | JavaScript 'eval' function and produce a string identical to the 235 | string the 'str' argument points to. The string must be ASCII or 236 | UTF8. A UTF8 string is converted to JavaScript Unicode i.e. to 237 | \\uxxxx. 238 | 239 | The function can, for example, be used if the server generates a 240 | JSON 241 | response or generates dynamic JavaScript in a CSP page. 242 | \sa BufPrint::printf with format flag j 243 | */ 244 | int jsonString(const char* str); 245 | #endif 246 | BufPrint_Flush flushCB; 247 | void *userData; 248 | char* buf; 249 | int cursor; 250 | int bufSize; 251 | }BufPrint; 252 | 253 | #define BufPrint_putcMacro(o, c) do { \ 254 | if((o)->cursor == (o)->bufSize) \ 255 | { \ 256 | if((o)->flushCB(o, 1)) \ 257 | return -1; \ 258 | } \ 259 | (o)->buf[(o)->cursor++] = c; \ 260 | } while(0) 261 | 262 | #ifdef __cplusplus 263 | extern "C" { 264 | #endif 265 | #define BufPrint_getUserData(o) (o)->userData 266 | #define BufPrint_erase(o) (o)->cursor=0 267 | #define BufPrint_getBuf(o) (o)->buf 268 | #define BufPrint_setBuf(o, b, size) (o)->buf=b,(o)->bufSize=size,(o)->cursor=0 269 | #define BufPrint_getBufSize(o) (o)->cursor 270 | BA_API void BufPrint_constructor( 271 | BufPrint* o,void* userData,BufPrint_Flush flush); 272 | BA_API void BufPrint_constructor2( 273 | BufPrint* o, char* buf,int size,void* userData,BufPrint_Flush flush); 274 | #define BufPrint_destructor(o) 275 | BA_API int BufPrint_vprintf(BufPrint* o, const char* fmt, va_list argList); 276 | BA_API int BufPrint_printf(BufPrint* o, const char* fmt, ...); 277 | BA_API int BufPrint_write(BufPrint* o, const void* data, int len); 278 | BA_API int BufPrint_putc(BufPrint* o, int c); 279 | BA_API int BufPrint_flush(BufPrint* o); 280 | #define BufPrint_write2(o, data) BufPrint_write(o, data, -1) 281 | BA_API int BufPrint_b64Encode(BufPrint* o, const void* source, S32 slen); 282 | BA_API int BufPrint_b64urlEncode( 283 | BufPrint* o, const void* source, S32 slen, BaBool padding); 284 | 285 | BA_API int BufPrint_jsonString(BufPrint* o, const char* str); 286 | #ifdef __cplusplus 287 | } 288 | inline void* BufPrint::getUserData() { 289 | return BufPrint_getUserData(this); 290 | } 291 | inline BufPrint::BufPrint(void* userData, BufPrint_Flush flush) { 292 | BufPrint_constructor(this, userData,flush); } 293 | inline BufPrint::BufPrint( 294 | char* buf,int size,void* userData,BufPrint_Flush flush) { 295 | BufPrint_constructor2(this,buf,size,userData,flush); } 296 | inline int BufPrint::vprintf(const char* fmt, va_list argList) { 297 | return BufPrint_vprintf(this, fmt, argList); } 298 | inline int BufPrint::printf(const char* fmt, ...) { 299 | int retv; va_list varg; 300 | va_start(varg, fmt); 301 | retv = BufPrint_vprintf(this, fmt, varg); 302 | va_end(varg); 303 | return retv; 304 | } 305 | inline char* BufPrint::getBuf() { 306 | return BufPrint_getBuf(this); } 307 | inline void BufPrint::setBuf(char* buffer, int size) { 308 | BufPrint_setBuf(this, buffer, size); } 309 | inline U32 BufPrint::getBufSize() { 310 | return BufPrint_getBufSize(this); } 311 | inline void BufPrint::erase() { 312 | BufPrint_erase(this); } 313 | inline int BufPrint::baputc(int c) { 314 | return BufPrint_putc(this, c); } 315 | inline int BufPrint::write(const void* data, int len) { 316 | return BufPrint_write(this, data, len); } 317 | inline int BufPrint::write(const char* data) { 318 | return BufPrint_write2(this, data); } 319 | inline int BufPrint::flush() { 320 | return BufPrint_flush(this); 321 | } 322 | inline int BufPrint::b64Encode(const void* source, S32 slen){ 323 | return BufPrint_b64Encode(this, source, slen); 324 | } 325 | inline int BufPrint::b64urlEncode(const void* source, S32 slen, bool padding){ 326 | return BufPrint_b64urlEncode(this, source, slen, padding?TRUE:FALSE); 327 | } 328 | inline int BufPrint::jsonString(const char* str){ 329 | return BufPrint_jsonString(this, str); 330 | } 331 | #endif 332 | 333 | /** @} */ /* end of BufPrint */ 334 | 335 | 336 | #endif 337 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 2.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE 4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION 5 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial content 12 | Distributed under this Agreement, and 13 | 14 | b) in the case of each subsequent Contributor: 15 | i) changes to the Program, and 16 | ii) additions to the Program; 17 | where such changes and/or additions to the Program originate from 18 | and are Distributed by that particular Contributor. A Contribution 19 | "originates" from a Contributor if it was added to the Program by 20 | such Contributor itself or anyone acting on such Contributor's behalf. 21 | Contributions do not include changes or additions to the Program that 22 | are not Modified Works. 23 | 24 | "Contributor" means any person or entity that Distributes the Program. 25 | 26 | "Licensed Patents" mean patent claims licensable by a Contributor which 27 | are necessarily infringed by the use or sale of its Contribution alone 28 | or when combined with the Program. 29 | 30 | "Program" means the Contributions Distributed in accordance with this 31 | Agreement. 32 | 33 | "Recipient" means anyone who receives the Program under this Agreement 34 | or any Secondary License (as applicable), including Contributors. 35 | 36 | "Derivative Works" shall mean any work, whether in Source Code or other 37 | form, that is based on (or derived from) the Program and for which the 38 | editorial revisions, annotations, elaborations, or other modifications 39 | represent, as a whole, an original work of authorship. 40 | 41 | "Modified Works" shall mean any work in Source Code or other form that 42 | results from an addition to, deletion from, or modification of the 43 | contents of the Program, including, for purposes of clarity any new file 44 | in Source Code form that contains any contents of the Program. Modified 45 | Works shall not include works that contain only declarations, 46 | interfaces, types, classes, structures, or files of the Program solely 47 | in each case in order to link to, bind by name, or subclass the Program 48 | or Modified Works thereof. 49 | 50 | "Distribute" means the acts of a) distributing or b) making available 51 | in any manner that enables the transfer of a copy. 52 | 53 | "Source Code" means the form of a Program preferred for making 54 | modifications, including but not limited to software source code, 55 | documentation source, and configuration files. 56 | 57 | "Secondary License" means either the GNU General Public License, 58 | Version 2.0, or any later versions of that license, including any 59 | exceptions or additional permissions as identified by the initial 60 | Contributor. 61 | 62 | 2. GRANT OF RIGHTS 63 | 64 | a) Subject to the terms of this Agreement, each Contributor hereby 65 | grants Recipient a non-exclusive, worldwide, royalty-free copyright 66 | license to reproduce, prepare Derivative Works of, publicly display, 67 | publicly perform, Distribute and sublicense the Contribution of such 68 | Contributor, if any, and such Derivative Works. 69 | 70 | b) Subject to the terms of this Agreement, each Contributor hereby 71 | grants Recipient a non-exclusive, worldwide, royalty-free patent 72 | license under Licensed Patents to make, use, sell, offer to sell, 73 | import and otherwise transfer the Contribution of such Contributor, 74 | if any, in Source Code or other form. This patent license shall 75 | apply to the combination of the Contribution and the Program if, at 76 | the time the Contribution is added by the Contributor, such addition 77 | of the Contribution causes such combination to be covered by the 78 | Licensed Patents. The patent license shall not apply to any other 79 | combinations which include the Contribution. No hardware per se is 80 | licensed hereunder. 81 | 82 | c) Recipient understands that although each Contributor grants the 83 | licenses to its Contributions set forth herein, no assurances are 84 | provided by any Contributor that the Program does not infringe the 85 | patent or other intellectual property rights of any other entity. 86 | Each Contributor disclaims any liability to Recipient for claims 87 | brought by any other entity based on infringement of intellectual 88 | property rights or otherwise. As a condition to exercising the 89 | rights and licenses granted hereunder, each Recipient hereby 90 | assumes sole responsibility to secure any other intellectual 91 | property rights needed, if any. For example, if a third party 92 | patent license is required to allow Recipient to Distribute the 93 | Program, it is Recipient's responsibility to acquire that license 94 | before distributing the Program. 95 | 96 | d) Each Contributor represents that to its knowledge it has 97 | sufficient copyright rights in its Contribution, if any, to grant 98 | the copyright license set forth in this Agreement. 99 | 100 | e) Notwithstanding the terms of any Secondary License, no 101 | Contributor makes additional grants to any Recipient (other than 102 | those set forth in this Agreement) as a result of such Recipient's 103 | receipt of the Program under the terms of a Secondary License 104 | (if permitted under the terms of Section 3). 105 | 106 | 3. REQUIREMENTS 107 | 108 | 3.1 If a Contributor Distributes the Program in any form, then: 109 | 110 | a) the Program must also be made available as Source Code, in 111 | accordance with section 3.2, and the Contributor must accompany 112 | the Program with a statement that the Source Code for the Program 113 | is available under this Agreement, and informs Recipients how to 114 | obtain it in a reasonable manner on or through a medium customarily 115 | used for software exchange; and 116 | 117 | b) the Contributor may Distribute the Program under a license 118 | different than this Agreement, provided that such license: 119 | i) effectively disclaims on behalf of all other Contributors all 120 | warranties and conditions, express and implied, including 121 | warranties or conditions of title and non-infringement, and 122 | implied warranties or conditions of merchantability and fitness 123 | for a particular purpose; 124 | 125 | ii) effectively excludes on behalf of all other Contributors all 126 | liability for damages, including direct, indirect, special, 127 | incidental and consequential damages, such as lost profits; 128 | 129 | iii) does not attempt to limit or alter the recipients' rights 130 | in the Source Code under section 3.2; and 131 | 132 | iv) requires any subsequent distribution of the Program by any 133 | party to be under a license that satisfies the requirements 134 | of this section 3. 135 | 136 | 3.2 When the Program is Distributed as Source Code: 137 | 138 | a) it must be made available under this Agreement, or if the 139 | Program (i) is combined with other material in a separate file or 140 | files made available under a Secondary License, and (ii) the initial 141 | Contributor attached to the Source Code the notice described in 142 | Exhibit A of this Agreement, then the Program may be made available 143 | under the terms of such Secondary Licenses, and 144 | 145 | b) a copy of this Agreement must be included with each copy of 146 | the Program. 147 | 148 | 3.3 Contributors may not remove or alter any copyright, patent, 149 | trademark, attribution notices, disclaimers of warranty, or limitations 150 | of liability ("notices") contained within the Program from any copy of 151 | the Program which they Distribute, provided that Contributors may add 152 | their own appropriate notices. 153 | 154 | 4. COMMERCIAL DISTRIBUTION 155 | 156 | Commercial distributors of software may accept certain responsibilities 157 | with respect to end users, business partners and the like. While this 158 | license is intended to facilitate the commercial use of the Program, 159 | the Contributor who includes the Program in a commercial product 160 | offering should do so in a manner which does not create potential 161 | liability for other Contributors. Therefore, if a Contributor includes 162 | the Program in a commercial product offering, such Contributor 163 | ("Commercial Contributor") hereby agrees to defend and indemnify every 164 | other Contributor ("Indemnified Contributor") against any losses, 165 | damages and costs (collectively "Losses") arising from claims, lawsuits 166 | and other legal actions brought by a third party against the Indemnified 167 | Contributor to the extent caused by the acts or omissions of such 168 | Commercial Contributor in connection with its distribution of the Program 169 | in a commercial product offering. The obligations in this section do not 170 | apply to any claims or Losses relating to any actual or alleged 171 | intellectual property infringement. In order to qualify, an Indemnified 172 | Contributor must: a) promptly notify the Commercial Contributor in 173 | writing of such claim, and b) allow the Commercial Contributor to control, 174 | and cooperate with the Commercial Contributor in, the defense and any 175 | related settlement negotiations. The Indemnified Contributor may 176 | participate in any such claim at its own expense. 177 | 178 | For example, a Contributor might include the Program in a commercial 179 | product offering, Product X. That Contributor is then a Commercial 180 | Contributor. If that Commercial Contributor then makes performance 181 | claims, or offers warranties related to Product X, those performance 182 | claims and warranties are such Commercial Contributor's responsibility 183 | alone. Under this section, the Commercial Contributor would have to 184 | defend claims against the other Contributors related to those performance 185 | claims and warranties, and if a court requires any other Contributor to 186 | pay any damages as a result, the Commercial Contributor must pay 187 | those damages. 188 | 189 | 5. NO WARRANTY 190 | 191 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 192 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS" 193 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 194 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF 195 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 196 | PURPOSE. Each Recipient is solely responsible for determining the 197 | appropriateness of using and distributing the Program and assumes all 198 | risks associated with its exercise of rights under this Agreement, 199 | including but not limited to the risks and costs of program errors, 200 | compliance with applicable laws, damage to or loss of data, programs 201 | or equipment, and unavailability or interruption of operations. 202 | 203 | 6. DISCLAIMER OF LIABILITY 204 | 205 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT 206 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS 207 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 208 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST 209 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 210 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 211 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 212 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE 213 | POSSIBILITY OF SUCH DAMAGES. 214 | 215 | 7. GENERAL 216 | 217 | If any provision of this Agreement is invalid or unenforceable under 218 | applicable law, it shall not affect the validity or enforceability of 219 | the remainder of the terms of this Agreement, and without further 220 | action by the parties hereto, such provision shall be reformed to the 221 | minimum extent necessary to make such provision valid and enforceable. 222 | 223 | If Recipient institutes patent litigation against any entity 224 | (including a cross-claim or counterclaim in a lawsuit) alleging that the 225 | Program itself (excluding combinations of the Program with other software 226 | or hardware) infringes such Recipient's patent(s), then such Recipient's 227 | rights granted under Section 2(b) shall terminate as of the date such 228 | litigation is filed. 229 | 230 | All Recipient's rights under this Agreement shall terminate if it 231 | fails to comply with any of the material terms or conditions of this 232 | Agreement and does not cure such failure in a reasonable period of 233 | time after becoming aware of such noncompliance. If all Recipient's 234 | rights under this Agreement terminate, Recipient agrees to cease use 235 | and distribution of the Program as soon as reasonably practicable. 236 | However, Recipient's obligations under this Agreement and any licenses 237 | granted by Recipient relating to the Program shall continue and survive. 238 | 239 | Everyone is permitted to copy and distribute copies of this Agreement, 240 | but in order to avoid inconsistency the Agreement is copyrighted and 241 | may only be modified in the following manner. The Agreement Steward 242 | reserves the right to publish new versions (including revisions) of 243 | this Agreement from time to time. No one other than the Agreement 244 | Steward has the right to modify this Agreement. The Eclipse Foundation 245 | is the initial Agreement Steward. The Eclipse Foundation may assign the 246 | responsibility to serve as the Agreement Steward to a suitable separate 247 | entity. Each new version of the Agreement will be given a distinguishing 248 | version number. The Program (including Contributions) may always be 249 | Distributed subject to the version of the Agreement under which it was 250 | received. In addition, after a new version of the Agreement is published, 251 | Contributor may elect to Distribute the Program (including its 252 | Contributions) under the new version. 253 | 254 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient 255 | receives no rights or licenses to the intellectual property of any 256 | Contributor under this Agreement, whether expressly, by implication, 257 | estoppel or otherwise. All rights in the Program not expressly granted 258 | under this Agreement are reserved. Nothing in this Agreement is intended 259 | to be enforceable by any entity that is not a Contributor or Recipient. 260 | No third-party beneficiary rights are created under this Agreement. 261 | 262 | Exhibit A - Form of Secondary Licenses Notice 263 | 264 | "This Source Code may also be made available under the following 265 | Secondary Licenses when the conditions for such availability set forth 266 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s), 267 | version(s), and exceptions or additional permissions here}." 268 | 269 | Simply including a copy of this Agreement, including this Exhibit A 270 | is not sufficient to license the Source Code under Secondary Licenses. 271 | 272 | If it is not possible or desirable to put the notice in a particular 273 | file, then You may include the notice in a location (such as a LICENSE 274 | file in a relevant directory) where a recipient would be likely to 275 | look for such a notice. 276 | 277 | You may add additional accurate notices of copyright ownership. 278 | -------------------------------------------------------------------------------- /inc/JParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | * 11 | **************************************************************************** 12 | * HEADER 13 | * 14 | * $Id: JParser.h 4915 2021-12-01 18:26:55Z wini $ 15 | * 16 | * COPYRIGHT: Real Time Logic LLC, 2006-2018 17 | * 18 | * This software is copyrighted by and is the sole property of Real 19 | * Time Logic LLC. All rights, title, ownership, or other interests in 20 | * the software remain the property of Real Time Logic LLC. This 21 | * software may only be used in accordance with the terms and 22 | * conditions stipulated in the corresponding license agreement under 23 | * which the software has been supplied. Any unauthorized use, 24 | * duplication, transmission, distribution, or disclosure of this 25 | * software is expressly forbidden. 26 | * 27 | * This Copyright notice may not be removed or modified without prior 28 | * written consent of Real Time Logic LLC. 29 | * 30 | * Real Time Logic LLC. reserves the right to modify this software 31 | * without notice. 32 | * 33 | * http://realtimelogic.com 34 | **************************************************************************** 35 | * 36 | */ 37 | 38 | #ifndef __JParser_h 39 | #define __JParser_h 40 | 41 | 42 | #include 43 | #include 44 | 45 | /** @addtogroup JSONCB 46 | @{ 47 | */ 48 | 49 | struct JParserIntf; 50 | struct JParserVal; 51 | 52 | /** The parser callback function. 53 | \param o, the interface object 54 | \param v, the parsed value 55 | \param recLevel goes from 0 to N and represents object nesting level 56 | */ 57 | typedef int (*JParserIntf_Service)( 58 | struct JParserIntf* o, struct JParserVal* v, int recLevel); 59 | 60 | 61 | /** The JParserIntf interface class is the interface between the parser and 62 | an object that implements the JParserIntf interface. 63 | */ 64 | typedef struct JParserIntf 65 | { 66 | #ifdef __cplusplus 67 | /** Create the callback interface object. 68 | \param s the parser service callback function. 69 | */ 70 | JParserIntf(JParserIntf_Service s) { service = s; } 71 | 72 | /** Calling the JParserIntf service function is typically performed 73 | in a design using a chained parser callback interface. 74 | \param v the parsed value provided by JParser 75 | \param recLevel must be adjusted by the chained callback 76 | */ 77 | int serviceCB(JParserVal* v, int recLevel); 78 | 79 | ~JParserIntf(){} 80 | JParserIntf() {} 81 | #endif 82 | JParserIntf_Service service; 83 | } JParserIntf; 84 | 85 | #define JParserIntf_constructor(o,serviceMA) (o)->service=serviceMA 86 | 87 | #define JParserIntf_serviceCB(o, v, recLev) (o)->service(o,v,recLev) 88 | 89 | #ifdef __cplusplus 90 | 91 | inline int JParserIntf::serviceCB(JParserVal* v, int recLevel) { 92 | return JParserIntf_serviceCB(this,v, recLevel); } 93 | #endif 94 | 95 | /** @} */ /* end of JSONCB */ 96 | 97 | /** @addtogroup JSONRef 98 | @{ 99 | */ 100 | 101 | /** The JSON types. 102 | */ 103 | typedef enum { 104 | /** Invalid JSON type. 105 | */ 106 | JVType_InvalidType, 107 | /** JSON string. 108 | */ 109 | JVType_String, 110 | /** JSON Number encoded as a float. 111 | */ 112 | JVType_Double, 113 | /** JSON Number encoded as an integer. 114 | */ 115 | JVType_Int, 116 | /** JSON Number encoded as a long integer. 117 | */ 118 | JVType_Long, 119 | /** JSON boolean. */ 120 | JVType_Boolean, 121 | /** JSON NULL value. */ 122 | JVType_Null, 123 | /** The JVAL is of type JSON object. */ 124 | JVType_Object, 125 | /** The JVAL is of type JSON array. */ 126 | JVType_Array 127 | } JVType; 128 | 129 | /** JSON error codes 130 | */ 131 | typedef enum 132 | { 133 | /** No error. */ 134 | JErrT_NoErr=0, 135 | /** Generic error. */ 136 | JErrT_JsonErr, 137 | /** Unexpected JSON type when parsing. 138 | \sa JErr::getExpT JErr::getRecT 139 | */ 140 | JErrT_WrongType, 141 | /** Invalid RPC method parameters. */ 142 | JErrT_InvalidMethodParams, 143 | /** A format error in JEncoder or JVal::get 144 | */ 145 | JErrT_FmtValErr, 146 | /** Memory allocation error. */ 147 | JErrT_MemErr, 148 | /** I/O error. */ 149 | JErrT_IOErr 150 | } JErrT; 151 | 152 | /** The JSON error container object 153 | */ 154 | typedef struct JErr 155 | { 156 | #ifdef __cplusplus 157 | /** Create a new object. */ 158 | JErr(); 159 | /** Reset -- remove any error so the object can be reused. */ 160 | void reset(); 161 | /** Returns true if the error flag is set. */ 162 | bool isError(); 163 | /** Returns true if no error. */ 164 | bool noError(); 165 | /** Returns the error type. */ 166 | JErrT getErrT(); 167 | /** Returns the expected type if this is a parse error. 168 | \sa getErrT getRecT 169 | */ 170 | JVType getExpT(); 171 | /** Returns the parsed type if this is a parse error. 172 | \sa getErrT getExpT 173 | */ 174 | JVType getRecT(); 175 | int setTooFewParams(); 176 | int setTypeErr(JVType expT, JVType recT); 177 | int setError(JErrT err,const char* msg); 178 | #endif 179 | const char* msg; 180 | JErrT err; 181 | JVType expType; 182 | JVType recType; 183 | } JErr; 184 | #ifdef __cplusplus 185 | extern "C" { 186 | #endif 187 | #define JErr_constructor(o) (o)->err=JErrT_NoErr 188 | #define JErr_reset(o) (o)->err=JErrT_NoErr, (o)->msg=0 189 | #define JErr_isError(o) (o)->err!=JErrT_NoErr 190 | #define JErr_noError(o) (o)->err==JErrT_NoErr 191 | #define JErr_getErrT(o) (o)->err 192 | #define JErr_getExpT(o) (o)->expType 193 | #define JErr_getRecT(o) (o)->recType 194 | BA_API int JErr_setTooFewParams(JErr* o); 195 | BA_API int JErr_setTypeErr(JErr* o, JVType expT, JVType recT); 196 | BA_API int JErr_setError(JErr* o,JErrT err,const char* msg); 197 | #ifdef __cplusplus 198 | } 199 | inline JErr::JErr() { 200 | JErr_constructor(this); } 201 | inline void JErr::reset() { 202 | JErr_reset(this); } 203 | inline bool JErr::isError() { 204 | return JErr_isError(this) ? true : false;} 205 | inline bool JErr::noError() { 206 | return JErr_noError(this) ? true : false;} 207 | inline JErrT JErr::getErrT() { 208 | return JErr_getErrT(this);} 209 | inline JVType JErr::getExpT() { 210 | return JErr_getExpT(this);} 211 | inline JVType JErr::getRecT() { 212 | return JErr_getRecT(this);} 213 | inline int JErr::setTooFewParams() { 214 | return JErr_setTooFewParams(this);} 215 | inline int JErr::setTypeErr(JVType expT, JVType recT) { 216 | return JErr_setTypeErr(this, expT, recT);} 217 | inline int JErr::setError(JErrT e,const char* message) { 218 | return JErr_setError(this,e, message);} 219 | #endif 220 | 221 | 222 | 223 | #ifndef __DOXYGEN__ 224 | typedef struct 225 | { 226 | AllocatorIntf* alloc; 227 | U8* buf; 228 | U32 index; 229 | size_t size; 230 | } JDBuf; 231 | 232 | 233 | /* JLextT: JSON Lexer Types. 234 | The following types are used by the lexer and parser. 235 | */ 236 | typedef enum { 237 | JLexerT_Null, 238 | JLexerT_Boolean, 239 | JLexerT_Number, 240 | JLexerT_String, 241 | JLexerT_BeginObject, 242 | JLexerT_BeginArray, 243 | JLexerT_EndObject, 244 | JLexerT_EndArray, 245 | JLexerT_Comma, /* ',' Array or object list comma. */ 246 | JLexerT_MemberSep, /* ':' for string : value */ 247 | JLexerT_NeedMoreData, /* Lexer not completed with current token. */ 248 | JLexerT_ParseErr, 249 | JLexerT_MemErr 250 | } JLexerT; 251 | 252 | 253 | 254 | typedef enum { 255 | JLexerSt_StartComment, 256 | JLexerSt_EatComment, 257 | JLexerSt_EndComment, 258 | JLexerSt_EatCppComment, 259 | JLexerSt_TrueFalseNull, 260 | JLexerSt_String, 261 | JLexerSt_StringEscape, 262 | JLexerSt_StringUnicode, 263 | JLexerSt_Number, 264 | JLexerSt_GetNextToken 265 | } JLexerSt; 266 | 267 | 268 | typedef struct 269 | { 270 | JDBuf* asmB; 271 | const U8* bufStart; 272 | const U8* bufEnd; 273 | const U8* tokenPtr; 274 | 275 | U32 unicode; 276 | S16 unicodeShift; 277 | 278 | /* typeChkPtr and retVal is used if the Lexer finds the start of 279 | true, false, or null. 280 | */ 281 | const U8* typeChkPtr; 282 | U8 retVal; 283 | 284 | U8 state; /* JLexerSt */ 285 | 286 | /* state for string or number. 287 | If in state number, 0 means positive number and 255 means neg. 288 | If in state String, sn is ' or ". 289 | If in state Boolean: true or false. 290 | */ 291 | U8 sn; 292 | U8 isDouble; /* Used when reading a number */ 293 | } JLexer; 294 | 295 | #endif /* __DOXYGEN__ */ 296 | 297 | /** Type 't' in JParserVal 298 | */ 299 | typedef enum { 300 | JParserT_InvalidType=0, /**< InvalidType */ 301 | JParserT_Null, /**< Null */ 302 | JParserT_String = 's', /**< String */ 303 | JParserT_Double = 'f', /**< Double */ 304 | JParserT_Int = 'd', /**< Int */ 305 | JParserT_Long = 'l', /**< 64 bit (long long) */ 306 | JParserT_Boolean = 'b', /**< Boolean */ 307 | JParserT_BeginObject = '{', /**< BeginObject */ 308 | JParserT_BeginArray = '[', /**< BeginArray */ 309 | JParserT_EndObject = '}', /**< EndObject */ 310 | JParserT_EndArray = ']' /**< EndArray */ 311 | } JParserT; 312 | 313 | /** The parser sets a JParserVal before calling the parser callback 314 | * JParserIntf. 315 | */ 316 | typedef struct JParserVal 317 | { 318 | /** A union controlled by the type 't' 319 | */ 320 | union 321 | { 322 | char* s; /**< If string */ 323 | #ifndef NO_DOUBLE 324 | double f; /**< If number of type double */ 325 | #endif 326 | S32 d; /**< If integer */ 327 | U64 l; /**< If long integer */ 328 | BaBool b; 329 | } v; 330 | 331 | /** object member name is set for objects. Use the following 332 | construction to differentiate between an object/array: 333 | \code 334 | if(*val->memberName) 335 | { 336 | // object 337 | } 338 | else 339 | { 340 | // array 341 | } 342 | 343 | \endcode 344 | */ 345 | char* memberName; 346 | JParserT t; /**< The type controlling 'v' */ 347 | } JParserVal; 348 | 349 | 350 | /** JSON Parser Status. 351 | */ 352 | typedef enum { 353 | 354 | /** The parser completed parsing a new JSON object. 355 | */ 356 | JParsStat_DoneEOS=1, 357 | 358 | /** The parser completed parsing a new JSON object, but found the 359 | start of a new object in the provided buffer. 360 | */ 361 | JParsStat_Done, 362 | 363 | 364 | /** The parser needs more data to complete. */ 365 | JParsStat_NeedMoreData = 100, 366 | 367 | /** JSON Parse error 368 | */ 369 | JParsStat_ParseErr = 200, 370 | 371 | /** The JParserIntf interface reported a problem. 372 | */ 373 | JParsStat_IntfErr, 374 | 375 | /** Memory allocation error. 376 | */ 377 | JParsStat_MemErr, 378 | 379 | /** Object nested too deep. Increase stack size in constructor */ 380 | JParsStat_StackOverflow 381 | } JParsStat; 382 | 383 | 384 | typedef enum { 385 | JParserSt_StartObj, 386 | JParserSt_BeginArray, 387 | JParserSt_MemberName, 388 | JParserSt_MemberSep, 389 | JParserSt_Value, 390 | JParserSt_EndObj, 391 | JParserSt_Comma 392 | } JParserSt; 393 | 394 | 395 | #define JPARSER_STACK_LEN 8 396 | 397 | /** The stack used internally by JParser */ 398 | typedef U8 JParserStackNode; 399 | 400 | /** The JSON parser parses a JSON stream and calls the JParserIntf 401 | callback interface for each parsed object/primitive type. 402 | 403 | \sa UBJParser 404 | */ 405 | struct JParser 406 | { 407 | #ifdef __cplusplus 408 | /** Create a JSON parser object. 409 | 410 | \param intf is the parser callback/interface. Provide your own 411 | callback or use one of JParserValFact or JDecoder. 412 | 413 | \param nameBuf is a buffer required for temporarily storing 414 | parsed object member names. 415 | 416 | \param namebufSize sizeof(nameBuf) 417 | 418 | \param alloc is the allocator used for internal buffer management. 419 | 420 | \param extraStackLen is a non documented feature and must be set to 0. 421 | */ 422 | JParser(JParserIntf* intf, char* nameBuf, int namebufSize, 423 | AllocatorIntf* alloc, int extraStackLen=0); 424 | 425 | /** Parse a JSON text chunk. 426 | \param buf a pointer to the JSON text chunk buffer. 427 | \param size is the buffer length. 428 | \returns 429 | \li 0: Needs more data. The JSON chunk parsed was only a 430 | partial object. 431 | \li > 0: A complete JSON object is assembled. 432 | \li < 0: Parse error. 433 | \sa getStatus 434 | */ 435 | int parse(const U8* buf, U32 size); 436 | 437 | /** Terminate and release the internal buffers. */ 438 | ~JParser(); 439 | 440 | /** Returns the parser status. Typically used when method parse 441 | returns a non zero value. 442 | \sa parse 443 | */ 444 | JParsStat getStatus(); 445 | #endif 446 | JLexer lexer; 447 | JParserVal val; 448 | JDBuf asmB; /* Assembling various values */ 449 | JDBuf mnameB; /* Assembling object member names */ 450 | JParserIntf* intf; 451 | S16 stackIx; 452 | S16 stackSize; 453 | U8 status; /* JParsStat */ 454 | U8 state; /* JParserSt */ 455 | /* It's possible to extend the stack size by reserving 456 | * N*JParserStackNode bytes immediately following the memory for 457 | * this struct instance. N is then used as 'extraStackLen' in constructor. 458 | */ 459 | JParserStackNode stack[JPARSER_STACK_LEN]; 460 | }; 461 | 462 | typedef struct JParser JParser; 463 | 464 | #ifdef __cplusplus 465 | extern "C" { 466 | #endif 467 | BA_API void JParser_constructor(JParser* o, JParserIntf* intf, char* nameBuf, 468 | int namebufSize, AllocatorIntf* alloc, 469 | int extraStackLen); 470 | BA_API int JParser_parse(JParser* o, const U8* buf, U32 size); 471 | BA_API void JParser_destructor(JParser* o); 472 | #define JParser_getStatus(o) ((JParsStat)(o)->status) 473 | #ifdef __cplusplus 474 | } 475 | inline JParser::JParser(JParserIntf* intf, char* nameBuf, 476 | int namebufSize, AllocatorIntf* alloc, 477 | int extraStackLen) { 478 | JParser_constructor(this, intf, nameBuf, namebufSize, alloc, extraStackLen); 479 | } 480 | inline int JParser::parse(const U8* buf, U32 size) { 481 | return JParser_parse(this, buf, size);} 482 | inline JParser::~JParser() { 483 | JParser_destructor(this);} 484 | inline JParsStat JParser::getStatus() { 485 | return JParser_getStatus(this);} 486 | #endif 487 | 488 | /** @} */ /* end of JSONRef */ 489 | 490 | #endif 491 | -------------------------------------------------------------------------------- /src/JEncoder.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | **************************************************************************** 11 | * PROGRAM MODULE 12 | * 13 | * $Id: JEncoder.c 4914 2021-12-01 18:24:30Z wini $ 14 | * 15 | * COPYRIGHT: Real Time Logic, 2006 - 2018 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | 37 | 38 | 39 | 40 | /* 41 | 42 | Remove the dependency on the source file JVal.c by defining: 43 | 44 | #define NO_JVAL_DEPENDENCY 45 | 46 | The above construction, which is designed for resource limited 47 | devices, enables the use of the JEncoder without requiring JVal.c 48 | 49 | The above disables function JEncoder::setJV and the format flag 'J' 50 | for function JEncoder_set/JEncoder_vSetJV 51 | 52 | */ 53 | 54 | 55 | 56 | 57 | 58 | #ifndef BA_LIB 59 | #define BA_LIB 1 60 | #endif 61 | 62 | #include 63 | #include 64 | 65 | 66 | 67 | #define JEncoder_isObject(o) \ 68 | ((o)->objectStack.data[((o)->objectStack.level/8)] & \ 69 | (1 << ((o)->objectStack.level%8))) 70 | 71 | #define JEncoder_setObject(o) \ 72 | (o)->objectStack.data[((o)->objectStack.level/8)] |= \ 73 | (1 << ((o)->objectStack.level%8)); 74 | 75 | #define JEncoder_clearObject(o) \ 76 | (o)->objectStack.data[((o)->objectStack.level/8)] &= \ 77 | ~(1 << ((o)->objectStack.level%8)); 78 | 79 | static int 80 | JEncoder_setIoErr(JEncoder* o) 81 | { 82 | JErr_setError(o->err, JErrT_IOErr, "Cannot write"); 83 | return -1; 84 | } 85 | 86 | static int 87 | JEncoder_setCommaSep(JEncoder* o) 88 | { 89 | if(o->startNewObj) 90 | o->startNewObj = FALSE; 91 | else 92 | { 93 | if(BufPrint_printf(o->out,",")<0) 94 | { 95 | JEncoder_setIoErr(o); 96 | return -1; 97 | } 98 | } 99 | return 0; 100 | } 101 | 102 | static BaBool 103 | JEncoder_beginValue(JEncoder* o, BaBool isMemberName) 104 | { 105 | const char* eMsg=0; 106 | 107 | if(JErr_isError(o->err)) 108 | return FALSE; /* Failed */ 109 | if(JEncoder_isObject(o)) 110 | { 111 | if(isMemberName) /* If called by method name */ 112 | { 113 | if(JEncoder_setCommaSep(o)) return FALSE; 114 | if(o->objectMember) 115 | eMsg = "Duplicate call to name"; 116 | else 117 | o->objectMember=1; 118 | } 119 | else if(o->objectMember) /* Do we have an object member name */ 120 | o->objectMember = 0; /* reset */ 121 | else 122 | eMsg = "Invalid fmt. Missing object member name"; 123 | } 124 | else 125 | { 126 | if(JEncoder_setCommaSep(o)) return FALSE; 127 | if(isMemberName) /* If called by method name */ 128 | eMsg="Invalid fmt in name. Not an object"; 129 | } 130 | if(eMsg) 131 | { 132 | JErr_setError(o->err, JErrT_FmtValErr, eMsg); 133 | return FALSE; 134 | } 135 | return TRUE; 136 | } 137 | 138 | 139 | void 140 | JEncoder_constructor(JEncoder* o, JErr* err, BufPrint* out) 141 | { 142 | memset(o, 0, sizeof(JEncoder)); 143 | o->err = err; 144 | o->out = out; 145 | o->startNewObj=TRUE; 146 | } 147 | 148 | int 149 | JEncoder_flush(JEncoder* o) 150 | { 151 | if(JErr_noError(o->err)) 152 | return BufPrint_flush(o->out); 153 | return -1; 154 | } 155 | 156 | 157 | int 158 | JEncoder_commit(JEncoder* o) 159 | { 160 | o->startNewObj=TRUE; 161 | return JEncoder_flush(o); 162 | } 163 | 164 | int 165 | JEncoder_setInt(JEncoder* o, S32 val) 166 | { 167 | if(JEncoder_beginValue(o, FALSE)) 168 | { 169 | if(BufPrint_printf(o->out, "%d", val)<0) 170 | return JEncoder_setIoErr(o); 171 | return 0; 172 | } 173 | return -1; 174 | } 175 | 176 | 177 | int 178 | JEncoder_setLong(JEncoder* o, S64 val) 179 | { 180 | if(JEncoder_beginValue(o, FALSE)) 181 | { 182 | if(BufPrint_printf(o->out, "%lld", val)<0) 183 | return JEncoder_setIoErr(o); 184 | return 0; 185 | } 186 | return -1; 187 | } 188 | 189 | 190 | #ifndef NO_DOUBLE 191 | int 192 | JEncoder_setDouble(JEncoder* o, double val) 193 | { 194 | if(JEncoder_beginValue(o, FALSE)) 195 | { 196 | if(BufPrint_printf(o->out,"%f",val)<0) 197 | return JEncoder_setIoErr(o); 198 | return 0; 199 | } 200 | return -1; 201 | } 202 | #endif 203 | 204 | 205 | int 206 | JEncoder_setString(JEncoder* o, const char* val) 207 | { 208 | if(JEncoder_beginValue(o, FALSE)) 209 | { 210 | if(val) 211 | { 212 | if(BufPrint_jsonString(o->out,val)<0) 213 | return JEncoder_setIoErr(o); 214 | } 215 | else 216 | { 217 | if(BufPrint_write(o->out,"null", -1)<0) 218 | return JEncoder_setIoErr(o); 219 | } 220 | return 0; 221 | } 222 | return -1; 223 | } 224 | 225 | 226 | int 227 | JEncoder_b64enc(JEncoder* o, const void* source, S32 slen) 228 | { 229 | if(JEncoder_beginValue(o, FALSE)) 230 | { 231 | if(BufPrint_putc(o->out,'"') || 232 | BufPrint_b64Encode(o->out,source, slen)<0 || 233 | BufPrint_putc(o->out,'"')) 234 | { 235 | return JEncoder_setIoErr(o); 236 | } 237 | } 238 | return -1; 239 | } 240 | 241 | 242 | int 243 | JEncoder_vFmtString(JEncoder* o, const char* fmt,va_list argList) 244 | { 245 | if(JEncoder_beginValue(o, FALSE)) 246 | { 247 | if(fmt) 248 | { 249 | if(BufPrint_putc(o->out,'"') || 250 | BufPrint_vprintf(o->out,fmt,argList)<0 || 251 | BufPrint_putc(o->out,'"')) 252 | { 253 | return JEncoder_setIoErr(o); 254 | } 255 | } 256 | else 257 | { 258 | if(BufPrint_write(o->out,"null", -1)<0) 259 | return JEncoder_setIoErr(o); 260 | } 261 | return 0; 262 | } 263 | return -1; 264 | } 265 | 266 | 267 | 268 | int 269 | JEncoder_setBoolean(JEncoder* o, BaBool val) 270 | { 271 | if(JEncoder_beginValue(o, FALSE)) 272 | { 273 | if(BufPrint_printf(o->out,"%s",val?"true":"false")<0) 274 | return JEncoder_setIoErr(o); 275 | return 0; 276 | } 277 | return -1; 278 | } 279 | 280 | 281 | int 282 | JEncoder_setNull(JEncoder* o) 283 | { 284 | if(JEncoder_beginValue(o, FALSE)) 285 | { 286 | if(BufPrint_write(o->out, "null", -1)<0) 287 | return JEncoder_setIoErr(o); 288 | return 0; 289 | } 290 | return -1; 291 | } 292 | 293 | 294 | #ifdef NO_JVAL_DEPENDENCY 295 | #define JEncoder_setJV(o,val,x) \ 296 | JErr_setError(o->err, JErrT_FmtValErr, "Feature 'J' Disabled");return -1 297 | #else 298 | int 299 | JEncoder_setJV(JEncoder* o, JVal* val, BaBool iterateNext) 300 | { 301 | for(; val && JErr_noError(o->err); val=JVal_getNextElem(val)) 302 | { 303 | if( JVal_isObjectMember(val) && ! o->objectMember ) 304 | { 305 | JEncoder_setName(o, JVal_getName(val)); 306 | } 307 | switch(JVal_getType(val)) 308 | { 309 | case JVType_Null: 310 | JEncoder_setNull(o); 311 | break; 312 | 313 | case JVType_Boolean: 314 | JEncoder_setBoolean(o,JVal_getBoolean(val,o->err)); 315 | break; 316 | 317 | case JVType_Double: 318 | #ifdef NO_DOUBLE 319 | baAssert(0); 320 | #else 321 | JEncoder_setDouble(o, JVal_getDouble(val, o->err)); 322 | #endif 323 | break; 324 | 325 | case JVType_Int: 326 | JEncoder_setInt(o, JVal_getInt(val, o->err)); 327 | break; 328 | 329 | case JVType_Long: 330 | JEncoder_setLong(o, JVal_getLong(val, o->err)); 331 | break; 332 | 333 | case JVType_String: 334 | JEncoder_setString(o, JVal_getString(val, o->err)); 335 | break; 336 | 337 | case JVType_Object: 338 | JEncoder_beginObject(o); 339 | JEncoder_setJV(o, JVal_getObject(val, o->err),TRUE); 340 | JEncoder_endObject(o); 341 | break; 342 | 343 | case JVType_Array: 344 | JEncoder_beginArray(o); 345 | JEncoder_setJV(o, JVal_getArray(val, o->err), TRUE); 346 | JEncoder_endArray(o); 347 | break; 348 | 349 | default: baAssert(0); 350 | } 351 | if( !iterateNext ) 352 | break; 353 | } 354 | return JErr_noError(o->err) ? 0 : -1; 355 | } 356 | #endif 357 | 358 | int 359 | JEncoder_setName(JEncoder* o, const char* name) 360 | { 361 | if(JEncoder_beginValue(o, TRUE)) 362 | { 363 | if(BufPrint_printf(o->out, "\"%s\":", name)<0) 364 | return JEncoder_setIoErr(o); 365 | return 0; 366 | } 367 | return -1; 368 | } 369 | 370 | 371 | int 372 | JEncoder_beginObject(JEncoder* o) 373 | { 374 | if(JEncoder_beginValue(o, FALSE)) 375 | { 376 | if(o->objectStack.level < (sizeof(o->objectStack.data)*8-1)) 377 | { 378 | /* Set current stack position to "isObject" */ 379 | o->objectStack.level++; 380 | JEncoder_setObject(o); 381 | if(BufPrint_write(o->out, "{", -1)<0) 382 | return JEncoder_setIoErr(o); 383 | o->startNewObj=TRUE; 384 | return 0; 385 | } 386 | JErr_setError(o->err, JErrT_FmtValErr, 387 | "Object nested too deep"); 388 | } 389 | return -1; 390 | } 391 | 392 | 393 | int 394 | JEncoder_endObject(JEncoder* o) 395 | { 396 | if(JErr_noError(o->err)) 397 | { 398 | if(o->objectStack.level > 0) 399 | { 400 | if(JEncoder_isObject(o)) 401 | { 402 | if(BufPrint_printf(o->out, "}", -1)<0) 403 | return JEncoder_setIoErr(o); 404 | JEncoder_clearObject(o); 405 | o->objectStack.level--; 406 | o->startNewObj=FALSE; 407 | return 0; 408 | } 409 | JErr_setError(o->err, JErrT_FmtValErr, 410 | "endObject: Not an object"); 411 | } 412 | else 413 | JErr_setError(o->err, JErrT_FmtValErr, 414 | "endObject: Unrolled too many times"); 415 | } 416 | return -1; 417 | } 418 | 419 | 420 | int 421 | JEncoder_beginArray(JEncoder* o) 422 | { 423 | if(JEncoder_beginValue(o, FALSE)) 424 | { 425 | if(o->objectStack.level < (sizeof(o->objectStack.data)*8)) 426 | { 427 | o->objectStack.level++; 428 | if(BufPrint_printf(o->out, "[", -1)<0) 429 | return JEncoder_setIoErr(o); 430 | o->startNewObj=TRUE; 431 | return 0; 432 | } 433 | JErr_setError(o->err, JErrT_FmtValErr, 434 | "Array nested too deep"); 435 | } 436 | return -1; 437 | } 438 | 439 | 440 | int 441 | JEncoder_endArray(JEncoder* o) 442 | { 443 | if(JErr_noError(o->err)) 444 | { 445 | 446 | if(o->objectStack.level > 0) 447 | { 448 | if( ! JEncoder_isObject(o) ) 449 | { 450 | if(BufPrint_printf(o->out, "]", -1)<0) 451 | return JEncoder_setIoErr(o); 452 | o->objectStack.level--; 453 | o->startNewObj=FALSE; 454 | return 0; 455 | } 456 | JErr_setError(o->err, JErrT_FmtValErr, 457 | "endArray: Is object"); 458 | } 459 | else 460 | JErr_setError(o->err, JErrT_FmtValErr, 461 | "endArray: Unrolled too many times"); 462 | } 463 | return -1; 464 | } 465 | 466 | 467 | static int 468 | JEncoder_setArray(JEncoder* o, const char flag, void* array, int len) 469 | { 470 | int i; 471 | JEncoder_beginArray(o); 472 | for(i = 0 ; i < len ; i++) 473 | { 474 | if(JErr_isError(o->err)) 475 | return -1; 476 | switch(flag) 477 | { 478 | case 'b': 479 | JEncoder_setBoolean(o, ((BaBool*)array)[i]); 480 | break; 481 | case 'd': 482 | JEncoder_setInt(o, ((S32*)array)[i]); 483 | break; 484 | case 'f': 485 | JEncoder_setDouble(o, ((double*)array)[i]); 486 | break; 487 | case 's': 488 | JEncoder_setString(o, ((const char**)array)[i]); 489 | break; 490 | case 'J': 491 | JEncoder_setJV(o, ((JVal**)array)[i], FALSE); 492 | break; 493 | 494 | default: 495 | JErr_setError( 496 | o->err, JErrT_FmtValErr, 497 | "Unknown or illegal format flag in array flag 'A'"); 498 | } 499 | } 500 | JEncoder_endArray(o); 501 | return 0; 502 | } 503 | 504 | 505 | int 506 | JEncoder_vSetJV(JEncoder* o, const char** fmt, va_list* argList) 507 | { 508 | union 509 | { 510 | const void* p; 511 | int len; 512 | } u; 513 | 514 | for( ; **fmt ; (*fmt)++) 515 | { 516 | if(JErr_isError(o->err)) 517 | return -1; 518 | if(**fmt == '}' || **fmt == ']') 519 | { 520 | if(o->objectStack.level == 0) 521 | { 522 | JErr_setError(o->err, JErrT_FmtValErr, 523 | "JEncoder::set Mismatched ']' or '}'"); 524 | return -1; 525 | } 526 | return 0; 527 | } 528 | if(JEncoder_isObject(o)) 529 | JEncoder_setName(o,va_arg(*argList, char*)); 530 | switch(**fmt) 531 | { 532 | case 'b': 533 | JEncoder_setBoolean(o, (BaBool)va_arg(*argList, int)); 534 | break; 535 | case 'd': 536 | JEncoder_setInt(o, va_arg(*argList, S32)); 537 | break; 538 | case 'l': 539 | JEncoder_setLong(o, va_arg(*argList, S64)); 540 | break; 541 | case 'f': 542 | JEncoder_setDouble(o, va_arg(*argList, double)); 543 | break; 544 | case 's': 545 | JEncoder_setString(o, va_arg(*argList, char*)); 546 | break; 547 | case 'n': 548 | JEncoder_setNull(o); 549 | break; 550 | case 'J': 551 | JEncoder_setJV(o, va_arg(*argList, JVal*), FALSE); 552 | break; 553 | case 'A': 554 | u.len = va_arg(*argList, int); 555 | JEncoder_setArray( 556 | o,*++(*fmt),va_arg(*argList,void*),u.len); 557 | break; 558 | case '[': 559 | (*fmt)++; 560 | JEncoder_beginArray(o); 561 | JEncoder_vSetJV(o, fmt, argList); 562 | JEncoder_endArray(o); 563 | if(**fmt != ']') 564 | { 565 | JErr_setError( 566 | o->err, JErrT_FmtValErr, 567 | "JEncoder::set End of array flag ']' not found"); 568 | return -1; 569 | } 570 | break; 571 | case '{': 572 | (*fmt)++; 573 | JEncoder_beginObject(o); 574 | JEncoder_vSetJV(o, fmt, argList); 575 | JEncoder_endObject(o); 576 | if(**fmt != '}') 577 | { 578 | JErr_setError( 579 | o->err, JErrT_FmtValErr, 580 | "JEncoder::set End of object flag '}' not found"); 581 | return -1; 582 | } 583 | break; 584 | 585 | default: 586 | JErr_setError(o->err, JErrT_FmtValErr, 587 | "JEncoder::set Unknown format flag"); 588 | } 589 | 590 | } 591 | return JErr_noError(o->err) ? 0 : -1; 592 | } 593 | 594 | 595 | int 596 | JEncoder_set(JEncoder* o, const char* fmt, ...) 597 | { 598 | int retVal; 599 | va_list varg; 600 | va_start(varg, fmt); 601 | retVal = JEncoder_vSetJV(o, &fmt, &varg); 602 | if(retVal) /* Can only set error once. Just in case not set */ 603 | JErr_setError(o->err, JErrT_FmtValErr, "?"); 604 | va_end(varg); 605 | return retVal; 606 | } 607 | -------------------------------------------------------------------------------- /inc/JVal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | * 11 | **************************************************************************** 12 | * HEADER 13 | * 14 | * $Id: JVal.h 4915 2021-12-01 18:26:55Z wini $ 15 | * 16 | * COPYRIGHT: Real Time Logic LLC, 2006-2014 17 | * 18 | * This software is copyrighted by and is the sole property of Real 19 | * Time Logic LLC. All rights, title, ownership, or other interests in 20 | * the software remain the property of Real Time Logic LLC. This 21 | * software may only be used in accordance with the terms and 22 | * conditions stipulated in the corresponding license agreement under 23 | * which the software has been supplied. Any unauthorized use, 24 | * duplication, transmission, distribution, or disclosure of this 25 | * software is expressly forbidden. 26 | * 27 | * This Copyright notice may not be removed or modified without prior 28 | * written consent of Real Time Logic LLC. 29 | * 30 | * Real Time Logic LLC. reserves the right to modify this software 31 | * without notice. 32 | * 33 | * http://www.realtimelogic.com 34 | **************************************************************************** 35 | * 36 | */ 37 | 38 | #ifndef __JVal_h 39 | #define __JVal_h 40 | 41 | #include 42 | #include 43 | 44 | /** @addtogroup JSONRef 45 | @{ 46 | */ 47 | 48 | 49 | /** JVal represents a value in a JSON tree. 50 | 51 | An instance of the JParserValFact creates a syntax tree out of the parsed 52 | JSON data. An instance of JVal is one node in the tree. Method 53 | JParserValFact::getFirstVal returns the tree root element. 54 | 55 | Most methods in this class take a JErr as argument. The methods set 56 | an error code if the JVal is not of the expected type or any other 57 | errors occur. 58 | 59 | You can check for errors for each method called, but the methods are 60 | designed such that they abort the operation if the error flag in JErr 61 | is set. Some methods return NULL if an error is detected. You can 62 | check for NULL values, but all methods are designed such that they 63 | accept a NULL "this" pointer. 64 | 65 |

Examples:

66 | 67 | See the JSON tutorial, section 68 | [Using JParserValFact](@ref UsingJParserValFact) 69 | , for examples on how to use JVal. 70 | 71 | */ 72 | struct JVal 73 | { 74 | #ifdef __cplusplus 75 | /** Returns the JSON type. 76 | */ 77 | JVType getType(); 78 | 79 | /** Equivalent to get with variable argument list replaced by argList. 80 | */ 81 | JVal* vget(JErr* err,const char** fmt, va_list* argList); 82 | 83 | /** Get any type of value(s) from a JVal node or JVal tree. 84 | 85 | The get method works in a similar fashion to the ANSI C function 86 | scanf; thus, it performs formatted input conversion. 87 | 88 | The method internally uses the 'getXXX' methods in this class 89 | for extracting the actual value(s), where XXX is Int, Long, etc.. The 90 | following table shows the relationship between the format flags and 91 | the JSON value extracted: 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 |
JSON typeFormat flagC typeMethod
Number d S32*JVal::getInt
Number l S64*JVal::getLong
Number f double*JVal::getDouble
boolean b BaBool*JVal::getBoolean
string s const char**JVal::getString
Any type J JVal**All methods
Start object { n/aJVal::getObject
End object } n/an/a
Start array [ n/aJVal::getArray
End array ] n/an/a
JVal[size] A Array of JValAll getXXX methods
119 | 120 | See the JSON tutorial, section 121 | [Using JParserValFact](@ref UsingJParserValFact) 122 | , for examples on how to use JVal. 123 | 124 | \sa JDecoder::get 125 | \sa JEncoder::set 126 | 127 |

Advanced C Example:

128 | \code 129 | JVal* jForecast[7]; //Array for 7 day forecast 130 | JVal_get(rootVal, 131 | &err, 132 | "{ssdddAJ}", 133 | "city",&city, 134 | "desc",&desc, 135 | "temp",&temp, 136 | "humidity",&humidity, 137 | "dt", &dt, 138 | "list",jForecast,7);//Flag '{A}' requires: member name, list, length 139 | if(JErr_noError(&err)) 140 | { 141 | for(i=0 ; i < 7 && JErr_noError(&err) ; i++) 142 | { 143 | JVal_get(jForecast[i], 144 | &err, 145 | "{dddds}", 146 | "wday",&wday, 147 | "tmax",&tmax, 148 | "tmin",&tmin, 149 | "humidity",&humidity, 150 | "desc",&desc); 151 | } 152 | } 153 | \endcode 154 | */ 155 | JVal* get(JErr* err, const char* fmt, ...); 156 | 157 | /** Returns the integer value for an integer JVal type or 158 | attempts to convert the value to an integer. JErr is set if the 159 | method cannot convert the value. 160 | */ 161 | S32 getInt(JErr* e); 162 | 163 | /** Sets a new integer value or changes the JSON type and sets the 164 | integer value. 165 | */ 166 | void setInt(JErr* e,S32 v); 167 | 168 | /** Returns the integer as a long value for an integer JVal type or 169 | attempts to convert the value to a long integer. JErr is set if the 170 | method cannot convert the value. 171 | */ 172 | S64 getLong(JErr* e); 173 | 174 | /** Sets a new integer value or changes the JSON type and sets the 175 | integer value. 176 | */ 177 | void setLong(JErr* e,S64 v); 178 | 179 | /** Returns the double value for a JVal float or 180 | attempts to convert the value to a float. JErr is set if the 181 | method cannot convert the value. 182 | */ 183 | double getDouble(JErr* e); 184 | 185 | /** Sets a new float value or changes the JSON type to float and sets the 186 | float value. 187 | */ 188 | void setDouble(JErr* e,double v); 189 | 190 | /** Returns the boolean value for a boolean JVal type or false if the 191 | JVal is JVType_Null. JErr is set for all other types. 192 | */ 193 | BaBool getBoolean(JErr* e); 194 | 195 | /** Sets a new boolean value or changes the JSON type and sets the 196 | boolean value. 197 | */ 198 | void setBoolean(JErr* e,BaBool v); 199 | 200 | /** Changes the JSON type if not NULL. 201 | */ 202 | void setNull(JErr* e); 203 | 204 | /** Returns the string as a const or returns NULL if the JVAL is 205 | a NULL type. JErr is set for all other types. 206 | */ 207 | const char* getString(JErr* e); 208 | 209 | /** Sets a string value and changes the JSON type if needed. The 210 | pointer is directly stored and not copied. The string must, 211 | therefore, have been allocated with the dynamic allocator 212 | used by the JVal tree. You cannot set a new string without 213 | managing the old string. 214 | */ 215 | void setString(JErr* e, char* v); 216 | 217 | /** Similar to getString, but you must manage the value as the 218 | value is detached from the tree. 219 | */ 220 | char* manageString(JErr* e); 221 | 222 | /** Returns the member name if this value is part of a JSON object. 223 | */ 224 | const char* getName(); 225 | 226 | /** Similar to getName, but you must manage the value as the 227 | value is detached from the tree. 228 | */ 229 | char* manageName(); 230 | 231 | /** Returns the next element if the parent is an object or an array. 232 | */ 233 | JVal* getNextElem(); 234 | 235 | /** Returns the first child if an object. JErr is set for all 236 | other types. 237 | */ 238 | JVal* getObject(JErr* e); 239 | 240 | /** Returns the first child if an array. JErr is set for all other types. 241 | */ 242 | JVal* getArray(JErr* e); 243 | 244 | /** Returns the first child if an array or object. JErr is set for all 245 | other types. 246 | */ 247 | JVal* getJ(JErr* e); 248 | 249 | /** Similar to getJ, but you must manage the JVal as the 250 | value is detached from the tree. 251 | */ 252 | JVal* manageJ(JErr* e); 253 | 254 | /** Returns the elements left in the list. Returns the number of 255 | childs if called on the value returned by getObject, 256 | getArray, or getJ. 257 | */ 258 | S32 getLength(JErr* e); 259 | 260 | /** Returns true if this is a child element in an object. 261 | Returns false if this is a child element in an array. 262 | */ 263 | bool isObjectMember(); 264 | 265 | /** Remove a child. Typically used together with method terminate. 266 | \param child is the child to remove. 267 | */ 268 | int unlink(JVal* child); 269 | 270 | /** Add a child to an object. 271 | \param e the error container. 272 | \param memberName is the object member name. 273 | \param child is the element to add. 274 | \param dAlloc is the allocator used for copying the memberName. 275 | */ 276 | int addMember(JErr* e, const char* memberName, 277 | JVal* child, AllocatorIntf* dAlloc); 278 | 279 | /** Add a child to an array. 280 | \param e the error container. 281 | \param child is the element to add. 282 | */ 283 | int add(JErr* e, JVal* child); 284 | 285 | /** Terminate the node and all sub nodes. The element to 286 | terminate must be managed. 287 | \param vAlloc is the allocator that was used for allocating 288 | the nodes. 289 | \param dAlloc is the allocator that was used for allocating 290 | the strings. 291 | 292 | \sa unlink manageJ JParserValFact::manageFirstVal 293 | */ 294 | void terminate(AllocatorIntf* vAlloc, AllocatorIntf* dAlloc); 295 | #endif 296 | union 297 | { 298 | struct JVal* firstChild; /* If object or array */ 299 | U8* s; /* If string */ 300 | #ifndef NO_DOUBLE 301 | double f; /* If floating point */ 302 | #endif 303 | S32 d; /* If integer */ 304 | S64 l; /* If long integer */ 305 | BaBool b; /* If true or false */ 306 | } v; 307 | 308 | char* memberName; 309 | struct JVal* next; 310 | JVType type; 311 | }; 312 | 313 | typedef struct JVal JVal; 314 | 315 | #ifdef __cplusplus 316 | extern "C" { 317 | #endif 318 | #define JVal_getType(o) (o)->type 319 | BA_API JVal* JVal_vget(JVal* o,JErr* err,const char** fmt, va_list* argList); 320 | BA_API JVal* JVal_get(JVal* o, JErr* err, const char* fmt, ...); 321 | BA_API S32 JVal_getInt(JVal* o, JErr* e); 322 | BA_API S64 JVal_getLong(JVal* o, JErr* e); 323 | BA_API double JVal_getDouble(JVal* o, JErr* e); 324 | BA_API BaBool JVal_getBoolean(JVal* o, JErr* e); 325 | BA_API const char* JVal_getString(JVal* o, JErr* e); 326 | BA_API char* JVal_manageString(JVal* o, JErr* e); 327 | BA_API const char* JVal_getName(JVal* o); 328 | BA_API char* JVal_manageName(JVal* o); 329 | #define JVal_getNextElem(o) (o)->next 330 | BA_API JVal* JVal_getObject(JVal* o, JErr* e); 331 | BA_API JVal* JVal_getArray(JVal* o, JErr* e); 332 | BA_API JVal* JVal_getJ(JVal* o, JErr* e); 333 | BA_API JVal* JVal_manageJ(JVal* o, JErr* e); 334 | BA_API S32 JVal_getLength(struct JVal* o, JErr* e); 335 | #define JVal_isObjectMember(o) ((o)->memberName != 0) 336 | BA_API int JVal_unlink(JVal* o, JVal* child); 337 | BA_API int JVal_addMember(JVal* o, JErr* e, const char* memberName, 338 | JVal* child, AllocatorIntf* dAlloc); 339 | BA_API int JVal_add(JVal* o, JErr* e, JVal* child); 340 | BA_API void JVal_terminate(JVal* o, AllocatorIntf* vAlloc, 341 | AllocatorIntf* dAlloc); 342 | #define JVal_setInt(o, e, v) JVal_setX(o, e, JVType_Int, &v) 343 | #define JVal_setLong(o, e, v) JVal_setX(o, e, JVType_Long, &v) 344 | #define JVal_setDouble(o, e, v) JVal_setX(o, e, JVType_Double, &v) 345 | #define JVal_setBoolean(o, e, v) JVal_setX(o, e, JVType_Boolean, &v) 346 | #define JVal_setNull(o, e) JVal_setX(o, e, JVType_Null, 0) 347 | #define JVal_setString(o, e, v) JVal_setX(o, e, JVType_String, v) 348 | BA_API void JVal_setX(JVal* o, JErr* e, JVType t, void* v); 349 | #ifdef __cplusplus 350 | } 351 | inline JVType JVal::getType(){ 352 | return JVal_getType(this); } 353 | inline JVal* JVal::vget(JErr* err,const char** fmt, va_list* argList){ 354 | return JVal_vget(this,err,fmt, argList); } 355 | inline JVal* JVal::get( JErr* err, const char* fmt, ...){ 356 | JVal* retv; va_list argList; 357 | va_start(argList, fmt); 358 | retv = JVal_vget(this,err,&fmt,&argList); 359 | va_end(argList); 360 | return retv; 361 | } 362 | inline S32 JVal::getInt(JErr* e){ 363 | return JVal_getInt(this, e); } 364 | inline S64 JVal::getLong(JErr* e){ 365 | return JVal_getLong(this, e); } 366 | inline double JVal::getDouble(JErr* e){ 367 | return JVal_getDouble(this, e); } 368 | inline BaBool JVal::getBoolean(JErr* e){ 369 | return JVal_getBoolean(this, e); } 370 | inline const char* JVal::getString(JErr* e){ 371 | return JVal_getString(this, e); } 372 | inline char* JVal::manageString(JErr* e){ 373 | return JVal_manageString(this, e); } 374 | inline const char* JVal::getName(){ 375 | return JVal_getName(this); } 376 | inline char* JVal::manageName(){ 377 | return JVal_manageName(this); } 378 | inline JVal* JVal::getNextElem(){ 379 | return JVal_getNextElem(this); } 380 | inline JVal* JVal::getObject(JErr* e){ 381 | return JVal_getObject(this, e); } 382 | inline JVal* JVal::getArray(JErr* e){ 383 | return JVal_getArray(this, e); } 384 | inline JVal* JVal::getJ(JErr* e){ 385 | return JVal_getJ(this, e); } 386 | inline JVal* JVal::manageJ(JErr* e){ 387 | return JVal_manageJ(this, e); } 388 | inline S32 JVal::getLength(JErr* e){ 389 | return JVal_getLength(this, e); } 390 | 391 | inline void JVal::setInt(JErr* e,S32 val) { 392 | JVal_setInt(this, e, val); } 393 | inline void JVal::setLong(JErr* e,S64 val) { 394 | JVal_setLong(this, e, val); } 395 | inline void JVal::setDouble(JErr* e,double val) { 396 | JVal_setDouble(this, e, val); } 397 | inline void JVal::setBoolean(JErr* e,BaBool val) { 398 | JVal_setBoolean(this, e, val); } 399 | inline void JVal::setNull(JErr* e) { 400 | JVal_setNull(this, e); } 401 | inline void JVal::setString(JErr* e, char* val) { 402 | JVal_setString(this, e, val); } 403 | inline bool JVal::isObjectMember(){ 404 | return JVal_isObjectMember(this) ? true : false; } 405 | inline int JVal::unlink(JVal* child){ 406 | return JVal_unlink(this, child); } 407 | inline int JVal::addMember(JErr* e, const char* name, 408 | JVal* child, AllocatorIntf* dAlloc) { 409 | return JVal_addMember(this, e, name, child, dAlloc); } 410 | inline int JVal::add(JErr* e, JVal* child) { 411 | return JVal_add(this, e, child); } 412 | inline void JVal::terminate(AllocatorIntf* vAlloc, AllocatorIntf* dAlloc){ 413 | JVal_terminate(this, vAlloc, dAlloc); } 414 | #endif 415 | 416 | /** @} */ /* end of JSONRef */ 417 | 418 | /** @addtogroup JSONCB 419 | @{ 420 | */ 421 | 422 | typedef enum 423 | { 424 | JParserValFactStat_OK=0, 425 | JParserValFactStat_DMemErr, 426 | JParserValFactStat_VMemErr, 427 | JParserValFactStat_MaxNodes 428 | } JParserValFactStat; 429 | 430 | /** JParserValFact is the JVal JSON parser factory class. An instance 431 | of this class is connected to an instance of the JParser. The 432 | JParser communicates with the JVal factory when parsing JSON, and 433 | the JVal factory creates JVal objects. 434 | 435 | Method getFirstVal returns the first value in the syntax tree. 436 | 437 | The class automatically manages the nodes allocated. The allocated 438 | nodes are automatically de-allocated when the destructor runs. You 439 | can manage the values by calling JParserValFact::manageFirstVal or 440 | by calling JVal::manageJ on any of the children. 441 | 442 | \sa JValFact 443 | \sa JDecode 444 | */ 445 | #ifdef __cplusplus 446 | typedef struct JParserValFact : public JParserIntf 447 | { 448 | /** create a JParserValFact JVal factory instance. 449 | \param vAlloc is used when allocating nodes. 450 | \param dAlloc is used when allocating strings. The two 451 | allocators can be the same. 452 | */ 453 | JParserValFact(AllocatorIntf* vAlloc, AllocatorIntf* dAlloc); 454 | 455 | /** The destructor terminates all nodes not managed. 456 | */ 457 | ~JParserValFact(); 458 | 459 | /** Returns the root of the JVal syntax tree. 460 | */ 461 | JVal* getFirstVal(); 462 | 463 | /** Similar to getFirstVal, but you must manage the JVal tree as the 464 | value is detached from the JParserValFact. 465 | */ 466 | JVal* manageFirstVal(); 467 | 468 | /** Terminate the syntax tree such that the JParserValFact 469 | instance can be reused when the JParser instance parses the 470 | next JSON object in a stream. 471 | */ 472 | void termFirstVal(); 473 | #else 474 | typedef struct JParserValFact 475 | { 476 | JParserIntf super; /*Inherits from JParserIntf*/ 477 | #endif 478 | AllocatorIntf* dAlloc; 479 | AllocatorIntf* vAlloc; 480 | JVal** vStack; 481 | int vStackSize; 482 | U32 nodeCounter; 483 | U32 maxNodes; 484 | JParserValFactStat status; 485 | } JParserValFact; 486 | #ifdef __cplusplus 487 | extern "C" { 488 | #endif 489 | BA_API void JParserValFact_constructor( 490 | JParserValFact* o, AllocatorIntf* vAlloc, AllocatorIntf* dAlloc); 491 | #define JParserValFact_getFirstVal(o) \ 492 | ((o)->vStack && *(o)->vStack ? *(o)->vStack : 0) 493 | BA_API JVal* JParserValFact_manageFirstVal(JParserValFact* o); 494 | BA_API void JParserValFact_termFirstVal(JParserValFact* o); 495 | BA_API void JParserValFact_destructor(JParserValFact* o); 496 | #ifdef __cplusplus 497 | } 498 | inline JParserValFact::JParserValFact( 499 | AllocatorIntf* vAlloc, AllocatorIntf* dAlloc){ 500 | JParserValFact_constructor(this, vAlloc, dAlloc);} 501 | inline JVal* JParserValFact::getFirstVal() { 502 | return JParserValFact_getFirstVal(this); } 503 | inline JVal* JParserValFact::manageFirstVal() { 504 | return JParserValFact_manageFirstVal(this); } 505 | inline void JParserValFact::termFirstVal() { 506 | JParserValFact_termFirstVal(this); } 507 | inline JParserValFact::~JParserValFact() { 508 | JParserValFact_destructor(this); } 509 | #endif 510 | 511 | /** @} */ /* end of JSONCB */ 512 | 513 | /** @addtogroup JSONRef 514 | @{ 515 | */ 516 | 517 | /** The JValFact enables one to manually create a JVal syntax tree or 518 | add nodes to an existing syntax tree. 519 | 520 | \sa JParserValFact 521 | */ 522 | typedef struct JValFact 523 | { 524 | #ifdef __cplusplus 525 | /** create a JValFact JVal factory instance. 526 | \param vAlloc is used when allocating nodes. 527 | \param dAlloc is used when allocating strings. The two 528 | allocators can be the same. 529 | */ 530 | JValFact(AllocatorIntf* vAlloc, AllocatorIntf* dAlloc); 531 | 532 | /** Make a string. Returns null if the allocators failed. 533 | */ 534 | JVal* mkString(const char* v); 535 | 536 | /** Make a float. Returns null if the allocator failed. 537 | */ 538 | JVal* mkDouble(double v); 539 | 540 | /** Make an integer. Returns null if the allocator failed. 541 | */ 542 | JVal* mkInt(S32 v); 543 | 544 | /** Make a long integer. Returns null if the allocator failed. 545 | */ 546 | JVal* mkLong(S64 v); 547 | 548 | /** Make a boolean. Returns null if the allocator failed. 549 | */ 550 | JVal* mkBoolean(bool v); 551 | 552 | /** Make a null value. Returns null if the allocator failed. 553 | */ 554 | JVal* mkNull(); 555 | 556 | /** Make a JSON object. Returns null if the allocator failed. 557 | */ 558 | JVal* mkObject(); 559 | 560 | /** Make a JSON array. Returns null if the allocator failed. 561 | */ 562 | JVal* mkArray(); 563 | #endif 564 | AllocatorIntf* dAlloc; 565 | AllocatorIntf* vAlloc; 566 | } JValFact; 567 | #ifdef __cplusplus 568 | extern "C" { 569 | #endif 570 | #define JValFact_mkString(o, v) JValFact_mkVal(o, JVType_String, v) 571 | #define JValFact_mkDouble(o, v) JValFact_mkVal(o, JVType_Double, &v) 572 | #define JValFact_mkInt(o, v) JValFact_mkVal(o, JVType_Int, &v) 573 | #define JValFact_mkLong(o, v) JValFact_mkVal(o, JVType_Long, &v) 574 | #define JValFact_mkBoolean(o, v) JValFact_mkVal(o, JVType_Boolean, &v) 575 | #define JValFact_mkNull(o) JValFact_mkVal(o, JVType_Null, 0) 576 | #define JValFact_mkObject(o) JValFact_mkVal(o, JVType_Object, 0) 577 | #define JValFact_mkArray(o) JValFact_mkVal(o, JVType_Array, 0) 578 | BA_API void JValFact_constructor( 579 | JValFact* o, AllocatorIntf* vAlloc, AllocatorIntf* dAlloc); 580 | BA_API JVal* JValFact_mkVal(JValFact* o, JVType t, const void* uv); 581 | #ifdef __cplusplus 582 | } 583 | inline JValFact::JValFact(AllocatorIntf* vAlloc, AllocatorIntf* dAlloc) { 584 | JValFact_constructor(this,vAlloc, dAlloc); } 585 | inline JVal* JValFact::mkString(const char* v) { 586 | return JValFact_mkString(this, v); } 587 | inline JVal* JValFact::mkDouble(double v) { 588 | return JValFact_mkDouble(this, v); } 589 | inline JVal* JValFact::mkInt(S32 v) { 590 | return JValFact_mkInt(this, v); } 591 | inline JVal* JValFact::mkLong(S64 v) { 592 | return JValFact_mkLong(this, v); } 593 | inline JVal* JValFact::mkBoolean(bool v) { 594 | BaBool b = v ? TRUE : FALSE; 595 | return JValFact_mkBoolean(this, b); } 596 | inline JVal* JValFact::mkNull() { 597 | return JValFact_mkNull(this); } 598 | inline JVal* JValFact::mkObject() { 599 | return JValFact_mkObject(this); } 600 | inline JVal* JValFact::mkArray() { 601 | return JValFact_mkArray(this); } 602 | #endif 603 | 604 | /** @} */ /* end of JSONRef */ 605 | 606 | #endif 607 | -------------------------------------------------------------------------------- /src/JVal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ____ _________ __ _ 3 | * / __ \___ ____ _/ /_ __(_)___ ___ ___ / / ____ ____ _(_)____ 4 | * / /_/ / _ \/ __ `/ / / / / / __ `__ \/ _ \/ / / __ \/ __ `/ / ___/ 5 | * / _, _/ __/ /_/ / / / / / / / / / / / __/ /___/ /_/ / /_/ / / /__ 6 | * /_/ |_|\___/\__,_/_/ /_/ /_/_/ /_/ /_/\___/_____/\____/\__, /_/\___/ 7 | * /____/ 8 | * 9 | * Barracuda Application Server 10 | **************************************************************************** 11 | * PROGRAM MODULE 12 | * 13 | * $Id: JVal.c 4914 2021-12-01 18:24:30Z wini $ 14 | * 15 | * COPYRIGHT: Real Time Logic, 2006 - 2018 16 | * 17 | * This software is copyrighted by and is the sole property of Real 18 | * Time Logic LLC. All rights, title, ownership, or other interests in 19 | * the software remain the property of Real Time Logic LLC. This 20 | * software may only be used in accordance with the terms and 21 | * conditions stipulated in the corresponding license agreement under 22 | * which the software has been supplied. Any unauthorized use, 23 | * duplication, transmission, distribution, or disclosure of this 24 | * software is expressly forbidden. 25 | * 26 | * This Copyright notice may not be removed or modified without prior 27 | * written consent of Real Time Logic LLC. 28 | * 29 | * Real Time Logic LLC. reserves the right to modify this software 30 | * without notice. 31 | * 32 | * http://www.realtimelogic.com 33 | **************************************************************************** 34 | * 35 | */ 36 | 37 | #ifndef BA_LIB 38 | #define BA_LIB 1 39 | #endif 40 | #include 41 | #include 42 | 43 | 44 | /**************************************************************************** 45 | JVal 46 | JSON value 47 | ****************************************************************************/ 48 | 49 | static void JVal_extractArray( 50 | JVal* o,JErr* err,const char flag,void* array,int len); 51 | static void JVal_extractObject( 52 | JVal* o,JErr* err,const char** fmt,va_list* argList); 53 | static JVal* JVal_extract( 54 | JVal* o,JErr* err,const char** fmt, va_list* argList); 55 | 56 | 57 | 58 | static int 59 | JVal_init(JVal* o, JVal* parent, JParserVal* pv, AllocatorIntf* dAlloc) 60 | { 61 | memset(o, 0, sizeof(JVal)); 62 | if(*pv->memberName) 63 | { 64 | o->memberName = baStrdup2(dAlloc, pv->memberName); 65 | if( ! o->memberName ) 66 | return -1; 67 | } 68 | switch(pv->t) 69 | { 70 | case JParserT_String: 71 | o->type = JVType_String; 72 | o->v.s = (U8*)baStrdup2(dAlloc, (char*)pv->v.s); 73 | if( ! o->v.s ) 74 | { 75 | if(o->memberName) 76 | AllocatorIntf_free(dAlloc, o->memberName); 77 | return -1; 78 | } 79 | break; 80 | case JParserT_Double: 81 | #ifdef NO_DOUBLE 82 | baAssert(0); 83 | #else 84 | o->v.f=pv->v.f; 85 | #endif 86 | o->type = JVType_Double; 87 | break; 88 | case JParserT_Int: 89 | o->v.d=pv->v.d; 90 | o->type = JVType_Int; 91 | break; 92 | case JParserT_Long: 93 | o->v.l=pv->v.l; 94 | o->type = JVType_Long; 95 | break; 96 | case JParserT_Boolean: 97 | o->v.b=pv->v.b; 98 | o->type = JVType_Boolean; 99 | break; 100 | case JParserT_Null: 101 | o->type = JVType_Null; 102 | break; 103 | case JParserT_BeginObject: 104 | o->type = JVType_Object; 105 | break; 106 | case JParserT_BeginArray: 107 | o->type = JVType_Array; 108 | break; 109 | default: 110 | baAssert(0); 111 | } 112 | if(parent) 113 | { 114 | if(parent->v.firstChild) 115 | { 116 | JVal* iter = parent->v.firstChild; 117 | while(iter->next) 118 | iter = iter->next; 119 | iter->next = o; 120 | } 121 | else 122 | parent->v.firstChild = o; 123 | } 124 | return 0; 125 | } 126 | 127 | 128 | static int 129 | JVal_extractValue(JVal* o, 130 | JErr* err, 131 | const char** fmt, 132 | va_list* argList) 133 | { 134 | union 135 | { 136 | BaBool* b; 137 | S32* d; 138 | S64* l; 139 | double* f; 140 | const char** s; 141 | void* p; 142 | JVal** j; 143 | } u; 144 | switch(**fmt) 145 | { 146 | case 'b': 147 | u.b = va_arg(*argList, BaBool*); 148 | *u.b = JVal_getBoolean(o, err); 149 | return 0; 150 | case 'd': 151 | u.d = va_arg(*argList, S32*); 152 | *u.d = JVal_getInt(o, err); 153 | return 0; 154 | case 'l': 155 | u.l = va_arg(*argList, S64*); 156 | *u.l = JVal_getLong(o, err); 157 | return 0; 158 | #ifndef NO_DOUBLE 159 | case 'f': 160 | u.f = va_arg(*argList, double*); 161 | *u.f = JVal_getDouble(o, err); 162 | return 0; 163 | #endif 164 | case 's': 165 | u.s = va_arg(*argList, const char**); 166 | *u.s = JVal_getString(o, err); 167 | return 0; 168 | case 'J': 169 | u.j = va_arg(*argList, JVal**); 170 | *u.j = o; 171 | return 0; 172 | case 'A': 173 | u.p = va_arg(*argList, void*); 174 | JVal_extractArray(JVal_getArray(o,err), 175 | err, 176 | *++(*fmt), 177 | u.p, 178 | va_arg(*argList, int)); 179 | return 0; 180 | case '[': 181 | (*fmt)++; 182 | JVal_extract(JVal_getArray(o,err),err,fmt,argList); 183 | if(**fmt != ']') 184 | { 185 | JErr_setError(err, JErrT_FmtValErr, 186 | "End of array flag ']' not found"); 187 | return 1; 188 | } 189 | return 0; 190 | case ']': 191 | return 1; 192 | case '{': 193 | (*fmt)++; 194 | JVal_extractObject( 195 | JVal_getObject(o,err),err,fmt,argList); 196 | return 0; 197 | case '}': 198 | return 1; 199 | 200 | default: 201 | JErr_setError(err, JErrT_FmtValErr, 202 | "Unknown format flag"); 203 | } 204 | return -1; 205 | } 206 | 207 | 208 | static void 209 | JVal_extractArray(JVal* o, 210 | JErr* err, 211 | const char flag, 212 | void* array, 213 | int len) 214 | { 215 | int i; 216 | if(!o) 217 | return; 218 | for(i = 0 ; i < len ; i++) 219 | { 220 | if(!o) 221 | JErr_setTooFewParams(err); 222 | if(JErr_isError(err)) 223 | return; 224 | switch(flag) 225 | { 226 | case 'b': 227 | ((BaBool*)array)[i] = JVal_getBoolean(o, err); 228 | break; 229 | case 'd': 230 | ((S32*)array)[i] = JVal_getInt(o, err); 231 | break; 232 | case 'l': 233 | ((S64*)array)[i] = JVal_getLong(o, err); 234 | break; 235 | #ifndef NO_DOUBLE 236 | case 'f': 237 | ((double*)array)[i] = JVal_getDouble(o, err); 238 | break; 239 | #endif 240 | case 's': 241 | ((const char**)array)[i] = JVal_getString(o, err); 242 | break; 243 | case 'J': 244 | ((JVal**)array)[i] = o; 245 | break; 246 | 247 | default: 248 | JErr_setError( 249 | err, JErrT_FmtValErr, 250 | "Unknown or illegal format flag in array flag 'A'"); 251 | } 252 | o = JVal_getNextElem(o); 253 | } 254 | } 255 | 256 | 257 | static void 258 | JVal_extractObject(JVal* o,JErr* err,const char** fmt,va_list* argList) 259 | { 260 | if(!o) 261 | return; 262 | for( ; **fmt && **fmt != '}' && JErr_noError(err) ; (*fmt)++) 263 | { 264 | const char* n; 265 | const char* name = va_arg(*argList, const char*); 266 | JVal* iter = o; 267 | while(iter && (n = JVal_getName(iter))!=0 && strcmp(name,n) ) 268 | iter = JVal_getNextElem(iter); 269 | if(!iter) 270 | { 271 | JErr_setError(err, JErrT_InvalidMethodParams, 272 | "Member name not found in object"); 273 | return; 274 | } 275 | if(JVal_extractValue(iter, 276 | err, 277 | fmt, 278 | argList)) 279 | { 280 | JErr_setError( 281 | err, JErrT_FmtValErr, 282 | "Detected mismatched object and array format flags"); 283 | return; 284 | } 285 | 286 | } 287 | if(**fmt != '}') 288 | { 289 | JErr_setError( 290 | err, JErrT_FmtValErr, 291 | "Format error: End of object '}' not found"); 292 | } 293 | } 294 | 295 | 296 | static JVal* 297 | JVal_extract(JVal* o,JErr* err,const char** fmt, va_list* argList) 298 | { 299 | for( ; **fmt ; (*fmt)++) 300 | { 301 | if(JErr_isError(err)) 302 | return 0; 303 | if(JVal_extractValue(o, err, fmt, argList)) 304 | break; 305 | if(!o) 306 | { 307 | JErr_setTooFewParams(err); 308 | return 0; 309 | } 310 | o = JVal_getNextElem(o); 311 | } 312 | return o; 313 | } 314 | 315 | 316 | JVal* 317 | JVal_vget(JVal* o,JErr* err,const char** fmt, va_list* argList) 318 | { 319 | o = JVal_extract(o,err,fmt,argList); 320 | if(**fmt) 321 | { 322 | JErr_setTooFewParams(err); 323 | return 0; 324 | } 325 | return o; 326 | } 327 | 328 | 329 | 330 | JVal* 331 | JVal_get(JVal* o, JErr* err, const char* fmt, ...) 332 | { 333 | JVal* retVal; 334 | va_list varg; 335 | va_start(varg, fmt); 336 | retVal = JVal_vget(o, err, &fmt, &varg); 337 | va_end(varg); 338 | return retVal; 339 | } 340 | 341 | S32 342 | JVal_getInt(JVal* o, JErr* e) 343 | { 344 | if(o) 345 | { 346 | if(o->type == JVType_Int) 347 | return o->v.d; 348 | #ifndef NO_DOUBLE 349 | if(o->type == JVType_Double) 350 | return (S32)o->v.f; 351 | #endif 352 | if(o->type == JVType_Long) 353 | return (S32)o->v.l; 354 | else if(o->type == JVType_Boolean) 355 | return (S32)o->v.b; 356 | else if(o->type == JVType_Null) 357 | return 0; 358 | JErr_setTypeErr(e, JVType_Int, o->type); 359 | } 360 | else 361 | JErr_setTooFewParams(e); 362 | return 0; 363 | } 364 | 365 | 366 | S64 367 | JVal_getLong(JVal* o, JErr* e) 368 | { 369 | if(o) 370 | { 371 | if(o->type == JVType_Long) 372 | return o->v.l; 373 | #ifndef NO_DOUBLE 374 | if(o->type == JVType_Double) 375 | return (S64)o->v.f; 376 | #endif 377 | if(o->type == JVType_Int) 378 | return (S64)o->v.d; 379 | else if(o->type == JVType_Boolean) 380 | return (S64)o->v.b; 381 | else if(o->type == JVType_Null) 382 | return 0; 383 | JErr_setTypeErr(e, JVType_Long, o->type); 384 | } 385 | else 386 | JErr_setTooFewParams(e); 387 | return 0; 388 | } 389 | 390 | #ifndef NO_DOUBLE 391 | double 392 | JVal_getDouble(JVal* o, JErr* e) 393 | { 394 | if(o) 395 | { 396 | if(o->type == JVType_Double) 397 | return o->v.f; 398 | if(o->type == JVType_Int) 399 | return (double)o->v.d; 400 | if(o->type == JVType_Long) 401 | return (double)o->v.l; 402 | else if(o->type == JVType_Boolean) 403 | return (double)o->v.b; 404 | else if(o->type == JVType_Null) 405 | return 0; 406 | JErr_setTypeErr(e, JVType_Double, o->type); 407 | } 408 | else 409 | JErr_setTooFewParams(e); 410 | return 0; 411 | } 412 | #endif 413 | 414 | BaBool 415 | JVal_getBoolean(JVal* o, JErr* e) 416 | { 417 | if(o) 418 | { 419 | if(o->type == JVType_Boolean) 420 | return o->v.b; 421 | else if(o->type == JVType_Null) 422 | return FALSE; 423 | JErr_setTypeErr(e, JVType_Boolean, o->type); 424 | } 425 | else 426 | JErr_setTooFewParams(e); 427 | return FALSE; 428 | } 429 | 430 | 431 | const char* 432 | JVal_getString(JVal* o, JErr* e) 433 | { 434 | if(o) 435 | { 436 | if(o->type == JVType_String) 437 | return (char*)o->v.s; 438 | else if(o->type == JVType_Null) 439 | return 0; 440 | JErr_setTypeErr(e, JVType_String, o->type); 441 | } 442 | else 443 | JErr_setTooFewParams(e); 444 | return 0; 445 | } 446 | 447 | 448 | char* 449 | JVal_manageString(JVal* o, JErr* e) 450 | { 451 | if(o) 452 | { 453 | if(o->type == JVType_String) 454 | { 455 | char* ptr = (char*)o->v.s; 456 | o->v.s=0; 457 | return ptr; 458 | } 459 | JErr_setTypeErr(e, JVType_String, o->type); 460 | } 461 | else 462 | JErr_setTooFewParams(e); 463 | return 0; 464 | } 465 | 466 | const char* 467 | JVal_getName(JVal* o) 468 | { 469 | return o ? o->memberName : 0; 470 | } 471 | 472 | char* 473 | JVal_manageName(JVal* o) 474 | { 475 | if(o) 476 | { 477 | char* ptr = o->memberName; 478 | o->memberName=0; 479 | return ptr; 480 | } 481 | return 0; 482 | } 483 | 484 | JVal* 485 | JVal_getObject(JVal* o, JErr* e) 486 | { 487 | if(o) 488 | { 489 | if(o->type == JVType_Object) 490 | return o->v.firstChild; 491 | JErr_setTypeErr(e, JVType_Object, o->type); 492 | } 493 | else 494 | JErr_setTooFewParams(e); 495 | return 0; 496 | } 497 | 498 | JVal* 499 | JVal_getArray(JVal* o, JErr* e) 500 | { 501 | if(o) 502 | { 503 | if(o->type == JVType_Array) 504 | return o->v.firstChild; 505 | JErr_setTypeErr(e, JVType_Array, o->type); 506 | } 507 | else 508 | JErr_setTooFewParams(e); 509 | return 0; 510 | } 511 | 512 | 513 | JVal* 514 | JVal_getJ(JVal* o, JErr* e) 515 | { 516 | if(o) 517 | { 518 | if(o->type == JVType_Array || o->type == JVType_Object) 519 | return o->v.firstChild; 520 | JErr_setTypeErr(e, JVType_Object, o->type); 521 | } 522 | else 523 | JErr_setTooFewParams(e); 524 | return 0; 525 | } 526 | 527 | 528 | JVal* 529 | JVal_manageJ(JVal* o, JErr* e) 530 | { 531 | if(o) 532 | { 533 | if(o->type == JVType_Array || o->type == JVType_Object) 534 | { 535 | JVal* retVal = o->v.firstChild; 536 | o->v.firstChild=0; 537 | return retVal; 538 | } 539 | JErr_setTypeErr(e, JVType_Object, o->type); 540 | } 541 | else 542 | JErr_setTooFewParams(e); 543 | return 0; 544 | } 545 | 546 | 547 | S32 548 | JVal_getLength(struct JVal* o, JErr* e) 549 | { 550 | o = JVal_getJ(o, e); 551 | if(o) 552 | { 553 | S32 len=1; 554 | while( (o = JVal_getNextElem(o)) != 0) 555 | len++; 556 | return len; 557 | } 558 | return 0; /* NULL means array/object is zero in length */ 559 | } 560 | 561 | 562 | void 563 | JVal_setX(JVal* o, JErr* e, JVType t, void* v) 564 | { 565 | if(o->type == JVType_Array || o->type == JVType_Object) 566 | { 567 | JErr_setTypeErr(e, o->type, t); 568 | return; 569 | } 570 | if(o->type == JVType_String && o->v.s) 571 | { 572 | JErr_setError(e,JErrT_MemErr, "JVal::setX string must be managed"); 573 | return; 574 | } 575 | o->type = t; 576 | switch(t) 577 | { 578 | case JVType_String: 579 | o->v.s=(U8*)v; 580 | break; 581 | case JVType_Double: 582 | #ifdef NO_DOUBLE 583 | o->v.l=*((S64*)v); 584 | #else 585 | o->v.f=*((double*)v); 586 | #endif 587 | break; 588 | case JVType_Int: 589 | o->v.d=*((S32*)v); 590 | break; 591 | case JVType_Long: 592 | o->v.l=*((S64*)v); 593 | break; 594 | case JVType_Boolean: 595 | o->v.b = *((BaBool*)v) ? TRUE : FALSE; 596 | break; 597 | case JVType_Null: 598 | break; 599 | default: 600 | baAssert(0); 601 | 602 | } 603 | } 604 | 605 | 606 | int 607 | JVal_unlink(JVal* o, JVal* child) 608 | { 609 | if( (o->type == JVType_Object || o->type == JVType_Array) && 610 | o->v.firstChild ) 611 | { 612 | JVal* iter; 613 | if(child == o->v.firstChild) 614 | { 615 | o->v.firstChild = child->next; 616 | child->next=0; 617 | return 0; 618 | } 619 | iter = o->v.firstChild; 620 | while(iter->next && iter->next != child) 621 | iter = iter->next; 622 | if(iter->next) 623 | { 624 | iter->next = child->next; 625 | child->next=0; 626 | return 0; 627 | } 628 | } 629 | return -1; 630 | } 631 | 632 | static int 633 | JVal_addChild(JVal* o, JVal* child) 634 | { 635 | if(child->next) 636 | return -1; 637 | child->next=o->v.firstChild; 638 | o->v.firstChild=child; 639 | return 0; 640 | } 641 | 642 | 643 | int 644 | JVal_addMember(JVal* o, JErr* e, const char* memberName, 645 | JVal* child, AllocatorIntf* dAlloc) 646 | { 647 | if(JErr_noError(e)) 648 | { 649 | if(o->type == JVType_Object) 650 | { 651 | if( ! child->memberName ) 652 | { 653 | child->memberName = 654 | dAlloc ? baStrdup2(dAlloc, memberName) : (char*)memberName; 655 | } 656 | if(child->memberName) 657 | return JVal_addChild(o, child); 658 | JErr_setError(e,JErrT_MemErr,0); 659 | } 660 | else 661 | JErr_setTypeErr(e, JVType_Int, o->type); 662 | } 663 | return -1; 664 | } 665 | 666 | 667 | int 668 | JVal_add(JVal* o, JErr* e, JVal* child) 669 | { 670 | if(JErr_noError(e)) 671 | { 672 | if(o->type == JVType_Array) 673 | return JVal_addChild(o, child); 674 | JErr_setTypeErr(e, JVType_Int, o->type); 675 | } 676 | return -1; 677 | } 678 | 679 | 680 | void 681 | JVal_terminate(JVal* o, AllocatorIntf* vAlloc, AllocatorIntf* dAlloc) 682 | { 683 | while(o) 684 | { 685 | JVal* next = o->next; 686 | if(o->type == JVType_Object || o->type == JVType_Array) 687 | JVal_terminate(o->v.firstChild, vAlloc, dAlloc); 688 | else if(o->type == JVType_String) 689 | AllocatorIntf_free(dAlloc, o->v.s); 690 | if(o->memberName) 691 | AllocatorIntf_free(dAlloc, o->memberName); 692 | AllocatorIntf_free(vAlloc, o); 693 | o = next; 694 | } 695 | } 696 | 697 | 698 | 699 | /**************************************************************************** 700 | JParserValFact 701 | JSON Value Factory for JParser 702 | ****************************************************************************/ 703 | 704 | static int 705 | JParserValFact_expandStack(JParserValFact* o) 706 | { 707 | size_t newSize = (o->vStackSize + 32) * sizeof(void*); 708 | JVal** v = o->vStack ? 709 | AllocatorIntf_realloc(o->dAlloc, o->vStack, &newSize) : 710 | AllocatorIntf_malloc(o->dAlloc, &newSize); 711 | if(v) 712 | { 713 | o->vStack = v; 714 | o->vStackSize=(int)(newSize/sizeof(void*)); 715 | return 0; 716 | } 717 | o->status=JParserValFactStat_DMemErr; 718 | return -1; 719 | } 720 | 721 | 722 | static int 723 | JParserValFact_service(JParserIntf* super, JParserVal* pv, int recLevel) 724 | { 725 | JVal* v; 726 | size_t jValSize = sizeof(JVal); 727 | JParserValFact* o = (JParserValFact*)super; /* upcast from base class */ 728 | if(pv->t == JParserT_EndObject || pv->t == JParserT_EndArray) 729 | return 0; /* Nothing to do */ 730 | if(++o->nodeCounter >= o->maxNodes) 731 | { 732 | o->status=JParserValFactStat_MaxNodes; 733 | return -1; 734 | } 735 | if(recLevel >= o->vStackSize && JParserValFact_expandStack(o)) 736 | return -1; 737 | if( (v = AllocatorIntf_malloc(o->vAlloc, &jValSize)) == 0 ) 738 | { 739 | o->status=JParserValFactStat_VMemErr; 740 | return -1; 741 | } 742 | if(JVal_init(v, recLevel ? o->vStack[recLevel-1] : 0, pv, o->dAlloc)) 743 | { 744 | o->status=JParserValFactStat_VMemErr; 745 | AllocatorIntf_free(o->vAlloc, v); 746 | return -1; 747 | } 748 | if(pv->t == JParserT_BeginObject || pv->t == JParserT_BeginArray) 749 | o->vStack[recLevel] = v; 750 | return 0; 751 | } 752 | 753 | 754 | void 755 | JParserValFact_constructor( 756 | JParserValFact* o, AllocatorIntf* vAlloc, AllocatorIntf* dAlloc) 757 | { 758 | memset(o, 0, sizeof(JParserValFact)); 759 | o->vAlloc=vAlloc; 760 | o->dAlloc=dAlloc; 761 | JParserIntf_constructor((JParserIntf*)o, JParserValFact_service); 762 | o->maxNodes=~(U32)0; 763 | } 764 | 765 | 766 | JVal* 767 | JParserValFact_manageFirstVal(JParserValFact* o) 768 | { 769 | if(o->vStack && *o->vStack) 770 | { 771 | JVal* v = *o->vStack; 772 | *o->vStack = 0; 773 | o->nodeCounter=0; 774 | return v; 775 | } 776 | return 0; 777 | } 778 | 779 | 780 | void 781 | JParserValFact_termFirstVal(JParserValFact* o) 782 | { 783 | if(o->vStack) 784 | { 785 | if(o->vStack) 786 | { 787 | JVal_terminate(*o->vStack, o->vAlloc, o->dAlloc); 788 | *o->vStack=0; 789 | o->nodeCounter=0; 790 | } 791 | AllocatorIntf_free(o->dAlloc, o->vStack); 792 | o->vStack=0; 793 | o->vStackSize=0; 794 | } 795 | } 796 | 797 | 798 | void 799 | JParserValFact_destructor(JParserValFact* o) 800 | { 801 | JParserValFact_termFirstVal(o); 802 | } 803 | 804 | 805 | 806 | /**************************************************************************** 807 | JValFact 808 | JSON Value Factory 809 | ****************************************************************************/ 810 | 811 | void 812 | JValFact_constructor(JValFact* o, AllocatorIntf* vAlloc, AllocatorIntf* dAlloc) 813 | { 814 | memset(o, 0, sizeof(JValFact)); 815 | o->vAlloc=vAlloc; 816 | o->dAlloc=dAlloc; 817 | } 818 | 819 | 820 | JVal* 821 | JValFact_mkVal(JValFact* o, JVType t, const void* uv) 822 | { 823 | size_t size=sizeof(JVal); 824 | JVal* v = (JVal*)AllocatorIntf_malloc(o->vAlloc,&size); 825 | if(v) 826 | { 827 | memset(v,0,sizeof(JVal)); 828 | v->type = t; 829 | switch(t) 830 | { 831 | case JVType_String: 832 | v->v.s=(U8*)baStrdup2(o->dAlloc, (const char*)uv); 833 | if(!v->v.s) 834 | t = JVType_InvalidType; 835 | break; 836 | case JVType_Double: 837 | #ifdef NO_DOUBLE 838 | v->v.l=*((S64*)uv); 839 | #else 840 | v->v.f=*((double*)uv); 841 | #endif 842 | break; 843 | case JVType_Int: 844 | v->v.d=*((S32*)uv); 845 | break; 846 | case JVType_Long: 847 | v->v.l=*((S64*)uv); 848 | break; 849 | case JVType_Boolean: 850 | v->v.b = *((BaBool*)uv) ? TRUE : FALSE; 851 | break; 852 | case JVType_Null: 853 | case JVType_Object: 854 | case JVType_Array: 855 | break; 856 | default: 857 | baAssert(0); 858 | t = JVType_InvalidType; 859 | } 860 | if(t != JVType_InvalidType) 861 | return v; 862 | AllocatorIntf_free(o->vAlloc, v); 863 | } 864 | return 0; 865 | } 866 | --------------------------------------------------------------------------------