Skip to content

Commit

Permalink
v3.2.0 - bug fixes. support for json comments
Browse files Browse the repository at this point in the history
  • Loading branch information
arkhipenko committed Dec 26, 2020
1 parent d78d7a1 commit 608a19e
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 55 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,22 @@ If a key does not exist, a new key-value pair is created. If a key exists, the v
`String s = "{\"ssid\":\"devices\",\"pwd\":\"********\"}";`
`d.jload(s)` will populate dictionary d from the JSON string s
`d.jload(s)` will populate dictionary `d` from the JSON string `s`.
`d.jload(s, 2)` will load only first 2 key/value pairs.
NOTE: as of version 3.2.0 JSON strings can contain comments (lines starting with a `#` symbol).
E.g. :
```json
# This JSON file contains comments
{
"key" : "value", # line comments are supported as well
}
```



#### Lookup values:

Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"type": "git",
"url": "https://github.com/arkhipenko/Dictionary.git"
},
"version": "3.1.2",
"version": "3.2.0",
"frameworks": "arduino",
"platforms": "*"
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=Dictionary
version=3.1.2
version=3.2.0
author=Anatoli Arkhipenko <arkhipenko@hotmail.com>
maintainer=Anatoli Arkhipenko <arkhipenko@hotmail.com>
sentence=A dictionary data type with a fast b-tree based search
Expand Down
139 changes: 87 additions & 52 deletions src/Dictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
v3.1.2:
2020-09-16 - use of namespace for NodeArray
v3.2.0:
2020-12-21 - support for comments (#) in imported JSON files
bug fix: heap corrupt when missing a comma
feature: stricter JSON formatting check
*/


Expand Down Expand Up @@ -138,6 +143,7 @@
#define DICTIONARY_COLON (-21)
#define DICTIONARY_QUOTE (-22)
#define DICTIONARY_BCKSL (-23)
#define DICTIONARY_FMT (-25)
#define DICTIONARY_EOF (-99)


Expand Down Expand Up @@ -212,7 +218,7 @@ class Dictionary {
size_t esize();

String json();
int8_t jload (String json, int num = 0);
int8_t jload (String json, int aNum = 0);
int8_t merge (Dictionary& dict);


Expand Down Expand Up @@ -524,7 +530,9 @@ String Dictionary::json() {

size_t ct = count();
for (size_t i = 0; i < ct; i++) {
s += '"' + key(i) + "\":\"" + value(i) + '"';
String vv = value(i);
vv.replace("\"","\\\"");
s += '"' + key(i) + "\":\"" + vv + '"';
if (i < ct - 1) s += ',';
}
s += '}';
Expand All @@ -533,75 +541,103 @@ String Dictionary::json() {
}


int8_t Dictionary::jload(String json, int num) {
int8_t Dictionary::jload(String json, int aNum) {
bool insideQoute = false;
bool nextVerbatim = false;
bool isValue = false;
const char* c = json.c_str();
bool isComment = false;
const char* jc = json.c_str();
size_t len = json.length();
int p = 0;
int8_t rc;
String currentKey;
String currentValue;

for (size_t i = 0; i < len; i++, c++) {
for (size_t i = 0; i < len; i++, jc++) {
char c = *jc;

if ( isComment ) {
if ( c == '\n' ) {
isComment = false;
isValue = false;
}
continue;
}
if (nextVerbatim) {
nextVerbatim = false;
nextVerbatim = false;
}
else {
// process all special cases: '\', '"', ':', and ','
if (*c == '\\') {
nextVerbatim = true;
continue;
// process all special cases: '\', '"', ':', and ','
if (c == '\\' ) {
nextVerbatim = true;
continue;
}
if ( c == '#' ) {
if ( !insideQoute ) {
isComment = true;
continue;
}
if (*c == '\"') {
if (!insideQoute) {
insideQoute = true;
continue;
}
else {
insideQoute = false;
if (isValue) {
insert(currentKey, currentValue);
currentValue = String();
currentKey = String();
if (num > 0 && p >= num) break;
}
}
}
if ( c == '\"' ) {
if (!insideQoute) {
insideQoute = true;
continue;
}
if (*c == '\n') {
if (insideQoute) {
return DICTIONARY_QUOTE;
}
if (nextVerbatim) {
return DICTIONARY_BCKSL;
}
else {
insideQoute = false;
if (isValue) {
rc = insert( currentKey, currentValue );
if (rc) return DICTIONARY_MEM; // if error - exit with an error code
currentValue = String();
currentKey = String();
p++;
if (aNum > 0 && p >= aNum) break;
}
continue;
}
if (!insideQoute) {
if (*c == ':') {
if (isValue) {
return DICTIONARY_COMMA; //missing comma probably
}
isValue = true;
continue;
}
if (*c == ',') {
if (!isValue) {
return DICTIONARY_COLON; //missing colon probably
}
isValue = false;
continue;
}
}
if (c == '\n') {
if ( insideQoute ) {
return DICTIONARY_QUOTE;
}
if ( nextVerbatim ) {
return DICTIONARY_BCKSL;
}
isValue = false; // missing comma, but let's forgive that
continue;
}
if (!insideQoute) {
if (c == ':') {
if ( isValue ) {
return DICTIONARY_COMMA; //missing comma probably
}
isValue = true;
continue;
}
if (c == ',') {
if ( !isValue ) {
return DICTIONARY_COLON; //missing colon probably
}
isValue = false;
continue;
}
if ( c == '{' || c == '}' || c == ' ' || c == '\t' ) continue;
return DICTIONARY_FMT;
}
}
if (insideQoute) {
if (isValue) currentValue.concat(*c);
else currentKey.concat(*c);
if (isValue) currentValue.concat(c);
else currentKey.concat(c);
}
}
if (insideQoute || nextVerbatim || (num > 0 && p < num)) return DICTIONARY_EOF;
return DICTIONARY_OK;
}
if (insideQoute || nextVerbatim || (aNum > 0 && p < aNum )) return DICTIONARY_EOF;
#ifdef _LIBDEBUG_
Serial.printf("Dictionary::jload: DICTIONARY_OK\n");
#endif
return DICTIONARY_OK;
}


int8_t Dictionary::merge(Dictionary& dict) {
size_t ct = dict.count();
int8_t rc;
Expand All @@ -613,7 +649,6 @@ int8_t Dictionary::merge(Dictionary& dict) {
return DICTIONARY_OK;
}


// ==== OPERATORS ====================================

bool Dictionary::operator () (String keystr) {
Expand Down

0 comments on commit 608a19e

Please sign in to comment.