Added class JsonToken

This commit is contained in:
Benoit Blanchon
2014-07-18 15:43:20 +02:00
parent 0d4d77a7cd
commit 4a1d8483cc
13 changed files with 268 additions and 159 deletions

View File

@ -7,8 +7,31 @@
#include "JsonHashTable.h"
using namespace ArduinoJson::Parser;
using namespace ArduinoJson::Internal;
DEPRECATED JsonHashTable JsonArray::getHashTable(int index)
{
return (JsonHashTable) (*this)[index];
}
/*
* Returns the token for the value at the specified index
*/
JsonValue JsonArray::operator[](int index)
{
// sanity check
if (index < 0 || !token.isArray() || index >= token.size())
return JsonValue::null();
// skip first token, it's the whole object
JsonToken currentToken = token + 1;
// skip all tokens before the specified index
for (int i = 0; i < index; i++)
{
// move forward: current + nested tokens
currentToken += 1 + currentToken.nestedTokenCount();
}
return JsonValue(json, currentToken);
}

View File

@ -7,6 +7,7 @@
#include "JsonValue.h"
#include "JsonArrayIterator.h"
#include "JsonToken.h"
namespace ArduinoJson
{
@ -15,40 +16,41 @@ namespace ArduinoJson
class JsonHashTable;
class JsonArray
{
{
public:
JsonArray() {}
JsonArray()
: token(0)
{
JsonArray(JsonValue& value)
: value(value)
}
JsonArray(char* json, Internal::JsonToken token)
: json(json), token(token)
{
}
bool success()
{
return value.success();
return token.isArray();
}
int size()
{
return value.size();
return success() ? token.size() : 0;
}
JsonValue operator[](int index)
{
return value[index];
}
JsonValue operator[](int index);
JsonArrayIterator begin()
{
return JsonArrayIterator(value);
return JsonArrayIterator(json, token);
}
JsonArrayIterator end()
{
return JsonArrayIterator();
return JsonArrayIterator(json, token + token.nestedTokenCount());
}
DEPRECATED int getLength()
@ -83,9 +85,15 @@ namespace ArduinoJson
return (char*) (*this)[index];
}
static JsonArray null()
{
return JsonArray();
}
private:
JsonValue value;
char* json;
Internal::JsonToken token;
};
}
}

View File

@ -6,6 +6,7 @@
#pragma once
#include "JsonValue.h"
#include "JsonToken.h"
namespace ArduinoJson
{
@ -21,33 +22,34 @@ namespace ArduinoJson
JsonArrayIterator operator++()
{
tokens++;
return *this;
JsonArrayIterator prev = *this;
token += 1;
return prev;
}
JsonValue operator*()
{
return JsonValue(json, tokens);
return JsonValue(json, token);
}
bool operator !=(const JsonArrayIterator& other)
{
return tokens != other.tokens || json != other.json;
return token != other.token || json != other.json;
}
private:
char* json;
jsmntok_t* tokens;
Internal::JsonToken token;
JsonArrayIterator()
: json(0), tokens(0)
: json(0), token(0)
{
}
JsonArrayIterator(JsonValue& value)
: json(value.json), tokens(value.tokens)
JsonArrayIterator(char* json, Internal::JsonToken& token)
: json(json), token(token)
{
}

View File

@ -3,13 +3,51 @@
* Benoit Blanchon 2014 - MIT License
*/
#include <string.h> // for strcmp()
#include "JsonHashTable.h"
#include "JsonArray.h"
#include "JsonValue.h"
using namespace ArduinoJson::Parser;
using namespace ArduinoJson::Internal;
DEPRECATED JsonArray JsonHashTable::getArray(const char* key)
{
return (JsonArray) (*this)[key];
return (*this)[key];
}
/*
* Returns the token for the value associated with the specified key
*/
JsonValue JsonHashTable::getValue(const char* desiredKey)
{
// sanity check
if (desiredKey == 0 || !token.isObject())
return JsonValue::null();
// skip first token, it's the whole object
JsonToken runningToken = token + 1;
// scan each keys
for (int i = 0; i < token.size() / 2; i++)
{
// get 'key' token string
char* key = runningToken.getText(json);
// move to the 'value' token
runningToken += 1;
// compare with desired name
if (strcmp(desiredKey, key) == 0)
{
// return the value token that follows the key token
return JsonValue(json, runningToken);
}
// skip nested tokens
runningToken += 1 + runningToken.nestedTokenCount();
}
// nothing found, return NULL
return JsonValue::null();
}

View File

@ -19,59 +19,70 @@ namespace ArduinoJson
public:
JsonHashTable() {}
JsonHashTable()
: token(Internal::JsonToken::null())
{
}
bool success()
{
return value.success();
return token.isObject();
}
JsonValue operator[](const char* key)
{
return value[key];
return getValue(key);
}
bool containsKey(const char* key)
{
return value[key];
return getValue(key).success();
}
DEPRECATED JsonArray getArray(const char* key);
DEPRECATED bool getBool(const char* key)
{
return value[key];
return getValue(key);
}
DEPRECATED double getDouble(const char* key)
{
return value[key];
return getValue(key);
}
DEPRECATED JsonHashTable getHashTable(const char* key)
{
return value[key];
return getValue(key);
}
DEPRECATED long getLong(const char* key)
{
return value[key];
return getValue(key);
}
DEPRECATED char* getString(const char* key)
{
return value[key];
return getValue(key);
}
static JsonHashTable null()
{
return JsonHashTable();
}
private:
JsonHashTable(JsonValue& value)
: value(value)
JsonHashTable(char* json, Internal::JsonToken token)
: json(json), token(token)
{
}
JsonValue value;
char* json;
Internal::JsonToken token;
JsonValue getValue(const char* key);
};
}
}

