unused; also not what official StepMania uses.
This commit is contained in:
@@ -1,5 +0,0 @@
|
|||||||
Since a few people have asked me, I figured I'd put a LICENSE file here. I wrote
|
|
||||||
this small library as an excercise. You are welcome to include jsonxx in your
|
|
||||||
project and redistributed it with your code in any license, provided that you
|
|
||||||
don't sue me for anything. Please let me know if you improved it, so that I can
|
|
||||||
merge your changes.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
h1. Introduction
|
|
||||||
|
|
||||||
JSON++ is a light-weight JSON parser written in C++.
|
|
||||||
|
|
||||||
h2. Why another JSON parser?
|
|
||||||
|
|
||||||
Perhaps because web service clients are usually written in dynamic
|
|
||||||
languages these days, none of the existing C++ JSON parsers suite my
|
|
||||||
needs very well, so I wrote one to used in another project. My goals
|
|
||||||
for JSON++ were:
|
|
||||||
* Efficient in both memory and speed.
|
|
||||||
* No third party dependencies. JSON++ only depends on the standard C++ library.
|
|
||||||
* Cross platform.
|
|
||||||
* Robust.
|
|
||||||
* Small and convenient API. Most of the time, you only need to call one function and two function templates.
|
|
||||||
* Easy to integrate. JSON++ only has one source file and one header file. Just compile the source file and link with your program.
|
|
||||||
|
|
||||||
h3. Usage
|
|
||||||
|
|
||||||
The following snippet is from one of the unit tests. It's quite self-descriptive.
|
|
||||||
|
|
||||||
<pre>
|
|
||||||
<code>
|
|
||||||
string teststr(
|
|
||||||
"{"
|
|
||||||
" \"foo\" : 1,"
|
|
||||||
" \"bar\" : false,"
|
|
||||||
" \"person\" : {\"name\" : \"GWB\", \"age\" : 60},"
|
|
||||||
" \"data\": [\"abcd\", 42]"
|
|
||||||
"}"
|
|
||||||
);
|
|
||||||
istringstream input(teststr);
|
|
||||||
Object o;
|
|
||||||
assert(o.parse(input));
|
|
||||||
assert(1 == o.get<long>("foo"));
|
|
||||||
assert(o.has<bool>("bar"));
|
|
||||||
assert(o.has<Object>("person"));
|
|
||||||
assert(o.get<Object>("person").has<long>("age"));
|
|
||||||
assert(o.has<Array>("data"));
|
|
||||||
assert(o.get<Array>("data").get<long>(1) == 42);
|
|
||||||
assert(o.get<Array>("data").get<string>(0) == "abcd");
|
|
||||||
assert(!o.has<long>("data"));
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
// Author: Hong Jiang <[email protected]>
|
|
||||||
|
|
||||||
#include "jsonxx.h"
|
|
||||||
|
|
||||||
#include <cctype>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace jsonxx {
|
|
||||||
|
|
||||||
void eat_whitespaces(std::istream& input) {
|
|
||||||
char ch;
|
|
||||||
do {
|
|
||||||
input.get(ch);
|
|
||||||
} while(isspace(ch));
|
|
||||||
input.putback(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to consume characters from the input stream and match the
|
|
||||||
// pattern string. Leading whitespaces from the input are ignored if
|
|
||||||
// ignore_ws is true.
|
|
||||||
bool match(const std::string& pattern, std::istream& input,
|
|
||||||
bool ignore_ws = true) {
|
|
||||||
if (ignore_ws) {
|
|
||||||
eat_whitespaces(input);
|
|
||||||
}
|
|
||||||
std::string::const_iterator cur(pattern.begin());
|
|
||||||
char ch(0);
|
|
||||||
while(input && !input.eof() && cur != pattern.end()) {
|
|
||||||
input.get(ch);
|
|
||||||
if (ch != *cur) {
|
|
||||||
input.putback(ch);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cur == pattern.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_string(std::istream& input, std::string* value) {
|
|
||||||
if (!match("\"", input)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char ch;
|
|
||||||
while(!input.eof() && input.good()) {
|
|
||||||
input.get(ch);
|
|
||||||
if (ch == '"') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value->push_back(ch);
|
|
||||||
}
|
|
||||||
if (input && ch == '"') {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_bool(std::istream& input, bool* value) {
|
|
||||||
if (match("true", input)) {
|
|
||||||
*value = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (match("false", input)) {
|
|
||||||
*value = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_null(std::istream& input) {
|
|
||||||
if (match("null", input)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_number(std::istream& input, long* value) {
|
|
||||||
eat_whitespaces(input);
|
|
||||||
char ch;
|
|
||||||
std::string value_str;
|
|
||||||
int sign = 1;
|
|
||||||
if (match("-", input)) {
|
|
||||||
sign = -1;
|
|
||||||
} else {
|
|
||||||
match("+", input);
|
|
||||||
}
|
|
||||||
while(input && !input.eof()) {
|
|
||||||
input.get(ch);
|
|
||||||
if (!isdigit(ch)) {
|
|
||||||
input.putback(ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value_str.push_back(ch);
|
|
||||||
}
|
|
||||||
if (value_str.size() > 0) {
|
|
||||||
std::istringstream(value_str) >> *value;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object::Object() : value_map_() {}
|
|
||||||
|
|
||||||
Object::~Object() {
|
|
||||||
std::map<std::string, Value*>::iterator i;
|
|
||||||
for (i = value_map_.begin(); i != value_map_.end(); ++i) {
|
|
||||||
delete i->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Object::parse(std::istream& input) {
|
|
||||||
if (!match("{", input)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
std::string key;
|
|
||||||
if (!parse_string(input, &key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!match(":", input)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Value* v = new Value();
|
|
||||||
if (!v->parse(input)) {
|
|
||||||
delete v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value_map_[key] = v;
|
|
||||||
} while (match(",", input));
|
|
||||||
|
|
||||||
if (!match("}", input)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::Value() : type_(INVALID_) {}
|
|
||||||
|
|
||||||
Value::~Value() {
|
|
||||||
if (type_ == STRING_) {
|
|
||||||
delete string_value_;
|
|
||||||
}
|
|
||||||
if (type_ == OBJECT_) {
|
|
||||||
delete object_value_;
|
|
||||||
}
|
|
||||||
if (type_ == ARRAY_) {
|
|
||||||
delete array_value_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Value::parse(std::istream& input) {
|
|
||||||
std::string string_value;
|
|
||||||
if (parse_string(input, &string_value)) {
|
|
||||||
string_value_ = new std::string();
|
|
||||||
string_value_->swap(string_value);
|
|
||||||
type_ = STRING_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (parse_number(input, &integer_value_)) {
|
|
||||||
type_ = INTEGER_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_bool(input, &bool_value_)) {
|
|
||||||
type_ = BOOL_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (parse_null(input)) {
|
|
||||||
type_ = NULL_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
array_value_ = new Array();
|
|
||||||
if (array_value_->parse(input)) {
|
|
||||||
type_ = ARRAY_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
delete array_value_;
|
|
||||||
object_value_ = new Object();
|
|
||||||
if (object_value_->parse(input)) {
|
|
||||||
type_ = OBJECT_;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
delete object_value_;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array::Array() : values_() {}
|
|
||||||
|
|
||||||
Array::~Array() {
|
|
||||||
for (unsigned int i = 0; i < values_.size(); ++i) {
|
|
||||||
delete values_[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Array::parse(std::istream& input) {
|
|
||||||
if (!match("[", input)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
Value* v = new Value();
|
|
||||||
if (!v->parse(input)) {
|
|
||||||
delete v;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
values_.push_back(v);
|
|
||||||
} while (match(",", input));
|
|
||||||
|
|
||||||
if (!match("]", input)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace jsonxx
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const jsonxx::Value& v) {
|
|
||||||
if (v.is<long>()) {
|
|
||||||
return stream << v.get<long>();
|
|
||||||
} else if (v.is<std::string>()) {
|
|
||||||
return stream << '"' << v.get<std::string>() << '"';
|
|
||||||
} else if (v.is<bool>()) {
|
|
||||||
if (v.get<bool>()) {
|
|
||||||
return stream << "true";
|
|
||||||
} else {
|
|
||||||
return stream << "false";
|
|
||||||
}
|
|
||||||
} else if (v.is<jsonxx::Value::Null>()) {
|
|
||||||
return stream << "null";
|
|
||||||
} else if (v.is<jsonxx::Object>()) {
|
|
||||||
return stream << v.get<jsonxx::Object>();
|
|
||||||
} else if (v.is<jsonxx::Array>()){
|
|
||||||
return stream << v.get<jsonxx::Array>();
|
|
||||||
}
|
|
||||||
// Shouldn't reach here.
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const jsonxx::Array& v) {
|
|
||||||
stream << "[";
|
|
||||||
const std::vector<jsonxx::Value*>& values(v.values());
|
|
||||||
for (unsigned int i = 0; i < values.size()-1; ++i) {
|
|
||||||
stream << *(values[i]) << ", ";
|
|
||||||
}
|
|
||||||
return stream << *(values[values.size()-1]) << "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const jsonxx::Object& v) {
|
|
||||||
stream << "{";
|
|
||||||
const std::map<std::string, jsonxx::Value*>& kv(v.kv_map());
|
|
||||||
for (std::map<std::string, jsonxx::Value*>::const_iterator i = kv.begin();
|
|
||||||
i != kv.end(); /**/) {
|
|
||||||
stream << i->first << ": " << *(i->second);
|
|
||||||
++i;
|
|
||||||
if ( i != kv.end()) {
|
|
||||||
stream << ", ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return stream << "}";
|
|
||||||
}
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
#ifndef JSONXX_H
|
|
||||||
#define JSONXX_H
|
|
||||||
// Author: Hong Jiang <[email protected]>
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace jsonxx {
|
|
||||||
|
|
||||||
// TODO: *::parse() should be static functions.
|
|
||||||
|
|
||||||
class Value;
|
|
||||||
|
|
||||||
// A JSON Object
|
|
||||||
class Object {
|
|
||||||
public:
|
|
||||||
Object();
|
|
||||||
~Object();
|
|
||||||
bool parse(std::istream& input);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool has(const std::string& key) const;
|
|
||||||
|
|
||||||
// Always call has<>() first. If the key doesn't exist, consider
|
|
||||||
// the behavior undefined.
|
|
||||||
template <typename T>
|
|
||||||
T& get(const std::string& key) const;
|
|
||||||
|
|
||||||
const std::map<std::string, Value*>& kv_map() const { return value_map_; }
|
|
||||||
private:
|
|
||||||
Object(const Object&);
|
|
||||||
Object& operator=(const Object&);
|
|
||||||
|
|
||||||
std::map<std::string, Value*> value_map_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Value;
|
|
||||||
|
|
||||||
class Array {
|
|
||||||
public:
|
|
||||||
Array();
|
|
||||||
~Array();
|
|
||||||
bool parse(std::istream& input);
|
|
||||||
|
|
||||||
unsigned int size() const { return values_.size(); }
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool has(unsigned int i) const;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& get(unsigned int i) const;
|
|
||||||
|
|
||||||
const std::vector<Value*>& values() const {
|
|
||||||
return values_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Array(const Array&);
|
|
||||||
Array& operator=(const Array&);
|
|
||||||
std::vector<Value*> values_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A value could be a number, an array, a string, an object, a
|
|
||||||
// boolean, or null
|
|
||||||
class Value {
|
|
||||||
public:
|
|
||||||
class Null {};
|
|
||||||
|
|
||||||
Value();
|
|
||||||
~Value();
|
|
||||||
bool parse(std::istream& input);
|
|
||||||
template<typename T>
|
|
||||||
bool is() const;
|
|
||||||
template<typename T>
|
|
||||||
T& get();
|
|
||||||
template<typename T>
|
|
||||||
const T& get() const;
|
|
||||||
private:
|
|
||||||
Value(const Value&);
|
|
||||||
Value& operator=(const Value&);
|
|
||||||
enum {
|
|
||||||
INTEGER_,
|
|
||||||
STRING_,
|
|
||||||
BOOL_,
|
|
||||||
NULL_,
|
|
||||||
ARRAY_,
|
|
||||||
OBJECT_,
|
|
||||||
INVALID_
|
|
||||||
} type_;
|
|
||||||
union {
|
|
||||||
long integer_value_;
|
|
||||||
std::string* string_value_;
|
|
||||||
bool bool_value_;
|
|
||||||
Array* array_value_;
|
|
||||||
Object* object_value_;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool Array::has(unsigned int i) const {
|
|
||||||
if (i >= size()) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
Value* v = values_.at(i);
|
|
||||||
return v->is<T>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& Array::get(unsigned int i) const {
|
|
||||||
assert(i < size());
|
|
||||||
Value* v = values_.at(i);
|
|
||||||
return v->get<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool Object::has(const std::string& key) const {
|
|
||||||
std::map<std::string, Value*>::const_iterator it(value_map_.find(key));
|
|
||||||
return it != value_map_.end() && it->second->is<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T& Object::get(const std::string& key) const {
|
|
||||||
assert(has<T>(key));
|
|
||||||
return value_map_.find(key)->second->get<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool Value::is<Value::Null>() const {
|
|
||||||
return type_ == NULL_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool Value::is<bool>() const {
|
|
||||||
return type_ == BOOL_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool Value::is<std::string>() const {
|
|
||||||
return type_ == STRING_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool Value::is<long>() const {
|
|
||||||
return type_ == INTEGER_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool Value::is<Array>() const {
|
|
||||||
return type_ == ARRAY_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool Value::is<Object>() const {
|
|
||||||
return type_ == OBJECT_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline bool& Value::get<bool>() {
|
|
||||||
assert(is<bool>());
|
|
||||||
return bool_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline std::string& Value::get<std::string>() {
|
|
||||||
assert(is<std::string>());
|
|
||||||
return *string_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline long& Value::get<long>() {
|
|
||||||
assert(is<long>());
|
|
||||||
return integer_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline Array& Value::get<Array>() {
|
|
||||||
assert(is<Array>());
|
|
||||||
return *array_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline Object& Value::get<Object>() {
|
|
||||||
assert(is<Object>());
|
|
||||||
return *object_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline const bool& Value::get<bool>() const {
|
|
||||||
assert(is<bool>());
|
|
||||||
return bool_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline const std::string& Value::get<std::string>() const {
|
|
||||||
assert(is<std::string>());
|
|
||||||
return *string_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline const long& Value::get<long>() const {
|
|
||||||
assert(is<long>());
|
|
||||||
return integer_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline const Array& Value::get<Array>() const {
|
|
||||||
assert(is<Array>());
|
|
||||||
return *array_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline const Object& Value::get<Object>() const {
|
|
||||||
assert(is<Object>());
|
|
||||||
return *object_value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace jsonxx
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const jsonxx::Value& v);
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const jsonxx::Object& v);
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const jsonxx::Array& v);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
// Author: Hong Jiang <[email protected]>
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "jsonxx.h"
|
|
||||||
|
|
||||||
namespace jsonxx {
|
|
||||||
bool parse_string(std::istream& input, std::string* value);
|
|
||||||
bool parse_number(std::istream& input, long* value);
|
|
||||||
bool match(const std::string& pattern, std::istream& input, bool ignore_ws = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
using namespace jsonxx;
|
|
||||||
using namespace std;
|
|
||||||
{
|
|
||||||
string teststr("\"field1\"");
|
|
||||||
string value;
|
|
||||||
istringstream input(teststr);
|
|
||||||
assert(parse_string(input, &value));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("\" field1\"");
|
|
||||||
string value;
|
|
||||||
istringstream input(teststr);
|
|
||||||
assert(parse_string(input, &value));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr(" \"field1\"");
|
|
||||||
string value;
|
|
||||||
istringstream input(teststr);
|
|
||||||
assert(parse_string(input, &value));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("6");
|
|
||||||
istringstream input(teststr);
|
|
||||||
long value;
|
|
||||||
assert(parse_number(input, &value));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr(" }");
|
|
||||||
istringstream input(teststr);
|
|
||||||
assert(match("}", input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("{ \"field1\" : 6 }");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Object o;
|
|
||||||
assert(o.parse(input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("{ \"field1 : 6 }");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Object o;
|
|
||||||
assert(!o.parse(input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("6");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("+6");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("-6");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("asdf");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(!v.parse(input));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("true");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
assert(v.is<bool>());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("false");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
assert(v.is<bool>());
|
|
||||||
assert(v.get<bool>() == false);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("null");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
assert(v.is<Value::Null>());
|
|
||||||
assert(!v.is<bool>());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("\"field1\"");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Value v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
assert(v.is<std::string>());
|
|
||||||
assert("field1" == v.get<std::string>());
|
|
||||||
ostringstream stream;
|
|
||||||
stream << v;
|
|
||||||
assert(stream.str() == "\"field1\"");
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr("[\"field1\", 6]");
|
|
||||||
istringstream input(teststr);
|
|
||||||
Array v;
|
|
||||||
assert(v.parse(input));
|
|
||||||
assert(v.has<std::string>(0));
|
|
||||||
assert("field1" == v.get<std::string>(0));
|
|
||||||
assert(v.has<long>(1));
|
|
||||||
assert(6 == v.get<long>(1));
|
|
||||||
assert(!v.has<bool>(2));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
string teststr(
|
|
||||||
"{"
|
|
||||||
" \"foo\" : 1,"
|
|
||||||
" \"bar\" : false,"
|
|
||||||
" \"person\" : {\"name\" : \"GWB\", \"age\" : 60},"
|
|
||||||
" \"data\": [\"abcd\", 42]"
|
|
||||||
"}"
|
|
||||||
);
|
|
||||||
istringstream input(teststr);
|
|
||||||
Object o;
|
|
||||||
assert(o.parse(input));
|
|
||||||
assert(1 == o.get<long>("foo"));
|
|
||||||
assert(o.has<bool>("bar"));
|
|
||||||
assert(o.has<Object>("person"));
|
|
||||||
assert(o.get<Object>("person").has<long>("age"));
|
|
||||||
assert(o.has<Array>("data"));
|
|
||||||
assert(o.get<Array>("data").get<long>(1) == 42);
|
|
||||||
assert(o.get<Array>("data").get<string>(0) == "abcd");
|
|
||||||
assert(!o.has<long>("data"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
http://hjiang.net/archives/245
|
|
||||||
and
|
|
||||||
http://github.com/hjiang/jsonxx
|
|
||||||
Reference in New Issue
Block a user