Completely ditch json::Array and json::Object's custom implementations and switch to typedefs to STL types.
Originally committed to SVN as r5752.
This commit is contained in:
parent
4e8848c110
commit
dd46c7af7f
7 changed files with 56 additions and 189 deletions
|
@ -228,7 +228,7 @@ bool Options::PutOption(json::Object &obj, const std::string &path, const json::
|
|||
|
||||
// New key, make object.
|
||||
if (pos == obj.end())
|
||||
pos = obj.insert(make_pair(thispart, json::Object()));
|
||||
pos = obj.insert(make_pair(thispart, json::Object())).first;
|
||||
|
||||
PutOptionVisitor visitor(restpart, value);
|
||||
pos->second.Accept(visitor);
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace json
|
|||
// forward declarations (more info further below)
|
||||
class Visitor;
|
||||
class ConstVisitor;
|
||||
class UnknownElement;
|
||||
|
||||
template <typename ValueTypeT>
|
||||
class TrivialType_T;
|
||||
|
@ -27,9 +28,9 @@ class TrivialType_T;
|
|||
typedef double Number;
|
||||
typedef bool Boolean;
|
||||
typedef std::string String;
|
||||
typedef std::deque<UnknownElement> Array;
|
||||
typedef std::map<std::string, UnknownElement> Object;
|
||||
|
||||
class Object;
|
||||
class Array;
|
||||
class Null;
|
||||
|
||||
|
||||
|
@ -130,75 +131,6 @@ private:
|
|||
Imp* m_pImp;
|
||||
};
|
||||
|
||||
class Array : private std::deque<UnknownElement>
|
||||
{
|
||||
public:
|
||||
using std::deque<UnknownElement>::back;
|
||||
using std::deque<UnknownElement>::begin;
|
||||
using std::deque<UnknownElement>::clear;
|
||||
using std::deque<UnknownElement>::const_iterator;
|
||||
using std::deque<UnknownElement>::const_reference;
|
||||
using std::deque<UnknownElement>::const_reverse_iterator;
|
||||
using std::deque<UnknownElement>::difference_type;
|
||||
using std::deque<UnknownElement>::empty;
|
||||
using std::deque<UnknownElement>::end;
|
||||
using std::deque<UnknownElement>::front;
|
||||
using std::deque<UnknownElement>::iterator;
|
||||
using std::deque<UnknownElement>::max_size;
|
||||
using std::deque<UnknownElement>::pointer;
|
||||
using std::deque<UnknownElement>::pop_back;
|
||||
using std::deque<UnknownElement>::pop_front;
|
||||
using std::deque<UnknownElement>::push_back;
|
||||
using std::deque<UnknownElement>::push_front;
|
||||
using std::deque<UnknownElement>::rbegin;
|
||||
using std::deque<UnknownElement>::reference;
|
||||
using std::deque<UnknownElement>::rend;
|
||||
using std::deque<UnknownElement>::reverse_iterator;
|
||||
using std::deque<UnknownElement>::size;
|
||||
using std::deque<UnknownElement>::size_type;
|
||||
using std::deque<UnknownElement>::swap;
|
||||
using std::deque<UnknownElement>::value_type;
|
||||
|
||||
UnknownElement& operator[](size_t idx);
|
||||
const UnknownElement& operator[](size_t idx) const;
|
||||
bool operator==(Array const& rgt) const;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Object - mimics std::map<std::string, UnknownElement>. The member value
|
||||
// contents are effectively heterogeneous thanks to the UnknownElement class
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, UnknownElement> Members;
|
||||
typedef Members::iterator iterator;
|
||||
typedef Members::const_iterator const_iterator;
|
||||
|
||||
bool operator == (const Object& object) const { return m_Members == object.m_Members; }
|
||||
|
||||
iterator begin() { return m_Members.begin(); }
|
||||
iterator end() { return m_Members.end(); }
|
||||
const_iterator begin() const { return m_Members.begin(); }
|
||||
const_iterator end() const { return m_Members.end(); }
|
||||
|
||||
size_t size() const { return m_Members.size(); }
|
||||
bool empty() const { return m_Members.empty(); }
|
||||
|
||||
iterator find(const std::string& name) { return m_Members.find(name); }
|
||||
const_iterator find(const std::string& name) const { return m_Members.find(name); }
|
||||
|
||||
iterator insert(std::pair<std::string, UnknownElement> const& ele);
|
||||
iterator erase(iterator it) { return m_Members.erase(it); }
|
||||
void clear() { m_Members.clear(); }
|
||||
|
||||
UnknownElement& operator [](const std::string& name);
|
||||
const UnknownElement& operator [](const std::string& name) const;
|
||||
|
||||
private:
|
||||
Members m_Members;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Null - doesn't do much of anything but satisfy the JSON spec. It is the default
|
||||
// element type of UnknownElement
|
||||
|
|
|
@ -138,7 +138,11 @@ inline UnknownElement& UnknownElement::operator[] (const std::string& key)
|
|||
inline const UnknownElement& UnknownElement::operator[] (const std::string& key) const
|
||||
{
|
||||
// throws if we aren't an object
|
||||
return CastTo<Object>()[key];
|
||||
Object const& obj = CastTo<Object>();
|
||||
Object::const_iterator it = obj.find(key);
|
||||
if (it == obj.end())
|
||||
throw Exception("Object member not found: " + key);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
inline UnknownElement& UnknownElement::operator[] (size_t index)
|
||||
|
@ -191,51 +195,4 @@ inline bool UnknownElement::operator == (const UnknownElement& element) const
|
|||
return m_pImp->Compare(*element.m_pImp);
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// Object members
|
||||
inline Object::iterator Object::insert(std::pair<std::string, UnknownElement> const& ele)
|
||||
{
|
||||
iterator it = find(ele.first);
|
||||
if (it != m_Members.end())
|
||||
throw Exception("Object member already exists: " + ele.first);
|
||||
|
||||
return m_Members.insert(ele).first;
|
||||
}
|
||||
|
||||
inline UnknownElement& Object::operator [](const std::string& name)
|
||||
{
|
||||
iterator it = find(name);
|
||||
if (it == m_Members.end())
|
||||
{
|
||||
it = insert(make_pair(name, UnknownElement()));
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
inline const UnknownElement& Object::operator [](const std::string& name) const
|
||||
{
|
||||
const_iterator it = find(name);
|
||||
if (it == end())
|
||||
throw Exception("Object member not found: " + name);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Array members
|
||||
inline UnknownElement& Array::operator[](size_t idx) {
|
||||
if (idx >= size())
|
||||
resize(idx + 1);
|
||||
return std::deque<UnknownElement>::operator[](idx);
|
||||
}
|
||||
|
||||
inline const UnknownElement& Array::operator[](size_t idx) const {
|
||||
if (idx >= size())
|
||||
throw Exception("Array out of bounds");
|
||||
return std::deque<UnknownElement>::operator[](idx);
|
||||
}
|
||||
|
||||
inline bool Array::operator==(Array const& rgt) const {
|
||||
return *static_cast<const std::deque<UnknownElement> *>(this) == rgt;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace json
|
|||
{
|
||||
|
||||
|
||||
inline std::istream& operator >> (std::istream& istr, UnknownElement& elementRoot) {
|
||||
inline std::istream& operator >> (std::istream& istr, UnknownElement& elementRoot) {
|
||||
Reader::Read(elementRoot, istr);
|
||||
return istr;
|
||||
}
|
||||
|
@ -87,39 +87,28 @@ inline char Reader::InputStream::Get()
|
|||
|
||||
class Reader::TokenStream
|
||||
{
|
||||
public:
|
||||
TokenStream(const Tokens& tokens);
|
||||
|
||||
const Token& Peek();
|
||||
const Token& Get();
|
||||
|
||||
bool EOS() const;
|
||||
|
||||
private:
|
||||
const Tokens& m_Tokens;
|
||||
Tokens::const_iterator m_itCurrent;
|
||||
|
||||
public:
|
||||
TokenStream(const Tokens& tokens)
|
||||
: m_Tokens(tokens), m_itCurrent(tokens.begin())
|
||||
{ }
|
||||
|
||||
const Token& Peek() {
|
||||
assert(m_itCurrent != m_Tokens.end());
|
||||
return *(m_itCurrent);
|
||||
}
|
||||
const Token& Get() {
|
||||
assert(m_itCurrent != m_Tokens.end());
|
||||
return *(m_itCurrent++);
|
||||
}
|
||||
|
||||
bool EOS() const {
|
||||
return m_itCurrent == m_Tokens.end();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
inline Reader::TokenStream::TokenStream(const Tokens& tokens) :
|
||||
m_Tokens(tokens),
|
||||
m_itCurrent(tokens.begin())
|
||||
{}
|
||||
|
||||
inline const Reader::Token& Reader::TokenStream::Peek() {
|
||||
assert(m_itCurrent != m_Tokens.end());
|
||||
return *(m_itCurrent);
|
||||
}
|
||||
|
||||
inline const Reader::Token& Reader::TokenStream::Get() {
|
||||
assert(m_itCurrent != m_Tokens.end());
|
||||
return *(m_itCurrent++);
|
||||
}
|
||||
|
||||
inline bool Reader::TokenStream::EOS() const {
|
||||
return m_itCurrent == m_Tokens.end();
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// Reader (finally)
|
||||
|
||||
|
@ -148,8 +137,7 @@ void Reader::Read_i(ElementTypeT& element, std::istream& istr)
|
|||
if (tokenStream.EOS() == false)
|
||||
{
|
||||
const Token& token = tokenStream.Peek();
|
||||
std::string sMessage = "Expected End of token stream; found " + token.sValue;
|
||||
throw ParseException(sMessage, token.locBegin, token.locEnd);
|
||||
throw ParseException("Expected End of token stream; found " + token.sValue, token.locBegin, token.locEnd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,8 +232,7 @@ inline void Reader::Scan(Tokens& tokens, InputStream& inputStream)
|
|||
break;
|
||||
|
||||
default: {
|
||||
std::string sErrorMessage = "Unexpected character in stream: " + sChar;
|
||||
throw ScanException(sErrorMessage, inputStream.GetLocation());
|
||||
throw ScanException("Unexpected character in stream: " + sChar, inputStream.GetLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,8 +257,7 @@ inline void Reader::MatchExpectedString(const std::string& sExpected, InputStrea
|
|||
if (inputStream.EOS() || // did we reach the end before finding what we're looking for...
|
||||
inputStream.Get() != *it) // ...or did we find something different?
|
||||
{
|
||||
std::string sMessage = "Expected string: " + sExpected;
|
||||
throw ScanException(sMessage, inputStream.GetLocation());
|
||||
throw ScanException("Expected string: " + sExpected, inputStream.GetLocation());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,10 +289,8 @@ inline void Reader::MatchString(std::string& string, InputStream& inputStream)
|
|||
case 'r': string.push_back('\r'); break;
|
||||
case 't': string.push_back('\t'); break;
|
||||
case 'u': // TODO: what do we do with this?
|
||||
default: {
|
||||
std::string sMessage = "Unrecognized escape sequence found in string: \\" + c;
|
||||
throw ScanException(sMessage, inputStream.GetLocation());
|
||||
}
|
||||
default:
|
||||
throw ScanException("Unrecognized escape sequence found in string: \\" + c, inputStream.GetLocation());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -328,7 +312,7 @@ inline void Reader::MatchNumber(std::string& sNumber, InputStream& inputStream)
|
|||
while (inputStream.EOS() == false &&
|
||||
numericChars.find(inputStream.Peek()) != numericChars.end())
|
||||
{
|
||||
sNumber.push_back(inputStream.Get());
|
||||
sNumber.push_back(inputStream.Get());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,8 +320,7 @@ inline void Reader::MatchNumber(std::string& sNumber, InputStream& inputStream)
|
|||
inline void Reader::Parse(UnknownElement& element, Reader::TokenStream& tokenStream)
|
||||
{
|
||||
if (tokenStream.EOS()) {
|
||||
std::string sMessage = "Unexpected end of token stream";
|
||||
throw ParseException(sMessage, Location(), Location()); // nowhere to point to
|
||||
throw ParseException("Unexpected end of token stream", Location(), Location()); // nowhere to point to
|
||||
}
|
||||
|
||||
const Token& token = tokenStream.Peek();
|
||||
|
@ -387,8 +370,7 @@ inline void Reader::Parse(UnknownElement& element, Reader::TokenStream& tokenStr
|
|||
|
||||
default:
|
||||
{
|
||||
std::string sMessage = "Unexpected token: " + token.sValue;
|
||||
throw ParseException(sMessage, token.locBegin, token.locEnd);
|
||||
throw ParseException("Unexpected token: " + token.sValue, token.locBegin, token.locEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,28 +384,23 @@ inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
|
|||
tokenStream.Peek().nType != Token::TOKEN_OBJECT_END);
|
||||
while (bContinue)
|
||||
{
|
||||
std::pair<std::string, UnknownElement> member;
|
||||
|
||||
// first the member name. save the token in case we have to throw an exception
|
||||
const Token& tokenName = tokenStream.Peek();
|
||||
member.first = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
||||
std::string const& name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
||||
|
||||
if (object.count(name))
|
||||
{
|
||||
throw ParseException("Duplicate object member token: " + name, tokenName.locBegin, tokenName.locEnd);
|
||||
}
|
||||
|
||||
// ...then the key/value separator...
|
||||
MatchExpectedToken(Token::TOKEN_MEMBER_ASSIGN, tokenStream);
|
||||
|
||||
// ...then the value itself (can be anything).
|
||||
Parse(member.second, tokenStream);
|
||||
UnknownElement value;
|
||||
Parse(value, tokenStream);
|
||||
|
||||
// try adding it to the object (this could throw)
|
||||
try
|
||||
{
|
||||
object.insert(member);
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
// must be a duplicate name
|
||||
throw ParseException("Duplicate object member token: " + member.first, tokenName.locBegin, tokenName.locEnd);
|
||||
}
|
||||
object[name] = value;
|
||||
|
||||
bContinue = (tokenStream.EOS() == false &&
|
||||
tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT);
|
||||
|
@ -476,8 +453,7 @@ inline void Reader::Parse(Number& number, Reader::TokenStream& tokenStream)
|
|||
// did we consume all characters in the token?
|
||||
if (iStr.eof() == false)
|
||||
{
|
||||
std::string sMessage = "Unexpected character in NUMBER token: " + iStr.peek();
|
||||
throw ParseException(sMessage, currentToken.locBegin, currentToken.locEnd);
|
||||
throw ParseException("Unexpected character in NUMBER token: " + iStr.peek(), currentToken.locBegin, currentToken.locEnd);
|
||||
}
|
||||
|
||||
number = dValue;
|
||||
|
@ -487,7 +463,7 @@ inline void Reader::Parse(Number& number, Reader::TokenStream& tokenStream)
|
|||
inline void Reader::Parse(Boolean& boolean, Reader::TokenStream& tokenStream)
|
||||
{
|
||||
const std::string& sValue = MatchExpectedToken(Token::TOKEN_BOOLEAN, tokenStream);
|
||||
boolean = (sValue == "true" ? true : false);
|
||||
boolean = (sValue == "true");
|
||||
}
|
||||
|
||||
|
||||
|
@ -501,15 +477,13 @@ inline const std::string& Reader::MatchExpectedToken(Token::Type nExpected, Read
|
|||
{
|
||||
if (tokenStream.EOS())
|
||||
{
|
||||
std::string sMessage = "Unexpected End of token stream";
|
||||
throw ParseException(sMessage, Location(), Location()); // nowhere to point to
|
||||
throw ParseException("Unexpected End of token stream", Location(), Location()); // nowhere to point to
|
||||
}
|
||||
|
||||
const Token& token = tokenStream.Get();
|
||||
if (token.nType != nExpected)
|
||||
{
|
||||
std::string sMessage = "Unexpected token: " + token.sValue;
|
||||
throw ParseException(sMessage, token.locBegin, token.locEnd);
|
||||
throw ParseException("Unexpected token: " + token.sValue, token.locBegin, token.locEnd);
|
||||
}
|
||||
|
||||
return token.sValue;
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
#include <vector>
|
||||
#endif
|
||||
|
||||
namespace json { class Object; }
|
||||
namespace json {
|
||||
class UnknownElement;
|
||||
typedef std::map<std::string, UnknownElement> Object;
|
||||
}
|
||||
|
||||
namespace agi {
|
||||
namespace hotkey {
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include <libaegisub/exception.h>
|
||||
|
||||
namespace json {
|
||||
class Array;
|
||||
class UnknownElement;
|
||||
typedef std::deque<UnknownElement> Array;
|
||||
}
|
||||
|
||||
namespace agi {
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#include <libaegisub/exception.h>
|
||||
|
||||
namespace json {
|
||||
class Object;
|
||||
class UnknownElement;
|
||||
typedef std::map<std::string, UnknownElement> Object;
|
||||
}
|
||||
|
||||
namespace agi {
|
||||
|
|
Loading…
Reference in a new issue