View File

@ -4,8 +4,10 @@
*/
#include "JsonParserBase.h"
#include "JsonToken.h"
using namespace ArduinoJson::Parser;
using namespace ArduinoJson::Internal;
JsonValue JsonParserBase::parse(char* json)
{
@ -13,7 +15,7 @@ JsonValue JsonParserBase::parse(char* json)
jsmn_init(&parser);
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, maxTokens))
return JsonValue();
return JsonValue::null();
return JsonValue(json, tokens);
return JsonValue(json, JsonToken(tokens));
}

21
JsonParser/JsonToken.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "JsonToken.h"
using namespace ArduinoJson::Internal;
int JsonToken::nestedTokenCount() const
{
jsmntok_t* t = token;
int yetToVisit = t->size;
int count = 0;
while (yetToVisit)
{
count++;
t++;
yetToVisit--;
yetToVisit += t->size;
}
return count;
}

87
JsonParser/JsonToken.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "jsmn.h"
namespace ArduinoJson
{
namespace Internal
{
class JsonToken
{
public:
JsonToken(jsmntok_t* token)
:token(token)
{
}
char* getText(char* json)
{
json[token->end] = 0;
return json + token->start;
}
JsonToken operator+ (int n)
{
return JsonToken(token + n);
}
void operator+= (int n)
{
token += n;
}
bool operator!= (const JsonToken& other)
{
return token != other.token;
}
int size()
{
return token->size;
}
bool isValid()
{
return token != 0;
}
bool isObject()
{
return token != 0 && token->type == JSMN_OBJECT;
}
bool isArray()
{
return token != 0 && token->type == JSMN_ARRAY;
}
bool isPrimitive()
{
return token != 0 && token->type == JSMN_PRIMITIVE;
}
bool isString()
{
return token != 0 && token->type == JSMN_STRING;
}
static JsonToken null()
{
return JsonToken(0);
}
int nestedTokenCount() const;
private:
jsmntok_t* token;
};
}
}

View File

