From e68d5fa324961a79c47230a818f9abd865c1a40e Mon Sep 17 00:00:00 2001 From: Azrrael-exe Date: Thu, 31 Oct 2013 19:02:05 -0500 Subject: [PATCH 1/2] Added methods for get and Int or Float Array aJsonClass::getFloatArray(aJsonObject* object) aJsonClass::getIntArray(aJsonObject* object) --- aJSON.cpp | 23 +++++++++++++++++++++++ aJSON.h | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/aJSON.cpp b/aJSON.cpp index ae8f463..f975a91 100644 --- a/aJSON.cpp +++ b/aJSON.cpp @@ -1283,6 +1283,29 @@ aJsonClass::addStringToObject(aJsonObject* object, const char* name, addItemToObject(object, name, createItem(s)); } +// Mods Added by Darkdruid and Azrrael-exe + +int* aJsonClass::getIntArray(aJsonObject* object) +{ + int* out=(int*)malloc(aJson.getArraySize(object)); + for(int i=0;ivalueint); + } + return out; +} + +float* aJsonClass::getFloatArray(aJsonObject* object) +{ + float* out=(float*)malloc(aJson.getArraySize(object)); + for(int i=0;ivaluefloat); + } + return out; +} + + //TODO conversion routines btw. float & int types? aJsonClass aJson; diff --git a/aJSON.h b/aJSON.h index 8f04d5f..c7c90df 100644 --- a/aJSON.h +++ b/aJSON.h @@ -240,6 +240,11 @@ class aJsonClass { void addStringToObject(aJsonObject* object, const char* name, const char* s); + //Mods by DarkDruiD and Azrrael-exe + + int* getIntArray(aJsonObject* object); + float* getFloatArray(aJsonObject* object); + protected: friend class aJsonStream; static aJsonObject* newItem(); From 9fd4b7c7deaf774e46a10a366b8716c778ec3ed9 Mon Sep 17 00:00:00 2001 From: Azrrael-exe Date: Fri, 1 Nov 2013 12:25:20 -0500 Subject: [PATCH 2/2] -Indentation of the Header File -Reorder in the cpp file to match the order with Header File --- aJSON.cpp | 793 +++++++++++++++++++++++++++--------------------------- aJSON.h | 331 ++++++++++++----------- 2 files changed, 562 insertions(+), 562 deletions(-) diff --git a/aJSON.cpp b/aJSON.cpp index f975a91..7414406 100644 --- a/aJSON.cpp +++ b/aJSON.cpp @@ -50,9 +50,11 @@ //how much digits after . for float #define FLOAT_PRECISION 5 +//****************************************** +// Public Funtions for the Class aJsonStream +//****************************************** -bool -aJsonStream::available() +bool aJsonStream::available() { if (bucket != EOF) return true; @@ -69,147 +71,8 @@ aJsonStream::available() return false; } -int -aJsonStream::getch() -{ - if (bucket != EOF) - { - int ret = bucket; - bucket = EOF; - return ret; - } - // In case input was malformed - can happen, this is the - // real world, we can end up in a situation where the parser - // would expect another character and end up stuck on - // stream()->available() forever, hence the 500ms timeout. - unsigned long i= millis()+500; - while ((!stream()->available()) && (millis() < i)) /* spin with a timeout*/; - return stream()->read(); -} - -void -aJsonStream::ungetch(char ch) -{ - bucket = ch; -} - -size_t -aJsonStream::write(uint8_t ch) -{ - return stream()->write(ch); -} - -size_t -aJsonStream::readBytes(uint8_t *buffer, size_t len) -{ - for (size_t i = 0; i < len; i++) - { - int ch = this->getch(); - if (ch == EOF) - { - return i; - } - buffer[i] = ch; - } - return len; -} - - -int -aJsonClientStream::getch() -{ - if (bucket != EOF) - { - int ret = bucket; - bucket = EOF; - return ret; - } - while (!stream()->available() && stream()->connected()) /* spin */; - if (!stream()->connected()) - { - stream()->stop(); - return EOF; - } - return stream()->read(); -} - -bool -aJsonStringStream::available() -{ - if (bucket != EOF) - return true; - return inbuf_len > 0; -} - -int -aJsonStringStream::getch() -{ - if (bucket != EOF) - { - int ret = bucket; - bucket = EOF; - return ret; - } - if (!inbuf || !inbuf_len) - { - return EOF; - } - char ch = *inbuf++; - inbuf_len--; - return ch; -} - -size_t -aJsonStringStream::write(uint8_t ch) -{ - if (!outbuf || outbuf_len <= 1) - { - return 0; - } - *outbuf++ = ch; outbuf_len--; - *outbuf = 0; - return 1; -} - - -// Internal constructor. -aJsonObject* -aJsonClass::newItem() -{ - aJsonObject* node = (aJsonObject*) malloc(sizeof(aJsonObject)); - if (node) - memset(node, 0, sizeof(aJsonObject)); - return node; -} - -// Delete a aJsonObject structure. -void -aJsonClass::deleteItem(aJsonObject *c) -{ - aJsonObject *next; - while (c) - { - next = c->next; - if (!(c->type & aJson_IsReference) && c->child) - { - deleteItem(c->child); - } - if ((c->type == aJson_String) && c->valuestring) - { - free(c->valuestring); - } - if (c->name) - { - free(c->name); - } - free(c); - c = next; - } -} - // Parse the input text to generate a number, and populate the result into item. -int -aJsonStream::parseNumber(aJsonObject *item) +int aJsonStream::parseNumber(aJsonObject *item) { int i = 0; char sign = 1; @@ -292,8 +155,7 @@ aJsonStream::parseNumber(aJsonObject *item) } // Render the number nicely from the given item into a string. -int -aJsonStream::printInt(aJsonObject *item) +int aJsonStream::printInt(aJsonObject *item) { if (item != NULL) { @@ -303,14 +165,13 @@ aJsonStream::printInt(aJsonObject *item) return 0; } -int -aJsonStream::printFloat(aJsonObject *item) +int aJsonStream::printFloat(aJsonObject *item) { if (item != NULL) { double d = item->valuefloat; if (d<0.0) { - this->print("-"); + this->print("-"); d=-d; } //print the integer part @@ -329,7 +190,7 @@ aJsonStream::printFloat(aJsonObject *item) //create an int out of it unsigned int digit = (unsigned int) fractional_part; //print it - this->print(digit, DEC); + this->print(digit, DEC); //remove it from the number fractional_part -= (double)digit; n--; @@ -340,8 +201,7 @@ aJsonStream::printFloat(aJsonObject *item) } // Parse the input text into an unescaped cstring, and populate item. -int -aJsonStream::parseString(aJsonObject *item) +int aJsonStream::parseString(aJsonObject *item) { //we do not need to skip here since the first byte should be '\"' int in = this->getch(); @@ -426,8 +286,7 @@ aJsonStream::parseString(aJsonObject *item) } // Render the cstring provided to an escaped version that can be printed. -int -aJsonStream::printStringPtr(const char *str) +int aJsonStream::printStringPtr(const char *str) { this->print("\""); char* ptr = (char*) str; @@ -437,37 +296,37 @@ aJsonStream::printStringPtr(const char *str) { if ((unsigned char) *ptr > 31 && *ptr != '\"' && *ptr != '\\') { - this->print(*ptr); + this->print(*ptr); ptr++; } else { - this->print('\\'); + this->print('\\'); switch (*ptr++) { case '\\': - this->print('\\'); + this->print('\\'); break; case '\"': - this->print('\"'); + this->print('\"'); break; case '/': - this->print('/'); + this->print('/'); break; case '\b': - this->print('b'); + this->print('b'); break; case '\f': - this->print('f'); + this->print('f'); break; case '\n': - this->print('n'); + this->print('n'); break; case '\r': - this->print('r'); + this->print('r'); break; case '\t': - this->print('t'); + this->print('t'); break; default: break; // eviscerate with prejudice. @@ -481,15 +340,13 @@ aJsonStream::printStringPtr(const char *str) } // Invote print_string_ptr (which is useful) on an item. -int -aJsonStream::printString(aJsonObject *item) +int aJsonStream::printString(aJsonObject *item) { return this->printStringPtr(item->valuestring); } // Utility to jump whitespace and cr/lf -int -aJsonStream::skip() +int aJsonStream::skip() { int in = this->getch(); while (in != EOF && (in <= 32)) @@ -507,8 +364,7 @@ aJsonStream::skip() // Utility to flush our buffer in case it contains garbage // since the parser will return the buffer untouched if it // cannot understand it. -int -aJsonStream::flush() +int aJsonStream::flush() { int in = this->getch(); while(in != EOF) @@ -518,67 +374,8 @@ aJsonStream::flush() return EOF; } - -// Parse an object - create a new root, and populate. -aJsonObject* -aJsonClass::parse(char *value) -{ - aJsonStringStream stringStream(value, NULL); - aJsonObject* result = parse(&stringStream); - return result; -} - -// Parse an object - create a new root, and populate. -aJsonObject* -aJsonClass::parse(aJsonStream* stream) -{ - return parse(stream, NULL); -} - -// Parse an object - create a new root, and populate. -aJsonObject* -aJsonClass::parse(aJsonStream* stream, char** filter) -{ - if (stream == NULL) - { - return NULL; - } - aJsonObject *c = newItem(); - if (!c) - return NULL; /* memory fail */ - - stream->skip(); - if (stream->parseValue(c, filter) == EOF) - { - deleteItem(c); - return NULL; - } - return c; -} - -// Render a aJsonObject item/entity/structure to text. -int -aJsonClass::print(aJsonObject* item, aJsonStream* stream) -{ - return stream->printValue(item); -} - -char* -aJsonClass::print(aJsonObject* item) -{ - char* outBuf = (char*) malloc(256); /* XXX: Dynamic size. */ - if (outBuf == NULL) - { - return NULL; - } - aJsonStringStream stringStream(NULL, outBuf, 256); - print(item, &stringStream); - return outBuf; -} - // Parser core - when encountering text, process appropriately. -int -aJsonStream::parseValue(aJsonObject *item, char** filter) +int aJsonStream::parseValue(aJsonObject *item, char** filter) { if (this->skip() == EOF) { @@ -664,8 +461,7 @@ aJsonStream::parseValue(aJsonObject *item, char** filter) } // Render a value to text. -int -aJsonStream::printValue(aJsonObject *item) +int aJsonStream::printValue(aJsonObject *item) { int result = 0; if (item == NULL) @@ -704,8 +500,7 @@ aJsonStream::printValue(aJsonObject *item) } // Build an array from input text. -int -aJsonStream::parseArray(aJsonObject *item, char** filter) +int aJsonStream::parseArray(aJsonObject *item, char** filter) { int in = this->getch(); if (in != '[') @@ -762,8 +557,7 @@ aJsonStream::parseArray(aJsonObject *item, char** filter) } // Render an array to text -int -aJsonStream::printArray(aJsonObject *item) +int aJsonStream::printArray(aJsonObject *item) { if (item == NULL) { @@ -798,8 +592,7 @@ aJsonStream::printArray(aJsonObject *item) } // Build an object from the text. -int -aJsonStream::parseObject(aJsonObject *item, char** filter) +int aJsonStream::parseObject(aJsonObject *item, char** filter) { int in = this->getch(); if (in != '{') @@ -873,8 +666,7 @@ aJsonStream::parseObject(aJsonObject *item, char** filter) } // Render an object to text. -int -aJsonStream::printObject(aJsonObject *item) +int aJsonStream::printObject(aJsonObject *item) { if (item == NULL) { @@ -916,173 +708,231 @@ aJsonStream::printObject(aJsonObject *item) return 0; } -// Get Array size/item / object item. -unsigned char -aJsonClass::getArraySize(aJsonObject *array) -{ - aJsonObject *c = array->child; - unsigned char i = 0; - while (c) - i++, c = c->next; - return i; -} -aJsonObject* -aJsonClass::getArrayItem(aJsonObject *array, unsigned char item) +//********************************************** +// Protected Funtions for the Class aJsonStream +//********************************************** + +int aJsonStream::getch() { - aJsonObject *c = array->child; - while (c && item > 0) - item--, c = c->next; - return c; + if (bucket != EOF) + { + int ret = bucket; + bucket = EOF; + return ret; + } + // In case input was malformed - can happen, this is the + // real world, we can end up in a situation where the parser + // would expect another character and end up stuck on + // stream()->available() forever, hence the 500ms timeout. + unsigned long i= millis()+500; + while ((!stream()->available()) && (millis() < i)) /* spin with a timeout*/; + return stream()->read(); } -aJsonObject* -aJsonClass::getObjectItem(aJsonObject *object, const char *string) + +size_t aJsonStream::readBytes(uint8_t *buffer, size_t len) { - aJsonObject *c = object->child; - while (c && strcasecmp(c->name, string)) - c = c->next; - return c; + for (size_t i = 0; i < len; i++) + { + int ch = this->getch(); + if (ch == EOF) + { + return i; + } + buffer[i] = ch; + } + return len; } -// Utility for array list handling. -void -aJsonClass::suffixObject(aJsonObject *prev, aJsonObject *item) +void aJsonStream::ungetch(char ch) { - prev->next = item; - item->prev = prev; + bucket = ch; } -// Utility for handling references. -aJsonObject* -aJsonClass::createReference(aJsonObject *item) + +size_t aJsonStream::write(uint8_t ch) { - aJsonObject *ref = newItem(); - if (!ref) - return 0; - memcpy(ref, item, sizeof(aJsonObject)); - ref->name = 0; - ref->type |= aJson_IsReference; - ref->next = ref->prev = 0; - return ref; + return stream()->write(ch); } -// Add item to array/object. -void -aJsonClass::addItemToArray(aJsonObject *array, aJsonObject *item) + +//************************************************* +// Public Methods for the Class aJsonClientStream +//************************************************* + +// NONE + +//************************************************* +// Private Methods for the Class aJsonClientStream +//************************************************* + +int aJsonClientStream::getch() { - aJsonObject *c = array->child; - if (!item) - return; - if (!c) + if (bucket != EOF) { - array->child = item; + int ret = bucket; + bucket = EOF; + return ret; } - else + while (!stream()->available() && stream()->connected()) /* spin */; + if (!stream()->connected()) { - while (c && c->next) - c = c->next; - suffixObject(c, item); + stream()->stop(); + return EOF; } + return stream()->read(); } -void -aJsonClass::addItemToObject(aJsonObject *object, const char *string, - aJsonObject *item) + +//************************************************* +// Public Methods for the Class aJsonStringStream +//************************************************* + +bool aJsonStringStream::available() { - if (!item) - return; - if (item->name) - free(item->name); - item->name = strdup(string); - addItemToArray(object, item); + if (bucket != EOF) + return true; + return inbuf_len > 0; } -void -aJsonClass::addItemReferenceToArray(aJsonObject *array, aJsonObject *item) + +//************************************************* +// Private Methods for the Class aJsonStringStream +//************************************************* + +int aJsonStringStream::getch() { - addItemToArray(array, createReference(item)); -} -void -aJsonClass::addItemReferenceToObject(aJsonObject *object, const char *string, - aJsonObject *item) + if (bucket != EOF) + { + int ret = bucket; + bucket = EOF; + return ret; + } + if (!inbuf || !inbuf_len) + { + return EOF; + } + char ch = *inbuf++; + inbuf_len--; + return ch; +} + +size_t aJsonStringStream::write(uint8_t ch) { - addItemToObject(object, string, createReference(item)); + if (!outbuf || outbuf_len <= 1) + { + return 0; + } + *outbuf++ = ch; outbuf_len--; + *outbuf = 0; + return 1; } -aJsonObject* -aJsonClass::detachItemFromArray(aJsonObject *array, unsigned char which) + +//************************************************* +// Public Methods for the Class aJsonClass +//************************************************* + +// Parse an object - create a new root, and populate. +aJsonObject* aJsonClass::parse(aJsonStream* stream) { - aJsonObject *c = array->child; - while (c && which > 0) - c = c->next, which--; + return parse(stream, NULL); +} + +// Parse an object - create a new root, and populate. +aJsonObject* aJsonClass::parse(aJsonStream* stream, char** filter) +{ + if (stream == NULL) + { + return NULL; + } + aJsonObject *c = newItem(); if (!c) - return 0; - if (c->prev) - c->prev->next = c->next; - if (c->next) - c->next->prev = c->prev; - if (c == array->child) - array->child = c->next; - c->prev = c->next = 0; + return NULL; /* memory fail */ + + stream->skip(); + if (stream->parseValue(c, filter) == EOF) + { + deleteItem(c); + return NULL; + } return c; } -void -aJsonClass::deleteItemFromArray(aJsonObject *array, unsigned char which) + +// Parse an object - create a new root, and populate. +aJsonObject* aJsonClass::parse(char *value) { - deleteItem(detachItemFromArray(array, which)); + aJsonStringStream stringStream(value, NULL); + aJsonObject* result = parse(&stringStream); + return result; } -aJsonObject* -aJsonClass::detachItemFromObject(aJsonObject *object, const char *string) + +// Render a aJsonObject item/entity/structure to text. +int aJsonClass::print(aJsonObject* item, aJsonStream* stream) { - unsigned char i = 0; - aJsonObject *c = object->child; - while (c && strcasecmp(c->name, string)) - i++, c = c->next; - if (c) - return detachItemFromArray(object, i); - return 0; + return stream->printValue(item); } -void -aJsonClass::deleteItemFromObject(aJsonObject *object, const char *string) + +char* aJsonClass::print(aJsonObject* item) { - deleteItem(detachItemFromObject(object, string)); + char* outBuf = (char*) malloc(256); /* XXX: Dynamic size. */ + if (outBuf == NULL) + { + return NULL; + } + aJsonStringStream stringStream(NULL, outBuf, 256); + print(item, &stringStream); + return outBuf; } -// Replace array/object items with new ones. -void -aJsonClass::replaceItemInArray(aJsonObject *array, unsigned char which, - aJsonObject *newitem) +void aJsonClass::deleteItem(aJsonObject *c) { - aJsonObject *c = array->child; - while (c && which > 0) - c = c->next, which--; - if (!c) - return; - newitem->next = c->next; - newitem->prev = c->prev; - if (newitem->next) - newitem->next->prev = newitem; - if (c == array->child) - array->child = newitem; - else - newitem->prev->next = newitem; - c->next = c->prev = 0; - deleteItem(c); + aJsonObject *next; + while (c) + { + next = c->next; + if (!(c->type & aJson_IsReference) && c->child) + { + deleteItem(c->child); + } + if ((c->type == aJson_String) && c->valuestring) + { + free(c->valuestring); + } + if (c->name) + { + free(c->name); + } + free(c); + c = next; + } } -void -aJsonClass::replaceItemInObject(aJsonObject *object, const char *string, - aJsonObject *newitem) + +// Get Array size/item / object item. +unsigned char aJsonClass::getArraySize(aJsonObject *array) { + aJsonObject *c = array->child; unsigned char i = 0; + while (c) + i++, c = c->next; + return i; +} + +aJsonObject* aJsonClass::getArrayItem(aJsonObject *array, unsigned char item) +{ + aJsonObject *c = array->child; + while (c && item > 0) + item--, c = c->next; + return c; +} + +aJsonObject* aJsonClass::getObjectItem(aJsonObject *object, const char *string) +{ aJsonObject *c = object->child; while (c && strcasecmp(c->name, string)) - i++, c = c->next; - if (c) - { - newitem->name = strdup(string); - replaceItemInArray(object, i, newitem); - } + c = c->next; + return c; } // Create basic types: -aJsonObject* -aJsonClass::createNull() +//******************** +aJsonObject* aJsonClass::createNull() { aJsonObject *item = newItem(); if (item) @@ -1090,8 +940,7 @@ aJsonClass::createNull() return item; } -aJsonObject* -aJsonClass::createTrue() +aJsonObject* aJsonClass::createTrue() { aJsonObject *item = newItem(); if (item) @@ -1101,8 +950,8 @@ aJsonClass::createTrue() } return item; } -aJsonObject* -aJsonClass::createFalse() + +aJsonObject* aJsonClass::createFalse() { aJsonObject *item = newItem(); if (item) @@ -1112,8 +961,8 @@ aJsonClass::createFalse() } return item; } -aJsonObject* -aJsonClass::createItem(char b) + +aJsonObject* aJsonClass::createItem(char b) { aJsonObject *item = newItem(); if (item) @@ -1124,8 +973,7 @@ aJsonClass::createItem(char b) return item; } -aJsonObject* -aJsonClass::createItem(int num) +aJsonObject* aJsonClass::createItem(int num) { aJsonObject *item = newItem(); if (item) @@ -1136,8 +984,7 @@ aJsonClass::createItem(int num) return item; } -aJsonObject* -aJsonClass::createItem(double num) +aJsonObject* aJsonClass::createItem(double num) { aJsonObject *item = newItem(); if (item) @@ -1148,8 +995,7 @@ aJsonClass::createItem(double num) return item; } -aJsonObject* -aJsonClass::createItem(const char *string) +aJsonObject* aJsonClass::createItem(const char *string) { aJsonObject *item = newItem(); if (item) @@ -1160,16 +1006,15 @@ aJsonClass::createItem(const char *string) return item; } -aJsonObject* -aJsonClass::createArray() +aJsonObject* aJsonClass::createArray() { aJsonObject *item = newItem(); if (item) item->type = aJson_Array; return item; } -aJsonObject* -aJsonClass::createObject() + +aJsonObject* aJsonClass::createObject() { aJsonObject *item = newItem(); if (item) @@ -1178,8 +1023,8 @@ aJsonClass::createObject() } // Create Arrays: -aJsonObject* -aJsonClass::createIntArray(int *numbers, unsigned char count) +//******************* +aJsonObject* aJsonClass::createIntArray(int *numbers, unsigned char count) { unsigned char i; aJsonObject *n = 0, *p = 0, *a = createArray(); @@ -1195,8 +1040,7 @@ aJsonClass::createIntArray(int *numbers, unsigned char count) return a; } -aJsonObject* -aJsonClass::createFloatArray(double *numbers, unsigned char count) +aJsonObject* aJsonClass::createFloatArray(double *numbers, unsigned char count) { unsigned char i; aJsonObject *n = 0, *p = 0, *a = createArray(); @@ -1212,8 +1056,7 @@ aJsonClass::createFloatArray(double *numbers, unsigned char count) return a; } -aJsonObject* -aJsonClass::createDoubleArray(double *numbers, unsigned char count) +aJsonObject* aJsonClass::createDoubleArray(double *numbers, unsigned char count) { unsigned char i; aJsonObject *n = 0, *p = 0, *a = createArray(); @@ -1229,8 +1072,7 @@ aJsonClass::createDoubleArray(double *numbers, unsigned char count) return a; } -aJsonObject* -aJsonClass::createStringArray(const char **strings, unsigned char count) +aJsonObject* aJsonClass::createStringArray(const char **strings, unsigned char count) { unsigned char i; aJsonObject *n = 0, *p = 0, *a = createArray(); @@ -1246,43 +1088,157 @@ aJsonClass::createStringArray(const char **strings, unsigned char count) return a; } -void -aJsonClass::addNullToObject(aJsonObject* object, const char* name) +// Add item to array/object. +//*************************** +void aJsonClass::addItemToArray(aJsonObject *array, aJsonObject *item) +{ + aJsonObject *c = array->child; + if (!item) + return; + if (!c) + { + array->child = item; + } + else + { + while (c && c->next) + c = c->next; + suffixObject(c, item); + } +} +void aJsonClass::addItemToObject(aJsonObject *object, const char *string, + aJsonObject *item) +{ + if (!item) + return; + if (item->name) + free(item->name); + item->name = strdup(string); + addItemToArray(object, item); +} + +// Add reference items to array/object. +//************************************* +void aJsonClass::addItemReferenceToArray(aJsonObject *array, aJsonObject *item) +{ + addItemToArray(array, createReference(item)); +} + +void aJsonClass::addItemReferenceToObject(aJsonObject *object, const char *string, + aJsonObject *item) +{ + addItemToObject(object, string, createReference(item)); +} + + +// Remove/Detach items from Arrays/Objects. +//***************************************** +aJsonObject* aJsonClass::detachItemFromArray(aJsonObject *array, unsigned char which) +{ + aJsonObject *c = array->child; + while (c && which > 0) + c = c->next, which--; + if (!c) + return 0; + if (c->prev) + c->prev->next = c->next; + if (c->next) + c->next->prev = c->prev; + if (c == array->child) + array->child = c->next; + c->prev = c->next = 0; + return c; +} + +void aJsonClass::deleteItemFromArray(aJsonObject *array, unsigned char which) +{ + deleteItem(detachItemFromArray(array, which)); +} + +aJsonObject* aJsonClass::detachItemFromObject(aJsonObject *object, const char *string) +{ + unsigned char i = 0; + aJsonObject *c = object->child; + while (c && strcasecmp(c->name, string)) + i++, c = c->next; + if (c) + return detachItemFromArray(object, i); + return 0; +} + +void aJsonClass::deleteItemFromObject(aJsonObject *object, const char *string) +{ + deleteItem(detachItemFromObject(object, string)); +} + +// Replace array/object items with new ones. +//****************************************** +void aJsonClass::replaceItemInArray(aJsonObject *array, unsigned char which, + aJsonObject *newitem) +{ + aJsonObject *c = array->child; + while (c && which > 0) + c = c->next, which--; + if (!c) + return; + newitem->next = c->next; + newitem->prev = c->prev; + if (newitem->next) + newitem->next->prev = newitem; + if (c == array->child) + array->child = newitem; + else + newitem->prev->next = newitem; + c->next = c->prev = 0; + deleteItem(c); +} + +void aJsonClass::replaceItemInObject(aJsonObject *object, const char *string, + aJsonObject *newitem) +{ + unsigned char i = 0; + aJsonObject *c = object->child; + while (c && strcasecmp(c->name, string)) + i++, c = c->next; + if (c) + { + newitem->name = strdup(string); + replaceItemInArray(object, i, newitem); + } +} + +void aJsonClass::addNullToObject(aJsonObject* object, const char* name) { addItemToObject(object, name, createNull()); } -void -aJsonClass::addTrueToObject(aJsonObject* object, const char* name) +void aJsonClass::addTrueToObject(aJsonObject* object, const char* name) { addItemToObject(object, name, createTrue()); } -void -aJsonClass::addFalseToObject(aJsonObject* object, const char* name) +void aJsonClass::addFalseToObject(aJsonObject* object, const char* name) { addItemToObject(object, name, createFalse()); } -void -aJsonClass::addNumberToObject(aJsonObject* object, const char* name, int n) +void aJsonClass::addNumberToObject(aJsonObject* object, const char* name, int n) { addItemToObject(object, name, createItem(n)); } -void -aJsonClass::addNumberToObject(aJsonObject* object, const char* name, double n) +void aJsonClass::addNumberToObject(aJsonObject* object, const char* name, double n) { addItemToObject(object, name, createItem(n)); } -void -aJsonClass::addStringToObject(aJsonObject* object, const char* name, +void aJsonClass::addStringToObject(aJsonObject* object, const char* name, const char* s) { addItemToObject(object, name, createItem(s)); } + // Mods Added by Darkdruid and Azrrael-exe int* aJsonClass::getIntArray(aJsonObject* object) @@ -1305,6 +1261,45 @@ float* aJsonClass::getFloatArray(aJsonObject* object) return out; } +//************************************************* +// Protected Methods for the Class aJsonClass +//************************************************* + +// Internal constructor. + +aJsonObject* aJsonClass::newItem() +{ + aJsonObject* node = (aJsonObject*) malloc(sizeof(aJsonObject)); + if (node) + memset(node, 0, sizeof(aJsonObject)); + return node; +} + +//************************************************* +// Private Methods for the Class aJsonClass +//************************************************* + +// Utility for array list handling. +void aJsonClass::suffixObject(aJsonObject *prev, aJsonObject *item) +{ + prev->next = item; + item->prev = prev; +} +// Utility for handling references. + +aJsonObject* aJsonClass::createReference(aJsonObject *item) +{ + aJsonObject *ref = newItem(); + if (!ref) + return 0; + memcpy(ref, item, sizeof(aJsonObject)); + ref->name = 0; + ref->type |= aJson_IsReference; + ref->next = ref->prev = 0; + return ref; +} + +//--------------------------------------- //TODO conversion routines btw. float & int types? diff --git a/aJSON.h b/aJSON.h index c7c90df..a6949f8 100644 --- a/aJSON.h +++ b/aJSON.h @@ -50,8 +50,9 @@ #endif // The aJson structure: -typedef struct aJsonObject { - char *name; // The item's name string, if this item is the child of, or is in the list of subitems of an object. +typedef struct aJsonObject +{ + char *name; // The item's name string, if this item is the child of, or is in the list of subitems of an object. struct aJsonObject *next, *prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem struct aJsonObject *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object. @@ -69,104 +70,108 @@ typedef struct aJsonObject { * it is meant to abstract out differences between Stream (e.g. serial * stream) and Client (which may or may not be connected) or provide even * stream-ish interface to string buffers. */ -class aJsonStream : public Print { -public: - aJsonStream(Stream *stream_) +class aJsonStream : public Print +{ + public: + aJsonStream(Stream *stream_) : stream_obj(stream_), bucket(EOF) {} /* Use this to check if more data is available, as aJsonStream * can read some more data than really consumed and automatically * skips separating whitespace if you use this method. */ - virtual bool available(); - - int parseNumber(aJsonObject *item); - int printInt(aJsonObject *item); - int printFloat(aJsonObject *item); - - int parseString(aJsonObject *item); - int printStringPtr(const char *str); - int printString(aJsonObject *item); - - int skip(); - int flush(); - - int parseValue(aJsonObject *item, char** filter); - int printValue(aJsonObject *item); - - int parseArray(aJsonObject *item, char** filter); - int printArray(aJsonObject *item); - - int parseObject(aJsonObject *item, char** filter); - int printObject(aJsonObject *item); - -protected: - /* Blocking load of character, returning EOF if the stream - * is exhausted. */ - /* Base implementation just looks at bucket, returns EOF - * otherwise; descendats take care of the real reading. */ - virtual int getch(); - virtual size_t readBytes(uint8_t *buffer, size_t len); - /* Return the character back to the front of the stream - * after loading it with getch(). Only returning a single - * character is supported. */ - virtual void ungetch(char ch); - - /* Inherited from class Print. */ - virtual size_t write(uint8_t ch); - - /* stream attribute is used only from virtual functions, - * therefore an object inheriting aJsonStream may avoid - * using streams completely. */ - Stream *stream_obj; - /* Use this accessor for stream retrieval; some subclasses - * may use their own stream subclass. */ - virtual inline Stream *stream() { return stream_obj; } - - /* bucket is EOF by default. Otherwise, it is a character - * to be returned by next getch() - returned by a call - * to ungetch(). */ - int bucket; + virtual bool available(); + + int parseNumber(aJsonObject *item); + int printInt(aJsonObject *item); + int printFloat(aJsonObject *item); + + int parseString(aJsonObject *item); + int printStringPtr(const char *str); + int printString(aJsonObject *item); + + int skip(); + int flush(); + + int parseValue(aJsonObject *item, char** filter); + int printValue(aJsonObject *item); + + int parseArray(aJsonObject *item, char** filter); + int printArray(aJsonObject *item); + + int parseObject(aJsonObject *item, char** filter); + int printObject(aJsonObject *item); + + protected: + /* Blocking load of character, returning EOF if the stream + * is exhausted. */ + /* Base implementation just looks at bucket, returns EOF + * otherwise; descendats take care of the real reading. */ + virtual int getch(); + virtual size_t readBytes(uint8_t *buffer, size_t len); + /* Return the character back to the front of the stream + * after loading it with getch(). Only returning a single + * character is supported. */ + virtual void ungetch(char ch); + + /* Inherited from class Print. */ + virtual size_t write(uint8_t ch); + + /* stream attribute is used only from virtual functions, + * therefore an object inheriting aJsonStream may avoid + * using streams completely. */ + Stream *stream_obj; + /* Use this accessor for stream retrieval; some subclasses + * may use their own stream subclass. */ + virtual inline Stream *stream() { return stream_obj; } + + /* bucket is EOF by default. Otherwise, it is a character + * to be returned by next getch() - returned by a call + * to ungetch(). */ + int bucket; }; /* JSON stream that consumes data from a connection (usually * Ethernet client) until the connection is closed. */ -class aJsonClientStream : public aJsonStream { -public: - aJsonClientStream(Client *stream_) - : aJsonStream(NULL), client_obj(stream_) - {} - -private: - virtual int getch(); - - Client *client_obj; - virtual inline Client *stream() { return client_obj; } +class aJsonClientStream : public aJsonStream +{ + public: + aJsonClientStream(Client *stream_) + : aJsonStream(NULL), client_obj(stream_) + {} + + private: + virtual int getch(); + + Client *client_obj; + virtual inline Client *stream() { return client_obj; } }; /* JSON stream that is bound to input and output string buffer. This is * for internal usage by string-based aJsonClass methods. */ /* TODO: Elastic output buffer support. */ -class aJsonStringStream : public aJsonStream { -public: - /* Either of inbuf, outbuf can be NULL if you do not care about - * particular I/O direction. */ - aJsonStringStream(char *inbuf_, char *outbuf_ = NULL, size_t outbuf_len_ = 0) - : aJsonStream(NULL), inbuf(inbuf_), outbuf(outbuf_), outbuf_len(outbuf_len_) - { - inbuf_len = inbuf ? strlen(inbuf) : 0; - } - - virtual bool available(); - -private: - virtual int getch(); - virtual size_t write(uint8_t ch); - - char *inbuf, *outbuf; - size_t inbuf_len, outbuf_len; +class aJsonStringStream : public aJsonStream +{ + public: + /* Either of inbuf, outbuf can be NULL if you do not care about + * particular I/O direction. */ + aJsonStringStream(char *inbuf_, char *outbuf_ = NULL, size_t outbuf_len_ = 0) + : aJsonStream(NULL), inbuf(inbuf_), outbuf(outbuf_), outbuf_len(outbuf_len_) + { + inbuf_len = inbuf ? strlen(inbuf) : 0; + } + + virtual bool available(); + + private: + virtual int getch(); + virtual size_t write(uint8_t ch); + + char *inbuf, *outbuf; + size_t inbuf_len, outbuf_len; }; -class aJsonClass { +class aJsonClass +{ /****************************************************************************** * Constructors ******************************************************************************/ @@ -174,85 +179,85 @@ class aJsonClass { /****************************************************************************** * User API ******************************************************************************/ -public: - // Supply a block of JSON, and this returns a aJson object you can interrogate. Call aJson.deleteItem when finished. - aJsonObject* parse(aJsonStream* stream); //Reads from a stream - aJsonObject* parse(aJsonStream* stream,char** filter_values); //Read from a file, but only return values include in the char* array filter_values - aJsonObject* parse(char *value); //Reads from a string - // Render a aJsonObject entity to text for transfer/storage. Free the char* when finished. - int print(aJsonObject *item, aJsonStream* stream); - char* print(aJsonObject* item); - //Renders a aJsonObject directly to a output stream - char stream(aJsonObject *item, aJsonStream* stream); - // Delete a aJsonObject entity and all sub-entities. - void deleteItem(aJsonObject *c); - - // Returns the number of items in an array (or object). - unsigned char getArraySize(aJsonObject *array); - // Retrieve item number "item" from array "array". Returns NULL if unsuccessful. - aJsonObject* getArrayItem(aJsonObject *array, unsigned char item); - // Get item "string" from object. Case insensitive. - aJsonObject* getObjectItem(aJsonObject *object, const char *string); - - // These calls create a aJsonObject item of the appropriate type. - aJsonObject* createNull(); - aJsonObject* createTrue(); - aJsonObject* createFalse(); - aJsonObject* createItem(char b); - aJsonObject* createItem(int num); - aJsonObject* createItem(double num); - aJsonObject* createItem(const char *string); - aJsonObject* createArray(); - aJsonObject* createObject(); - - // These utilities create an Array of count items. - aJsonObject* createIntArray(int *numbers, unsigned char count); - aJsonObject* createFloatArray(double *numbers, unsigned char count); - aJsonObject* createDoubleArray(double *numbers, unsigned char count); - aJsonObject* createStringArray(const char **strings, unsigned char count); - - // Append item to the specified array/object. - void addItemToArray(aJsonObject *array, aJsonObject *item); - void addItemToObject(aJsonObject *object, const char *string, - aJsonObject *item); - // 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. - void addItemReferenceToArray(aJsonObject *array, aJsonObject *item); - void addItemReferenceToObject(aJsonObject *object, const char *string, - aJsonObject *item); - - // Remove/Detach items from Arrays/Objects. - aJsonObject* detachItemFromArray(aJsonObject *array, unsigned char which); - void deleteItemFromArray(aJsonObject *array, unsigned char which); - aJsonObject* detachItemFromObject(aJsonObject *object, const char *string); - void deleteItemFromObject(aJsonObject *object, const char *string); - - // Update array items. - void replaceItemInArray(aJsonObject *array, unsigned char which, - aJsonObject *newitem); - void replaceItemInObject(aJsonObject *object, const char *string, - aJsonObject *newitem); - - void addNullToObject(aJsonObject* object, const char* name); - void addTrueToObject(aJsonObject* object, const char* name); - void addFalseToObject(aJsonObject* object, const char* name); - void addNumberToObject(aJsonObject* object, const char* name, int n); - void addNumberToObject(aJsonObject* object, const char* name, double n); - void addStringToObject(aJsonObject* object, const char* name, - const char* s); - - //Mods by DarkDruiD and Azrrael-exe - - int* getIntArray(aJsonObject* object); - float* getFloatArray(aJsonObject* object); - -protected: - friend class aJsonStream; - static aJsonObject* newItem(); - -private: - void suffixObject(aJsonObject *prev, aJsonObject *item); - - aJsonObject* createReference(aJsonObject *item); + public: + // Supply a block of JSON, and this returns a aJson object you can interrogate. Call aJson.deleteItem when finished. + aJsonObject* parse(aJsonStream* stream); //Reads from a stream + aJsonObject* parse(aJsonStream* stream,char** filter_values); //Read from a file, but only return values include in the char* array filter_values + aJsonObject* parse(char *value); //Reads from a string + // Render a aJsonObject entity to text for transfer/storage. Free the char* when finished. + int print(aJsonObject *item, aJsonStream* stream); + char* print(aJsonObject* item); + //Renders a aJsonObject directly to a output stream + char stream(aJsonObject *item, aJsonStream* stream); + // Delete a aJsonObject entity and all sub-entities. + void deleteItem(aJsonObject *c); + + // Returns the number of items in an array (or object). + unsigned char getArraySize(aJsonObject *array); + // Retrieve item number "item" from array "array". Returns NULL if unsuccessful. + aJsonObject* getArrayItem(aJsonObject *array, unsigned char item); + // Get item "string" from object. Case insensitive. + aJsonObject* getObjectItem(aJsonObject *object, const char *string); + + // These calls create a aJsonObject item of the appropriate type. + aJsonObject* createNull(); + aJsonObject* createTrue(); + aJsonObject* createFalse(); + aJsonObject* createItem(char b); + aJsonObject* createItem(int num); + aJsonObject* createItem(double num); + aJsonObject* createItem(const char *string); + aJsonObject* createArray(); + aJsonObject* createObject(); + + // These utilities create an Array of count items. + aJsonObject* createIntArray(int *numbers, unsigned char count); + aJsonObject* createFloatArray(double *numbers, unsigned char count); + aJsonObject* createDoubleArray(double *numbers, unsigned char count); + aJsonObject* createStringArray(const char **strings, unsigned char count); + + // Append item to the specified array/object. + void addItemToArray(aJsonObject *array, aJsonObject *item); + void addItemToObject(aJsonObject *object, const char *string, + aJsonObject *item); + // 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. + void addItemReferenceToArray(aJsonObject *array, aJsonObject *item); + void addItemReferenceToObject(aJsonObject *object, const char *string, + aJsonObject *item); + + // Remove/Detach items from Arrays/Objects. + aJsonObject* detachItemFromArray(aJsonObject *array, unsigned char which); + void deleteItemFromArray(aJsonObject *array, unsigned char which); + aJsonObject* detachItemFromObject(aJsonObject *object, const char *string); + void deleteItemFromObject(aJsonObject *object, const char *string); + + // Update array items. + void replaceItemInArray(aJsonObject *array, unsigned char which, + aJsonObject *newitem); + void replaceItemInObject(aJsonObject *object, const char *string, + aJsonObject *newitem); + + void addNullToObject(aJsonObject* object, const char* name); + void addTrueToObject(aJsonObject* object, const char* name); + void addFalseToObject(aJsonObject* object, const char* name); + void addNumberToObject(aJsonObject* object, const char* name, int n); + void addNumberToObject(aJsonObject* object, const char* name, double n); + void addStringToObject(aJsonObject* object, const char* name, + const char* s); + + //Mods by DarkDruiD and Azrrael-exe + + int* getIntArray(aJsonObject* object); + float* getFloatArray(aJsonObject* object); + + protected: + friend class aJsonStream; + static aJsonObject* newItem(); + + private: + void suffixObject(aJsonObject *prev, aJsonObject *item); + + aJsonObject* createReference(aJsonObject *item); }; extern aJsonClass aJson;