[144] | 1 | /*
|
---|
| 2 | Copyright (c) 2001, Interactive Matter, Marcus Nowotny
|
---|
| 3 |
|
---|
| 4 | Based on the cJSON Library, Copyright (C) 2009 Dave Gamble
|
---|
| 5 |
|
---|
| 6 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
---|
| 7 | of this software and associated documentation files (the "Software"), to deal
|
---|
| 8 | in the Software without restriction, including without limitation the rights
|
---|
| 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
| 10 | copies of the Software, and to permit persons to whom the Software is
|
---|
| 11 | furnished to do so, subject to the following conditions:
|
---|
| 12 |
|
---|
| 13 | The above copyright notice and this permission notice shall be included in
|
---|
| 14 | all copies or substantial portions of the Software.
|
---|
| 15 |
|
---|
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
---|
| 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
| 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
---|
| 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
---|
| 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
---|
| 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
---|
| 22 | THE SOFTWARE.
|
---|
| 23 | */
|
---|
| 24 |
|
---|
| 25 | #ifndef aJson__h
|
---|
| 26 | #define aJson__h
|
---|
| 27 |
|
---|
| 28 | #include <Print.h>
|
---|
| 29 | #include <Stream.h>
|
---|
| 30 | #include <Client.h>
|
---|
| 31 | #include <Arduino.h> // To get access to the Arduino millis() function
|
---|
| 32 |
|
---|
| 33 | /******************************************************************************
|
---|
| 34 | * Definitions
|
---|
| 35 | ******************************************************************************/
|
---|
| 36 | // aJson Types:
|
---|
| 37 | #define aJson_NULL 0
|
---|
| 38 | #define aJson_Boolean 1
|
---|
| 39 | #define aJson_Int 2
|
---|
| 40 | #define aJson_Float 3
|
---|
| 41 | #define aJson_String 4
|
---|
| 42 | #define aJson_Array 5
|
---|
| 43 | #define aJson_Object 6
|
---|
| 44 |
|
---|
| 45 | #define aJson_IsReference 128
|
---|
| 46 |
|
---|
| 47 | #ifndef EOF
|
---|
| 48 | #define EOF -1
|
---|
| 49 | #endif
|
---|
| 50 |
|
---|
| 51 | #define PRINT_BUFFER_LEN 256
|
---|
| 52 |
|
---|
| 53 | // The aJson structure:
|
---|
| 54 | typedef struct aJsonObject {
|
---|
| 55 | char *name; // The item's name string, if this item is the child of, or is in the list of subitems of an object.
|
---|
| 56 | struct aJsonObject *next, *prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem
|
---|
| 57 | struct aJsonObject *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object.
|
---|
| 58 |
|
---|
| 59 | char type; // The type of the item, as above.
|
---|
| 60 |
|
---|
| 61 | union {
|
---|
| 62 | char *valuestring; // The item's string, if type==aJson_String
|
---|
| 63 | char valuebool; //the items value for true & false
|
---|
| 64 | int valueint; // The item's value, if type==aJson_Int
|
---|
| 65 | double valuefloat; // The item's value, if type==aJson_Float
|
---|
| 66 | };
|
---|
| 67 | } aJsonObject;
|
---|
| 68 |
|
---|
| 69 | /* aJsonStream is stream representation of aJson for its internal use;
|
---|
| 70 | * it is meant to abstract out differences between Stream (e.g. serial
|
---|
| 71 | * stream) and Client (which may or may not be connected) or provide even
|
---|
| 72 | * stream-ish interface to string buffers. */
|
---|
| 73 | class aJsonStream : public Print {
|
---|
| 74 | public:
|
---|
| 75 | aJsonStream(Stream *stream_)
|
---|
| 76 | : stream_obj(stream_), bucket(EOF)
|
---|
| 77 | {}
|
---|
| 78 | /* Use this to check if more data is available, as aJsonStream
|
---|
| 79 | * can read some more data than really consumed and automatically
|
---|
| 80 | * skips separating whitespace if you use this method. */
|
---|
| 81 | virtual bool available();
|
---|
| 82 |
|
---|
| 83 | int parseNumber(aJsonObject *item);
|
---|
| 84 | int printInt(aJsonObject *item);
|
---|
| 85 | int printFloat(aJsonObject *item);
|
---|
| 86 |
|
---|
| 87 | int parseString(aJsonObject *item);
|
---|
| 88 | int printStringPtr(const char *str);
|
---|
| 89 | int printString(aJsonObject *item);
|
---|
| 90 |
|
---|
| 91 | int skip();
|
---|
| 92 | int flush();
|
---|
| 93 |
|
---|
| 94 | int parseValue(aJsonObject *item, char** filter);
|
---|
| 95 | int printValue(aJsonObject *item);
|
---|
| 96 |
|
---|
| 97 | int parseArray(aJsonObject *item, char** filter);
|
---|
| 98 | int printArray(aJsonObject *item);
|
---|
| 99 |
|
---|
| 100 | int parseObject(aJsonObject *item, char** filter);
|
---|
| 101 | int printObject(aJsonObject *item);
|
---|
| 102 |
|
---|
| 103 | protected:
|
---|
| 104 | /* Blocking load of character, returning EOF if the stream
|
---|
| 105 | * is exhausted. */
|
---|
| 106 | /* Base implementation just looks at bucket, returns EOF
|
---|
| 107 | * otherwise; descendats take care of the real reading. */
|
---|
| 108 | virtual int getch();
|
---|
| 109 | virtual size_t readBytes(uint8_t *buffer, size_t len);
|
---|
| 110 | /* Return the character back to the front of the stream
|
---|
| 111 | * after loading it with getch(). Only returning a single
|
---|
| 112 | * character is supported. */
|
---|
| 113 | virtual void ungetch(char ch);
|
---|
| 114 |
|
---|
| 115 | /* Inherited from class Print. */
|
---|
| 116 | virtual size_t write(uint8_t ch);
|
---|
| 117 |
|
---|
| 118 | /* stream attribute is used only from virtual functions,
|
---|
| 119 | * therefore an object inheriting aJsonStream may avoid
|
---|
| 120 | * using streams completely. */
|
---|
| 121 | Stream *stream_obj;
|
---|
| 122 | /* Use this accessor for stream retrieval; some subclasses
|
---|
| 123 | * may use their own stream subclass. */
|
---|
| 124 | virtual inline Stream *stream() { return stream_obj; }
|
---|
| 125 |
|
---|
| 126 | /* bucket is EOF by default. Otherwise, it is a character
|
---|
| 127 | * to be returned by next getch() - returned by a call
|
---|
| 128 | * to ungetch(). */
|
---|
| 129 | int bucket;
|
---|
| 130 | };
|
---|
| 131 |
|
---|
| 132 | /* JSON stream that consumes data from a connection (usually
|
---|
| 133 | * Ethernet client) until the connection is closed. */
|
---|
| 134 | class aJsonClientStream : public aJsonStream {
|
---|
| 135 | public:
|
---|
| 136 | aJsonClientStream(Client *stream_)
|
---|
| 137 | : aJsonStream(NULL), client_obj(stream_)
|
---|
| 138 | {}
|
---|
| 139 |
|
---|
| 140 | private:
|
---|
| 141 | virtual int getch();
|
---|
| 142 |
|
---|
| 143 | Client *client_obj;
|
---|
| 144 | virtual inline Client *stream() { return client_obj; }
|
---|
| 145 | };
|
---|
| 146 |
|
---|
| 147 | /* JSON stream that is bound to input and output string buffer. This is
|
---|
| 148 | * for internal usage by string-based aJsonClass methods. */
|
---|
| 149 | /* TODO: Elastic output buffer support. */
|
---|
| 150 | class aJsonStringStream : public aJsonStream {
|
---|
| 151 | public:
|
---|
| 152 | /* Either of inbuf, outbuf can be NULL if you do not care about
|
---|
| 153 | * particular I/O direction. */
|
---|
| 154 | aJsonStringStream(char *inbuf_, char *outbuf_ = NULL, size_t outbuf_len_ = 0)
|
---|
| 155 | : aJsonStream(NULL), inbuf(inbuf_), outbuf(outbuf_), outbuf_len(outbuf_len_)
|
---|
| 156 | {
|
---|
| 157 | inbuf_len = inbuf ? strlen(inbuf) : 0;
|
---|
| 158 | }
|
---|
| 159 |
|
---|
| 160 | virtual bool available();
|
---|
| 161 |
|
---|
| 162 | private:
|
---|
| 163 | virtual int getch();
|
---|
| 164 | virtual size_t write(uint8_t ch);
|
---|
| 165 |
|
---|
| 166 | char *inbuf, *outbuf;
|
---|
| 167 | size_t inbuf_len, outbuf_len;
|
---|
| 168 | };
|
---|
| 169 |
|
---|
| 170 | class aJsonClass {
|
---|
| 171 | /******************************************************************************
|
---|
| 172 | * Constructors
|
---|
| 173 | ******************************************************************************/
|
---|
| 174 |
|
---|
| 175 | /******************************************************************************
|
---|
| 176 | * User API
|
---|
| 177 | ******************************************************************************/
|
---|
| 178 | public:
|
---|
| 179 | // Supply a block of JSON, and this returns a aJson object you can interrogate. Call aJson.deleteItem when finished.
|
---|
| 180 | aJsonObject* parse(aJsonStream* stream); //Reads from a stream
|
---|
| 181 | aJsonObject* parse(aJsonStream* stream,char** filter_values); //Read from a file, but only return values include in the char* array filter_values
|
---|
| 182 | aJsonObject* parse(char *value); //Reads from a string
|
---|
| 183 | // Render a aJsonObject entity to text for transfer/storage. Free the char* when finished.
|
---|
| 184 | int print(aJsonObject *item, aJsonStream* stream);
|
---|
| 185 | char* print(aJsonObject* item);
|
---|
| 186 | //Renders a aJsonObject directly to a output stream
|
---|
| 187 | char stream(aJsonObject *item, aJsonStream* stream);
|
---|
| 188 | // Delete a aJsonObject entity and all sub-entities.
|
---|
| 189 | void deleteItem(aJsonObject *c);
|
---|
| 190 |
|
---|
| 191 | // Returns the number of items in an array (or object).
|
---|
| 192 | unsigned char getArraySize(aJsonObject *array);
|
---|
| 193 | // Retrieve item number "item" from array "array". Returns NULL if unsuccessful.
|
---|
| 194 | aJsonObject* getArrayItem(aJsonObject *array, unsigned char item);
|
---|
| 195 | // Get item "string" from object. Case insensitive.
|
---|
| 196 | aJsonObject* getObjectItem(aJsonObject *object, const char *string);
|
---|
| 197 |
|
---|
| 198 | // These calls create a aJsonObject item of the appropriate type.
|
---|
| 199 | aJsonObject* createNull();
|
---|
| 200 | aJsonObject* createItem(bool b);
|
---|
| 201 | aJsonObject* createItem(char b);
|
---|
| 202 | aJsonObject* createItem(int num);
|
---|
| 203 | aJsonObject* createItem(double num);
|
---|
| 204 | aJsonObject* createItem(const char *string);
|
---|
| 205 | aJsonObject* createArray();
|
---|
| 206 | aJsonObject* createObject();
|
---|
| 207 |
|
---|
| 208 | // These utilities create an Array of count items.
|
---|
| 209 | aJsonObject* createIntArray(int *numbers, unsigned char count);
|
---|
| 210 | aJsonObject* createFloatArray(double *numbers, unsigned char count);
|
---|
| 211 | aJsonObject* createDoubleArray(double *numbers, unsigned char count);
|
---|
| 212 | aJsonObject* createStringArray(const char **strings, unsigned char count);
|
---|
| 213 |
|
---|
| 214 | // Append item to the specified array/object.
|
---|
| 215 | void addItemToArray(aJsonObject *array, aJsonObject *item);
|
---|
| 216 | void addItemToObject(aJsonObject *object, const char *string,
|
---|
| 217 | aJsonObject *item);
|
---|
| 218 | // Append reference to item to the specified array/object. Use this when you want to add an existing aJsonObject to a new aJsonObject, but don't want to corrupt your existing aJsonObject.
|
---|
| 219 | void addItemReferenceToArray(aJsonObject *array, aJsonObject *item);
|
---|
| 220 | void addItemReferenceToObject(aJsonObject *object, const char *string,
|
---|
| 221 | aJsonObject *item);
|
---|
| 222 |
|
---|
| 223 | // Remove/Detach items from Arrays/Objects.
|
---|
| 224 | aJsonObject* detachItemFromArray(aJsonObject *array, unsigned char which);
|
---|
| 225 | void deleteItemFromArray(aJsonObject *array, unsigned char which);
|
---|
| 226 | aJsonObject* detachItemFromObject(aJsonObject *object, const char *string);
|
---|
| 227 | void deleteItemFromObject(aJsonObject *object, const char *string);
|
---|
| 228 |
|
---|
| 229 | // Update array items.
|
---|
| 230 | void replaceItemInArray(aJsonObject *array, unsigned char which,
|
---|
| 231 | aJsonObject *newitem);
|
---|
| 232 | void replaceItemInObject(aJsonObject *object, const char *string,
|
---|
| 233 | aJsonObject *newitem);
|
---|
| 234 |
|
---|
| 235 | void addNullToObject(aJsonObject* object, const char* name);
|
---|
| 236 | void addBooleanToObject(aJsonObject* object, const char* name, bool b);
|
---|
| 237 | void addNumberToObject(aJsonObject* object, const char* name, int n);
|
---|
| 238 | void addNumberToObject(aJsonObject* object, const char* name, double n);
|
---|
| 239 | void addStringToObject(aJsonObject* object, const char* name,
|
---|
| 240 | const char* s);
|
---|
| 241 |
|
---|
| 242 | protected:
|
---|
| 243 | friend class aJsonStream;
|
---|
| 244 | static aJsonObject* newItem();
|
---|
| 245 |
|
---|
| 246 | private:
|
---|
| 247 | void suffixObject(aJsonObject *prev, aJsonObject *item);
|
---|
| 248 |
|
---|
| 249 | aJsonObject* createReference(aJsonObject *item);
|
---|
| 250 | };
|
---|
| 251 |
|
---|
| 252 | extern aJsonClass aJson;
|
---|
| 253 |
|
---|
| 254 | #endif
|
---|