@ -4,141 +4,57 @@
*/
#include <stdlib.h> // for strtol, strtod
#include <string.h> // for strcmp()
#include "JsonArray.h"
#include "JsonHashTable.h"
#include "JsonValue.h"
using namespace ArduinoJson::Parser;
using namespace ArduinoJson::Internal;
JsonValue::operator bool()
{
if (tokens == 0 || tokens->type != JSMN_PRIMITIVE) return 0;
if (!token.isPrimitive()) return 0;
char *text = token.getText(json);
// "true"
if (json[tokens->start] == 't') return true;
if (text[0] == 't') return true;
// "false"
if (json[tokens->start] == 'f') return false;
if (text[0] == 'f') return false;
// "null"
if (json[tokens->start] == 'n') return false;
if (text[0] == 'n') return false;
// number
return strtol(json + tokens->start, 0, 0) != 0;
return strtol(text, 0, 0) != 0;
}
JsonValue::operator double()
{
if (tokens == 0 || tokens->type != JSMN_PRIMITIVE) return 0;
return strtod(json + tokens->start, 0);
return token.isPrimitive() ? strtod(token.getText(json), 0) : 0;
}
JsonValue::operator long()
{
if (tokens == 0 || tokens->type != JSMN_PRIMITIVE) return 0;
return strtol(json + tokens->start, 0, 0);
return token.isPrimitive() ? strtol(token.getText(json), 0, 0) : 0;
}
JsonValue::operator char*()
{
if (tokens == 0 || tokens->type != JSMN_PRIMITIVE && tokens->type != JSMN_STRING)
return 0;
// add null terminator to the string
json[tokens->end] = 0;
return json + tokens->start;
return token.isString() || token.isPrimitive() ? token.getText(json) : 0;
}
JsonValue::operator JsonArray()
{
return tokens != 0 && tokens->type == JSMN_ARRAY
? JsonArray(*this)
: JsonArray();
return token.isArray()
? JsonArray(json, token)
: JsonArray::null();
}
JsonValue::operator JsonHashTable()
{
return tokens != 0 && tokens->type == JSMN_OBJECT
? JsonHashTable(*this)
: JsonHashTable();
}
int JsonValue::size()
{
return tokens != 0 && tokens->type == JSMN_ARRAY ? tokens->size : 0;
}
/*
* Returns the token for the value associated with the specified key
*/
JsonValue JsonValue::operator [](const char* desiredKey)
{
// sanity check
if (json == 0 || desiredKey == 0 || tokens->type != JSMN_OBJECT)
return JsonValue();
// skip first token, it's the whole object
jsmntok_t* currentToken = tokens + 1;
// scan each keys
for (int i = 0; i < tokens[0].size / 2; i++)
{
// get key token string
char* key = JsonValue(json, currentToken);
// compare with desired name
if (strcmp(desiredKey, key) == 0)
{
// return the value token that follows the key token
return JsonValue(json, currentToken + 1);
}
// move forward: key + value + nested tokens
currentToken += 2 + getNestedTokenCount(currentToken + 1);
}
// nothing found, return NULL
return JsonValue();
}
/*
* Returns the token for the value at the specified index
*/
JsonValue JsonValue::operator[](int index)
{
// sanity check
if (index < 0 || index >= size())
return JsonValue();
// skip first token, it's the whole object
jsmntok_t* currentToken = tokens + 1;
// skip all tokens before the specified index
for (int i = 0; i < index; i++)
{
// move forward: current + nested tokens
currentToken += 1 + getNestedTokenCount(currentToken);
}
return JsonValue(json, currentToken);
}
int JsonValue::getNestedTokenCount(jsmntok_t* token)
{
int tokensToVisit = token->size;
int count = 0;
while (tokensToVisit)
{
count++;
token++;
tokensToVisit--;
tokensToVisit += token->size;
}
return count;
return token.isObject()
? JsonHashTable(json, token)
: JsonHashTable::null();
}

View File

@ -5,7 +5,7 @@
#pragma once
#include "jsmn.h"
#include "JsonToken.h"
#ifndef ARDUINO_JSON_NO_DEPRECATED_WARNING
#ifdef __GNUC__
@ -26,44 +26,37 @@ namespace ArduinoJson
class JsonValue
{
friend class JsonArrayIterator;
public:
JsonValue()
: json(0), tokens(0)
{
}
public:
JsonValue(char* json, jsmntok_t* tokens)
: json(json), tokens(tokens)
JsonValue(char* json, Internal::JsonToken token)
: json(json), token(token)
{
}
bool success()
{
return json != 0 && tokens != 0;
}
return token.isValid();
}
operator bool();
operator double();
operator long();
operator char*();
operator JsonArray();
operator JsonHashTable();
JsonValue operator[](int index);
JsonValue operator[](const char*key);
JsonValue operator[](const char*);
JsonValue operator[](int);
int size();
static JsonValue null()
{
return JsonValue(0, Internal::JsonToken(0));
}
private:
char* json;
jsmntok_t* tokens;
static int getNestedTokenCount(jsmntok_t* token);
Internal::JsonToken token;
};
}
}

View File

@ -11,7 +11,7 @@ namespace JsonParserTests
{
public:
TEST_METHOD(TestMethod1)
TEST_METHOD(SimpleIteraton)
{
char json [] = "[1,2,3]";
JsonParser<4> parser;

View File

@ -89,6 +89,7 @@
<ClCompile Include="..\JsonParser\JsonArray.cpp" />
<ClCompile Include="..\JsonParser\JsonHashTable.cpp" />
<ClCompile Include="..\JsonParser\JsonParserBase.cpp" />
<ClCompile Include="..\JsonParser\JsonToken.cpp" />
<ClCompile Include="..\JsonParser\JsonValue.cpp" />
<ClCompile Include="JsonArrayIteratorTests.cpp" />
<ClCompile Include="JsonArrayTests.cpp" />
@ -102,6 +103,7 @@
<ClInclude Include="..\JsonParser\JsonHashTable.h" />
<ClInclude Include="..\JsonParser\JsonParser.h" />
<ClInclude Include="..\JsonParser\JsonParserBase.h" />
<ClInclude Include="..\JsonParser\JsonToken.h" />
<ClInclude Include="..\JsonParser\JsonValue.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -42,6 +42,9 @@
<ClCompile Include="JsonArrayIteratorTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonParser\JsonToken.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\JsonParser\jsmn.h">
@ -65,5 +68,8 @@
<ClInclude Include="..\JsonParser\JsonArrayIterator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser\JsonToken.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>