├── src
├── CMakeLists.txt
├── cli
│ ├── wje
│ ├── CMakeLists.txt
│ ├── wjecli.h
│ └── wjecli.c
├── lib
│ ├── CMakeLists.txt
│ └── xpl.c
├── wjreader
│ └── CMakeLists.txt
├── wjwriter
│ ├── CMakeLists.txt
│ └── wjwriter.c
└── wjelement
│ ├── CMakeLists.txt
│ ├── hash.c
│ ├── element.h
│ └── element.c
├── include
├── CMakeLists.txt
├── nmutil.h
├── memmgr.h
├── wjwriter.h
├── xpl.h
├── wjreader.h
└── wjelement.h
├── example
├── Makefile
├── layout.json
├── layout.schema
├── example.c
└── validate.c
├── pkg-config.pc.cmake
├── README_PlanetLabs.md
├── INSTALL
├── .gitignore
├── cmake_uninstall.cmake.in
├── COPYING.MIT
├── windows
├── wjelement.sln
├── wjelement-VC100.sln
├── wjelement.vcproj
└── wjelement-VC100.vcxproj
├── README
├── README.md
├── Makefile-all
├── documentation
├── index.html
├── wjwriter.html
├── wjreader.html
└── wjelement.html
├── CMakeLists.txt
└── COPYING.LESSER
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_subdirectory(lib)
2 | add_subdirectory(wjreader)
3 | add_subdirectory(wjwriter)
4 | add_subdirectory(wjelement)
5 | add_subdirectory(cli)
6 |
--------------------------------------------------------------------------------
/src/cli/wje:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | dir=`dirname $0`
4 |
5 | which rlwrap > /dev/null
6 | if [ $? == 0 ]; then
7 | rlwrap -pred $dir/wjecli $@
8 | else
9 | $dir/wjecli $@
10 | fi
11 |
--------------------------------------------------------------------------------
/include/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | FILE(GLOB INCLUDES_HEADERS *.h )
2 | LIST(REMOVE_ITEM INCLUDES_HEADERS ${PROJECT_SOURCE_DIR}/include/config.h)
3 | INSTALL(FILES ${INCLUDES_HEADERS} DESTINATION include/)
4 |
--------------------------------------------------------------------------------
/example/Makefile:
--------------------------------------------------------------------------------
1 | TARGET=validate
2 | TARGET2=example
3 |
4 | all:
5 | gcc -o ${TARGET} ${TARGET}.c -lwjelement -lwjreader
6 | gcc -o ${TARGET2} ${TARGET2}.c -lwjelement -lwjreader
7 |
8 | clean:
9 | rm ${TARGET} ${TARGET2}
10 |
--------------------------------------------------------------------------------
/example/layout.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "layout",
3 | "headers": {
4 | "msg_id": "DSCS1385112923586"
5 | },
6 | "obj": {
7 | "name": "test",
8 | "status": "draft",
9 | "orientation": "landscape",
10 | "widget": []
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/pkg-config.pc.cmake:
--------------------------------------------------------------------------------
1 | Name: wjelement
2 | Description: ${PROJECT_DESCRIPTION}
3 | Version: ${PROJECT_VERSION}
4 | Requires: ${PKG_CONFIG_REQUIRES}
5 | prefix=${CMAKE_INSTALL_PREFIX}
6 | includedir=${PKG_CONFIG_INCLUDEDIR}
7 | libdir=${PKG_CONFIG_LIBDIR}
8 | Libs: ${PKG_CONFIG_LIBS}
9 | Cflags: ${PKG_CONFIG_CFLAGS}
10 |
--------------------------------------------------------------------------------
/src/cli/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_executable(wjecli wjecli.c wjecli.h cmds.c)
2 |
3 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ALL_CFLAGS} ${PTHREAD_CFLAGS} ${OPENSSL_CFLAGS}")
4 |
5 | target_link_libraries(wjecli
6 | wjelement
7 | )
8 |
9 | install(TARGETS wjecli DESTINATION bin)
10 | install(PROGRAMS wje DESTINATION bin)
11 |
12 |
--------------------------------------------------------------------------------
/README_PlanetLabs.md:
--------------------------------------------------------------------------------
1 |
2 | Upstream: https://github.com/netmail-open/wjelement
3 |
4 | Packaging as a .deb in debuild/wjelement (package wjelement-pl)
5 |
6 | This package is used by plcompositor for JSON parsing and schema validation.
7 |
8 | This repo was cloned by Frank Warmerdam, and is lightly modified from
9 | upstream for clean building.
10 |
11 |
--------------------------------------------------------------------------------
/src/lib/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(xpl
2 | xpl.c
3 | )
4 |
5 | target_link_libraries(xpl
6 | ${ALL_LIBS}
7 | )
8 |
9 | SET_TARGET_PROPERTIES(
10 | xpl
11 | PROPERTIES
12 | VERSION 1.0.0
13 | SOVERSION 1
14 | INSTALL_NAME_DIR "${LIB_DEST_DIR}"
15 | )
16 |
17 | install(TARGETS xpl
18 | LIBRARY DESTINATION ${LIB_DEST_DIR}
19 | ARCHIVE DESTINATION ${LIB_DEST_DIR}
20 | )
21 |
--------------------------------------------------------------------------------
/src/wjreader/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(wjreader
2 | wjreader.c
3 | )
4 |
5 | target_link_libraries(wjreader
6 | xpl
7 | ${ALL_LIBS}
8 | )
9 |
10 | SET_TARGET_PROPERTIES(
11 | wjreader
12 | PROPERTIES
13 | VERSION 1.0.0
14 | SOVERSION 1
15 | INSTALL_NAME_DIR "${LIB_DEST_DIR}"
16 | )
17 |
18 | install(TARGETS wjreader
19 | LIBRARY DESTINATION ${LIB_DEST_DIR}
20 | ARCHIVE DESTINATION ${LIB_DEST_DIR}
21 | )
22 |
--------------------------------------------------------------------------------
/src/wjwriter/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(wjwriter
2 | wjwriter.c
3 | )
4 |
5 | target_link_libraries(wjwriter
6 | xpl
7 | ${ALL_LIBS}
8 | )
9 | #link_directories($(MPLUS_GUARDIAN_BINARY_DIR)/src/libs/wjwriter)
10 |
11 | SET_TARGET_PROPERTIES(
12 | wjwriter
13 | PROPERTIES
14 | VERSION 1.0.0
15 | SOVERSION 1
16 | INSTALL_NAME_DIR "${LIB_DEST_DIR}"
17 | )
18 |
19 |
20 | install(TARGETS wjwriter
21 | LIBRARY DESTINATION ${LIB_DEST_DIR}
22 | ARCHIVE DESTINATION ${LIB_DEST_DIR}
23 | )
24 |
--------------------------------------------------------------------------------
/INSTALL:
--------------------------------------------------------------------------------
1 | Compile and install WJElement:
2 |
3 | $ ccmake . #change settings if desired, 'c'onfigure and 'g'enerate
4 | $ cmake -DLIB_DEST_DIR=/usr/local/lib64 #set lib path if needed
5 | $ make
6 | # make install
7 |
8 | You may also use:
9 | $ cmake-gui .
10 | instead of ccmake.
11 |
12 |
13 | Use it in your program:
14 |
15 | #include
9 | WJElement - JSON manipulation in C
10 |
12 | WJElement is a very flexible JSON library developed by Messaging Architects.
13 | It was created for MA's "WARP" webserver, and is built on top of the
14 | (also-included) lower-level WJReader and WJWriter libraries.
15 |
17 | About
8 |
18 |
36 |
26 |
34 |
40 | WJElement and its related libraries may be consumed in any project, 41 | open or closed, as outlined by the 42 | GNU Lesser 43 | General Public License (any version). 44 | Include it as-is and link to it 45 | from your code, massage it into your own statically-linked package, or use it 46 | in ways we haven't thought of. Read the docs/headers, have fun, and if you 47 | use it for something awesome, let us know about it! :^) 48 |
49 | 50 |52 |
73 | In the spirit of being upfront, and to help you guage whether WJElement is 74 | right for you without asking you to invest too much time, there are a few 75 | things to note about this library: 76 |
77 |78 |
116 | You are free and encouraged to add and contribute features if 117 | you are so inclined. In some cases, there are comments or even empty code 118 | blocks, just waiting to be filled in. WJElement is great, but you can make it 119 | even better! 120 |
121 | 122 |124 |
11 | The WARP JSON Writer provides the ability to easily write a JSON document to 12 | a stream. All data formatting is done automatically. 13 |
14 | 15 |17 | WJWriter 18 | is The WJWriter document, the library's primary structure 19 |
20 |21 | From wjwriter.h: 22 |
23 | typedef struct {
24 | XplBool pretty;
25 |
26 | /*
27 | Base may be set to 8, 10 (default), or 16. Using a base other than 10
28 | will result in a non standard JSON document which may not be read
29 | properly by all parsers.
30 | */
31 | int base;
32 |
33 | struct {
34 | void *data;
35 | WJWriteCallback cb;
36 | } write;
37 |
38 | struct {
39 | void *data;
40 | void (* freecb)(void *data);
41 | } user;
42 | } WJWriterPublic;
43 | typedef WJWriterPublic* WJWriter;
44 |
45 |
46 | 47 | WJWriteCallback 48 | - Generic data writer (to file, socket, encoder, etc.) 49 |
50 |51 |
54 | 55 | 56 |52 | typedef size_t (* WJWriteCallback)(char *data, size_t size, void *writedata); 53 |
59 | WJWOpenDocument 60 | - Open a stream that is ready to accept a JSON document. 61 |
62 |63 |
69 | 70 |64 | WJWriter WJWOpenDocument(XplBool pretty, WJWriteCallback callback, 65 | void *writeData); 66 | WJWriter _WJWOpenDocument(XplBool pretty, WJWriteCallback callback, 67 | void *writedata, size_t buffersize); 68 |
71 | A callback function 72 | must be provided which will be used to write data as it is ready. 73 |
74 |75 | A buffersize of 0 will disable write buffering entirely. The write buffer 76 | used will be at least the size requested, but may be larger. 77 |
78 |79 | WJWOpenFILEDocument 80 | - helper to write to an open FILE *. 81 |
82 |83 |
86 | 87 |84 | WJWriter WJWOpenFILEDocument(XplBool pretty, FILE *file); 85 |
88 | An alternative method of opening a JSON document for writing, which will 89 | provide a proper callback for writing the data to an open FILE *. 90 |
91 |92 | WJWCloseDocument 93 | - Close a WJWriter document 94 |
95 |96 |
99 | 100 |97 | XplBool WJWCloseDocument(WJWriter doc); 98 |
102 | WJWOpenArray 103 | - Open an array. 104 |
105 |106 |
109 | 110 |107 | XplBool WJWOpenArray(char *name, WJWriter doc); 108 |
111 | All objects that are direct children of the array MUST NOT 112 | be named. A value of NULL should be passed as name for any such values. 113 |
114 |115 | When all values of the array have been written it can be closed with 116 | WJWCloseArray(). 117 |
118 |119 | WJWCloseArray 120 | - Close an array. 121 |
122 |123 |
126 | 127 |124 | XplBool WJWCloseArray(WJWriter doc); 125 |
128 | WJWOpenObject 129 | - Open an object. 130 |
131 |132 |
135 | 136 |133 | XplBool WJWOpenObject(char *name, WJWriter doc); 134 |
137 | Open an object. All objects that are direct children of the object MUST be 138 | named. A value of NULL should NOT be passed as name for any such values. 139 |
140 |141 | When all values of the object have been written it can be closed with 142 | WJWCloseObject(). 143 |
144 |145 | WJWCloseObject 146 | - Close an object. 147 |
148 |149 |
152 | 153 |150 | XplBool WJWCloseObject(WJWriter doc); 151 |
155 | These WJWriter functions 156 | write a value to the document. If any values are written that are a direct 157 | child of an object then a non-NULL name MUST be provided. If any values are 158 | written that are a direct child of an array then a non-NULL name MUST NOT be 159 | provided. 160 |
161 |162 | A string value may be written in multiple pieces. A JSON string will be 163 | started with the first call to WJWString, or WJWStringN and the string will 164 | not be completed until the "done" argument is set to TRUE or there is a call 165 | to write a non-string type value. 166 |
167 |168 |
180 | 181 |169 | XplBool WJWStringN(char *name, char *value, size_t length, XplBool done, WJWriter doc); 170 | XplBool WJWString(char *name, char *value, XplBool done, WJWriter doc); 171 | XplBool WJWBoolean(char *name, XplBool value, WJWriter doc); 172 | XplBool WJWNull(char *name, WJWriter doc); 173 | 174 | XplBool WJWInt32(char *name, int32 value, WJWriter doc); 175 | XplBool WJWUInt32(char *name, uint32 value, WJWriter doc); 176 | XplBool WJWInt64(char *name, int64 value, WJWriter doc); 177 | XplBool WJWUInt64(char *name, uint64 value, WJWriter doc); 178 | XplBool WJWDouble(char *name, double value, WJWriter doc); 179 |
182 | WJWRawValue 183 | - Write a raw, pre-formatted value to the document. 184 |
185 |186 |
189 | 190 |187 | XplBool WJWRawValue(char *name, char *value, XplBool done, WJWriter doc); 188 |
191 | It is up to the caller to 192 | ensure that the data is properly formatted and complete. 193 |
194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /include/xpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of WJElement. 3 | 4 | WJElement is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU Lesser General Public License as published 6 | by the Free Software Foundation. 7 | 8 | WJElement is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU Lesser General Public License for more details. 12 | 13 | You should have received a copy of the GNU Lesser General Public License 14 | along with WJElement. If not, see11 | The WARP JSON Reader provides the ability to parse a JSON document as a 12 | stream. All parsing is done with a portion of the document loaded into a 13 | buffer, and the buffer is reloaded as needed. 14 |
15 |16 | This allows the parser to be very fast, but does require that data in the 17 | document is accessed in the order of the document. 18 |
19 | 20 |22 | WJReader 23 | is The WJReader document, the library's primary structure 24 |
25 |26 | From wjreader.h: 27 |
28 | typedef struct {
29 | uint32 depth;
30 | uint32 maxdepth;
31 | void *userdata;
32 | } WJReaderPublic;
33 | typedef WJReaderPublic * WJReader;
34 |
35 |
36 | 37 | WJRType 38 | specifies the type of a value being read. 39 |
40 |41 | From wjreader.h: 42 |
43 | typedef enum {
44 | WJR_TYPE_OBJECT = 'O',
45 | WJR_TYPE_ARRAY = 'A',
46 |
47 | WJR_TYPE_STRING = 'S',
48 | WJR_TYPE_NUMBER = 'N',
49 |
50 | WJR_TYPE_BOOL = 'B',
51 | WJR_TYPE_TRUE = 'T',
52 | WJR_TYPE_FALSE = 'F',
53 | WJR_TYPE_NULL = '0',
54 |
55 | WJR_TYPE_UNKNOWN = '?'
56 | } WJRType;
57 |
58 |
59 | 60 | WJReadCallback 61 | - Generic data reader (from file, socket, decoder, etc.) 62 |
63 |64 |
67 | 68 | 69 |65 | typedef size_t (* WJReadCallback)(char *data, size_t length, size_t seen, void *userdata); 66 |
72 | WJROpenDocument 73 | - Open a JSON document and prepare to parse. 74 |
75 |76 |
82 | 83 |77 | WJReader WJROpenDocument(WJReadCallback callback, void *userdata, char *buffer, 78 | size_t buffersize); 79 | WJReader _WJROpenDocument(WJReadCallback callback, void *userdata, char *buffer, 80 | size_t buffersize, uint32 maxdepth); 81 |
84 | A callback function must be 85 | provided which will be used to read data as it is needed. The callback is 86 | expected to load data into the provided buffer and return the number of 87 | bytes that where loaded. If the number of bytes loaded is less than the 88 | requested length then it is assumed that the end of the document has been 89 | reached. 90 |
91 |92 | If a buffer is provided to WJROpenDocument() then that buffer will be used, 93 | rather than allocating a new buffer. The size of the buffer must be 94 | provided as buffersize. If a buffer is not provided then one will be 95 | allocated of size buffersize. 96 |
97 |98 | If a buffersize of 0 is passed to WJROpenDocument then the default size will 99 | be used (4KB). Some data is kept in the buffer while parsing, such as 100 | element names and values. If the buffer is not large enough for these then 101 | the document will fail to be parsed and will be aborted. 102 |
103 |104 | WJROpenFILEDocument 105 | - helper to read from an open FILE *. 106 |
107 |108 |
111 | 112 |109 | WJReader WJROpenFILEDocument(FILE *jsonfile, char *buffer, size_t buffersize); 110 |
113 | An alternative method of opening a JSON document, which will provide a 114 | proper callback for reading the data from an open FILE *. 115 |
116 |117 | As with the standard WJROpenDocument() a buffersize of 0 will use the 118 | default buffer size. 119 |
120 |121 | WJROpenMemDocument 122 | - helper to read from memory. 123 |
124 |125 |
128 | 129 |126 | WJReader WJROpenMemDocument(char *json, char *buffer, size_t buffersize); 127 |
130 | An alternative method of opening a JSON document, which will provide a 131 | proper callback for reading from a pre-allocated buffer in memory. 132 |
133 |134 | As with the standard WJROpenDocument() a buffersize of 0 will use the 135 | default buffer size. 136 |
137 |138 | WJRCloseDocument 139 | - Close a WJReader document. 140 |
141 |142 |
145 | 146 |143 | XplBool WJRCloseDocument(WJReader doc); 144 |
148 | WJRNext 149 | - Get the type and name of the next element in 'doc'. 150 |
151 |152 |
155 | 156 |153 | char * WJRNext(char *parent, size_t maxnamelen, WJReader doc); 154 |
157 | Returns a string, which contains the name of the next element of the 158 | specified parent, prefixed by a single character that represents the type. 159 | The pointer returned may be used as the parent argument in future calls to 160 | WJRNext() in order to return the children of the current object. 161 |
162 |163 | If the object's name is larger than the maxnamelen argument then it will be 164 | truncated. 165 |
166 |167 | These WJReader functions 168 | Return the value of the last object returned by WJRNext(). The calling 169 | application is expected to know the type of the value, and call the 170 | appropriate function. When possible the value will be converted if it does 171 | not match the requested type. 172 |
173 |174 | If the buffer is not large enough to contain the entire value then the 175 | WJRString() function may return a partial value. It may be called multiple 176 | times until a NULL is returned to ensure that the entire value has been 177 | read. 178 |
179 |180 |
191 | 192 |181 | char * WJRString(XplBool *complete, WJReader doc); 182 | char * WJRStringEx(XplBool *complete, size_t *length, WJReader doc); 183 | XplBool WJRBoolean(WJReader doc); 184 | 185 | int32 WJRInt32(WJReader doc); 186 | uint32 WJRUInt32(WJReader doc); 187 | int64 WJRInt64(WJReader doc); 188 | uint64 WJRUInt64(WJReader doc); 189 | double WJRDouble(WJReader doc); 190 |
193 | WJRNegative 194 | - Check whether the current WJR_TYPE_NUMBER value is negative 195 |
196 |197 |
200 | 201 |198 | XplBool WJRNegative(WJReader doc); 199 |
202 | If the current element is a WJR_TYPE_NUMBER then this function can be used 203 | to determine if the value is negative or positive. If negative then TRUE 204 | will be returned. 205 |
206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /COPYING.LESSER: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc.11 | The WJElement interfaces allow you to load an entire JSON document into 12 | memory and to then access elements within it more easily. 13 |
14 |15 | WJElement uses UTF-8 encoding internally, as do the underlying 16 | WJReader 17 | and 18 | WJWriter. 19 | libraries. 20 | Adding other unicode support to WJR/WJW would not take too much work. 21 |
22 |23 | WJElement is thread-safe, though an individual WJElement document and its 24 | children should not be used across threads without locking. WJElement does 25 | not provide locking, but its structure provides a handy client pointer which 26 | you may use for this or any other purpose. 27 |
28 | 29 |31 | WJElement 32 | is the main structure used for JSON documents. In most circumstances 33 | it will not be necessary to access anything within such a structure directly, 34 | but there are times when peeking at a JSON object's name or type (and other 35 | properties) comes in handy. 36 |
37 |38 | From wjelement.h: 39 |
40 | typedef struct WJElementPublic {
41 | char *name;
42 | WJRType type;
43 |
44 | struct WJElementPublic *next;
45 | struct WJElementPublic *prev;
46 |
47 | struct WJElementPublic *child;
48 | struct WJElementPublic *parent;
49 |
50 | /* The number of children */
51 | int count;
52 |
53 | /*
54 | A count of changes that have been performed on this element, which can
55 | be reset by the consumer.
56 | */
57 | int changes;
58 |
59 | void *client;
60 |
61 | /*
62 | If set then this freecb will be called before actually free'ing a
63 | WJElement. If it returns FALSE then the WJElement will NOT be free'd.
64 |
65 | This can be used to allow caching of objects. If used in this way then
66 | the consumer that set the callback is responsible for ensuring that it
67 | does get free'd correctly at the correct time.
68 | */
69 | XplBool (* freecb)(struct WJElementPublic *);
70 | } WJElementPublic;
71 | typedef WJElementPublic * WJElement;
72 |
73 |
74 | 75 | WJEAction 76 | specifies which operation to carry out when calling the JSON manipulation 77 | functions. 78 |
79 |80 | From wjelement.h: 81 |
82 | typedef enum {
83 | WJE_GET = 0,
84 | WJE_SET,
85 | WJE_NEW,
86 | WJE_MOD
87 | } WJEAction;
88 |
89 |
90 | 91 |
152 | WJEParse 153 | - Parse the provided JSON document and return the new WJElement 154 |
155 |156 |
160 | 161 |157 | WJElement WJEParse(const char *json); 158 | WJElement _WJEParse(const char *json, char quote); 159 |
162 | The _WJEParse version can be used to parse a document with a non-standard 163 | quote character. This allows easy parsing of simple documents directly in a 164 | C source file without having to escape double quote characters. Example: 165 |
166 | doc = _WJEParse("{ 'foo': true, 'bar': 'yup' }", '\'');
167 |
168 |
169 | 170 | WJEOpenDocument 171 | - Load a WJElement object from the provided 172 | WJReader 173 |
174 |175 |
178 | 179 |176 | WJElement WJEOpenDocument(WJReader reader, char *where, WJELoadCB loadcb, void *data); 177 |
180 | If a load callback is provided then it will be called before adding any new 181 | children, allowing the consumer to leave specific elements of the hierarchy. 182 |
183 |184 | WJEWriteDocument 185 | - Write a WJElement object to the provided 186 | WJWriter 187 |
190 | 191 |188 | XplBool WJEWriteDocument(WJElement document, WJWriter writer, char *name); 189 |
192 | WJEWriteFILE 193 | - Write a WJElement object to the provided FILE* 194 |
197 | 198 |195 | void WJEWriteFILE(WJElement document, FILE* fd); 196 |
199 | WJEWriteFILE() requires an already opened FILE* to write to. 200 | It is also used internally by WJEDump() 201 |
202 | 203 |204 | WJEWriteMEM 205 | - Allocate and write to a string 206 |
209 | 210 |207 | char * WJEWriteMEM(WJElement document, XplBool pretty, size_t maxlength); 208 |
211 | WJEWriteMEM() allocates and returns a string containing the document. 212 | A maxlength of 0 means the string may be of unlimited length. 213 | The returned string must be freed with MemFree by the consumer. 214 |
215 | 216 |217 | WJECloseDocument 218 | - Destroy a WJElement object 219 |
220 |221 |
224 | 225 |222 | XplBool WJECloseDocument(WJElement document); 223 |
226 | WJECloseDocument is also used to delete/remove an item from a parent document: 227 | WJECloseDocument(WJEGet(...)); 228 |
229 |230 | WJECopyDocument 231 | - Duplicate an existing WJElement 232 |
233 |234 |
237 | 238 |235 | WJElement WJECopyDocument(WJElement to, WJElement from, WJECopyCB loadcb, void *data); 236 |
239 | If a copy callback is provided, then it will be called with each element in 240 | order to allow filtered copying on an element-by-element basis, using any 241 | criteria. 242 |
243 |244 | WJECopyDocument is normally used to create a new copy or to populate a new, 245 | empty document, but that is not required or enforced. If "to" is already 246 | populated, WJEMergeObjects is probably the desired function for copying in 247 | other contents. 248 |
249 |250 | WJEDetach 251 | - Remove a WJElement from it's parent (and siblings) 252 |
253 |254 |
257 | 258 |255 | XplBool WJEDetach(WJElement document); 256 |
259 | WJEAttach 260 | - Add a document to another document as a child 261 |
262 |263 |
266 | 267 |264 | XplBool WJEAttach(WJElement container, WJElement document); 265 |
268 | WJERename 269 | - Rename an element 270 |
271 |272 |
275 | 276 |273 | XplBool WJERename(WJElement document, const char *name); 274 |
277 | WJEMergeObjects 278 | - Merge all fields from one object to another 279 |
280 |281 |
284 | 285 |282 | XplBool WJEMergeObjects(WJElement to, WJElement from, XplBool overwrite); 283 |
287 | All JSON manipulation functions take a 'path' argument. This is a string as 288 | explained below, see WJElement Selectors 289 |
290 |291 | Functions which take a 'last' parameter allow enumeration of multiple 292 | matching elements, if non-NULL is passed. Handy for looping through objects 293 | and arrays. 294 |
295 |296 | WJEGet 297 | - Find the first element within the hierarchy of a WJElement that matches the 298 | specified path. 299 |
300 |301 |
304 | 305 |302 | WJElement WJEGet(WJElement container, char *path, WJElement last); 303 |
306 | In cases where a direct child of the WJElement is needed, 307 | WJEChild may be more suitable, especially if the child's 308 | name begins with a non-alphanumeric character. 309 |
310 |311 | WJEBool 312 | - Access a boolean element 313 |
314 |315 |
319 | 320 |316 | XplBool WJEBool(WJElement container, char *path, WJEAction action, XplBool value); 317 | XplBool _WJEBool(WJElement container, char *path, WJEAction action, WJElement *last, XplBool value); 318 |
321 | WJEString, WJEStringN 322 | - Access a string element 323 |
324 |325 |
332 | 333 |326 | char * WJEString(WJElement container, char *path, WJEAction action, char *value); 327 | char * _WJEString(WJElement container, char *path, WJEAction action, WJElement *last, char *value); 328 | 329 | char * WJEStringN(WJElement container, char *path, WJEAction action, char *value, size_t len); 330 | char * _WJEStringN(WJElement container, char *path, WJEAction action, WJElement *last, char *value, size_t len); 331 |
334 | WJEObject 335 | - Access an object element 336 |
337 |338 |
342 | 343 |339 | WJElement WJEObject(WJElement container, char *path, WJEAction action); 340 | WJElement _WJEObject(WJElement container, char *path, WJEAction action, WJElement *last); 341 |
344 | WJEArray 345 | - Access an array element 346 |
347 |348 |
352 | 353 |349 | WJElement WJEArray(WJElement container, char *path, WJEAction action); 350 | WJElement _WJEArray(WJElement container, char *path, WJEAction action, WJElement *last); 351 |
354 | WJENull 355 | - Access a null element 356 |
357 |358 |
362 | 363 |359 | WJElement WJENull(WJElement container, char *path, WJEAction action); 360 | WJElement _WJENull(WJElement container, char *path, WJEAction action, WJElement *last); 361 |
364 | WJEInt32 365 | - Access a number element, as a 32-bit integer 366 |
367 |368 |
372 | 373 |369 | int32 WJEInt32(WJElement container, char *path, WJEAction action, int32 value); 370 | int32 _WJEInt32(WJElement container, char *path, WJEAction action, WJElement *last, int32 value); 371 |
374 | WJEUInt32 375 | - Access a number element, as a 32-bit unsigned integer 376 |
377 |378 |
382 | 383 |379 | uint32 WJEUInt32(WJElement container, char *path, WJEAction action, uint32 value); 380 | uint32 _WJEUInt32(WJElement container, char *path, WJEAction action, WJElement *last, uint32 value); 381 |
384 | WJEInt64 385 | - Access a number element, as a 64-bit integer 386 |
387 |388 |
392 | 393 |389 | int64 WJEInt64(WJElement container, char *path, WJEAction action, int64 value); 390 | int64 _WJEInt64(WJElement container, char *path, WJEAction action, WJElement *last, int64 value); 391 |
394 | WJEUInt64 395 | - Access a number element, as a 64-bit unsigned integer 396 |
397 |398 |
402 | 403 |399 | uint64 WJEUInt64(WJElement container, char *path, WJEAction action, uint64 value); 400 | uint64 _WJEUInt64(WJElement container, char *path, WJEAction action, WJElement *last, uint64 value); 401 |
404 | WJEDouble 405 | - Access a number element, as a double (as in double-precision floating point) 406 |
407 |408 |
412 | 413 |409 | double WJEDouble(WJElement container, char *path, WJEAction action, double value); 410 | double _WJEDouble(WJElement container, char *path, WJEAction action, WJElement *last, double value); 411 |
414 | WJE...F variants 415 | - Format-capable versions of element functions 416 |
417 |418 | The following functions... 419 |
440 | 441 |438 | val = WJENumberF(doc, WJE_GET, NULL, 0, "foo[%d]", x); 439 |
442 | WJEChild 443 | - Find, create or update an element by name instead of path. This allows 444 | access to elements that would be difficult to reference by path. No selector 445 | syntax is used, so only direct children of the element can be found. 446 |
447 |448 |
451 | 452 |449 | WJElement WJEChild(WJElement container, char *name, WJEAction action); 450 |
453 | Type specific actions may be done by passing the resulting WJElement and a 454 | NULL path to WJEBool(), WJENumber(), WJEString(), WJEObject(), WJEArray() or 455 | WJENull(). 456 |
457 |459 | WJEHash 460 | - Calculate a hash for a document 461 |
462 |463 |
467 | 468 |464 | typedef int (* WJEHashCB)(void *context, void *data, size_t size); 465 | EXPORT void WJEHash(WJElement document, WJEHashCB update, void *context); 466 |
470 | Callbacks: 471 |
472 |473 |
479 | 480 |474 | typedef WJElement (* WJESchemaLoadCB)(const char *name, void *client, const char *file, const int line); 475 | typedef void (* WJESchemaFreeCB)(WJElement schema, void *client); 476 | typedef void (* WJESchemaMatchCB)(WJElement schema, const char *selector, void *client); 477 | typedef void (* WJEErrCB)(void *client, const char *format, ...); 478 |
481 | WJESchemaLoadCB callbacks are used to fetch schema as needed. 482 | WJESchemaFreeCB are called when schema is no longer needed. 483 |
484 |485 | WJESchemaValidate 486 | - Validate a document against a given schema. 487 |
488 |489 |
494 | 495 |490 | XplBool WJESchemaValidate(WJElement schema, WJElement document, 491 | WJEErrCB err, WJESchemaLoadCB load, 492 | WJESchemaFreeCB freecb, void *client); 493 |
496 | Additional schema will be loaded 497 | via the load callback if needed. Any validation errors will be reported, 498 | printf-style, to errcb.
499 |500 | If a the load callback is used to acquire schema but a NULL free callback is 501 | provided, WJECloseDocument will be used internally to release it. 502 |
503 |504 | WJESchemaIsType 505 | - Determine if a document implements a specific schema. 506 |
507 |508 |
513 | 514 |509 | XplBool WJESchemaIsType(WJElement document, const char *type, 510 | WJESchemaLoadCB loadcb, WJESchemaFreeCB freecb, 511 | void *client); 512 |
515 | Additional schema will be loaded via the load callback if needed. 516 |
517 |518 | If a load callback is not provided then the object type will still be checked 519 | but it will not be considered a match if it is a type that extends the 520 | specifed type. 521 |
522 |523 | WJESchemaNameIsType 524 | - variation of WJESchemaIsType which acts on schema name instead of a document 525 |
526 |527 |
532 | 533 |528 | XplBool WJESchemaNameIsType(const char *describedby, const char *type, 529 | WJESchemaLoadCB loadcb, 530 | WJESchemaFreeCB freecb, void *client); 531 |
534 | WJESchemaGetSelectors 535 | - find type/format-matching properties 536 |
537 |538 |
545 | 546 |539 | void WJESchemaGetSelectors(WJElement document, 540 | char *type, char *format, 541 | WJESchemaLoadCB load, 542 | WJESchemaFreeCB freecb, 543 | WJESchemaMatchCB matchcb, void *client); 544 |
547 | WJESchemaGetSelectors 548 | calls back matchcb for each WJElement selector which will fetch a property 549 | of a given type and format, from a given document. The load callback will be 550 | used to load all necessary schema, starting with the document's "describedby". 551 | stripat-type wildcards may be used; "Date*" will find "date" and "date-time". 552 |
553 |554 | WJESchemaGetAllSelectors 555 | - variation of WJESchemaGetSelectors which provides selectors that 556 | could exist in objects of the given "describedby" schema name 557 |
558 |559 |
566 | 567 |560 | void WJESchemaGetAllSelectors(char *describedby, 561 | char *type, char *format, 562 | WJESchemaLoadCB load, 563 | WJESchemaFreeCB freecb, 564 | WJESchemaMatchCB matchcb, void *client); 565 |
568 | WJESchemaFindBacklink 569 | - find "backlink" property by schema 570 |
571 |572 |
577 | 578 |573 | char * WJESchemaFindBacklink(WJElement document, const char *format, 574 | WJESchemaLoadCB loadcb, WJESchemaFreeCB freecb, 575 | void *client); 576 |
579 | WJESchemaNameFindBacklink 580 | - find "backlink" property by name 581 |
582 |583 |
588 | 589 |584 | char * WJESchemaNameFindBacklink(char *describedby, const char *format, 585 | WJESchemaLoadCB loadcb, WJESchemaFreeCB freecb, 586 | void *client); 587 |
590 | WJESchemaFreeBacklink 591 | - clean up a previously-found backlink 592 |
593 |594 |
597 | 598 |595 | void WJESchemaFreeBacklink(char *backlink); 596 |
600 | WJEDump 601 | - write a document to stdout 602 |
603 |604 |
607 | 608 | 609 |605 | void WJEDump(WJElement document); 606 |
611 | Elements within the hierarchy of a JSON document can be referenced using a 612 | path. Multiple levels of hierarchy can be referenced to find any element 613 | below the provided container. The following rules apply to any WJE 614 | functions that take a path argument. 615 |
616 |617 | A child may be referenced with an alpha-numeric name, or a subscript within 618 | square brackets: 619 |
624 | 625 |620 | foo 621 | ["foo"] 622 | ["$foo"] 623 |
626 | Additional levels of heirarchy can be referenced by appending an additional 627 | subscript, or appending a dot and an additional alpha-numeric name: 628 |
632 | 633 |629 | one.two.three.four 630 | one["two"]["three"].four 631 |
634 | Subscripts may contain double quoted names. Any special characters, 635 | (including .[]*?"'\) can be included by prefixing with a \. 636 |
640 | 641 |637 | foo["bar.smeg"] 638 | foo["something with a \"quote\""] 639 |
642 | Subscripts may contain single quoted names, which behave as double quoted 643 | names but also allow for * and ? wild card substitution: 644 |
647 | 648 |645 | foo['bar.*'] 646 |
649 | Subscripts may reference an item by it's offset in an array (or object): 650 |
654 | 655 |651 | foo[0] 652 | foo[3] 653 |
656 | Negative offsets are wrapped to the end of the array (or object) meaning 657 | that [-1] references the last item. 658 |
659 |660 | Subscripts may reference a range of offsets by providing 2 offsets seperated 661 | by a colon: 662 |
665 | 666 |663 | foo[2:5] 664 |
667 | Subscripts may reference a set of items by seperating offsets, offset, 668 | ranges, double quoted and single quoted values: 669 |
672 | 673 |670 | foo[2,4:6,'bar.*', "smeg"] 671 |
674 | An empty subscript may be specified to reference all children. 675 |
678 | 679 |676 | [] 677 |
680 | A subscript of $ may be specified in actions perform creations to reference 681 | the item after the end of an array. This allows appending to an array. 682 |
685 | 686 |683 | [$] 684 |
687 | A subscript may be prefixed by an | character to indicate that the subscript 688 | is optional. The portion of the selector from the | on will be ignored if 689 | there is a match and that match has no children. 690 |
691 |692 | For example, if an element named foo may either be a string or an array of 693 | strings you can enumerate all values using a selector of: 694 |
697 | 698 |695 | foo|[] 696 |
699 | A NULL path refers to the container itself. 700 |
701 |702 | A path may end in a condition. The condition consists of an operator and a 703 | value. The value may be a number, a double quoted string, or a single 704 | quoted string. If a single quoted string is used it may contain * and ? 705 | wild cards. 706 |
707 |708 | The following operators are supported for any value: 709 |
712 | 713 |710 | ==, != 711 |
714 | A number value may also use the following operators: 715 |
718 | 719 |716 | <, >, <=, >= 717 |
720 | Example: 721 |
726 |722 | foo.bar <= 3 723 | foo.bar != 'foo*' 724 | foo.bar != "one" 725 |
727 | A condition may be separated from a path with a ; character. 728 |
729 |730 | In the following examples the object named "foo" will be returned if it has 731 | a child named "bar" that matches the condition. 732 |
737 | 738 | 739 | 740 | 741 | --------------------------------------------------------------------------------733 | foo; bar <= 3 734 | foo; bar != 'foo*' 735 | foo; bar != "one" 736 |