forked from mia/Aegisub
Only automatically convert json objects to other types when they are uninitialized
Originally committed to SVN as r6005.
This commit is contained in:
parent
a78417177a
commit
3097dc634e
6 changed files with 130 additions and 181 deletions
|
@ -14,32 +14,40 @@ Author: Terry Caton
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using namespace json;
|
||||||
|
|
||||||
|
class CastVisitorBase : public Visitor, public ConstVisitor {
|
||||||
|
void Visit(Array&) { }
|
||||||
|
void Visit(Object&) { }
|
||||||
|
void Visit(Number&) { }
|
||||||
|
void Visit(String&) { }
|
||||||
|
void Visit(Boolean&) { }
|
||||||
|
void Visit(Null&) { is_null = true; }
|
||||||
|
void Visit(Array const&) { }
|
||||||
|
void Visit(Object const&) { }
|
||||||
|
void Visit(Number const&) { }
|
||||||
|
void Visit(String const&) { }
|
||||||
|
void Visit(Boolean const&) { }
|
||||||
|
void Visit(Null const&) { is_null = true; }
|
||||||
|
public:
|
||||||
|
bool is_null;
|
||||||
|
CastVisitorBase() : is_null(false) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct CastVisitor : public CastVisitorBase {
|
||||||
|
T *element;
|
||||||
|
CastVisitor() : element(0) { }
|
||||||
|
void Visit(T& ele) { element = &ele; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace json
|
namespace json
|
||||||
{
|
{
|
||||||
|
|
||||||
/////////////////////////
|
/////////////////////////
|
||||||
// UnknownElement members
|
// UnknownElement members
|
||||||
class CastVisitor : public ConstVisitor
|
|
||||||
{
|
|
||||||
virtual void Visit(const Array&) { }
|
|
||||||
virtual void Visit(const Object&) { }
|
|
||||||
virtual void Visit(const Number&) { }
|
|
||||||
virtual void Visit(const String&) { }
|
|
||||||
virtual void Visit(const Boolean&) { }
|
|
||||||
virtual void Visit(const Null&) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ElementTypeT>
|
|
||||||
class CastVisitor_T : public CastVisitor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const ElementTypeT *element;
|
|
||||||
CastVisitor_T() : element(0) { }
|
|
||||||
|
|
||||||
// we don't know what this is, but it overrides one of the base's no-op functions
|
|
||||||
void Visit(const ElementTypeT& element) { this->element = &element; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class UnknownElement::Imp
|
class UnknownElement::Imp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -57,15 +65,15 @@ template <typename ElementTypeT>
|
||||||
class UnknownElement::Imp_T : public UnknownElement::Imp
|
class UnknownElement::Imp_T : public UnknownElement::Imp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Imp_T(const ElementTypeT& element) : m_Element(element) {}
|
Imp_T(const ElementTypeT& element) : m_Element(element) { }
|
||||||
virtual Imp* Clone() const { return new Imp_T<ElementTypeT>(*this); }
|
Imp* Clone() const { return new Imp_T<ElementTypeT>(*this); }
|
||||||
|
|
||||||
virtual void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); }
|
void Accept(ConstVisitor& visitor) const { visitor.Visit(m_Element); }
|
||||||
virtual void Accept(Visitor& visitor) { visitor.Visit(m_Element); }
|
void Accept(Visitor& visitor) { visitor.Visit(m_Element); }
|
||||||
|
|
||||||
virtual bool Compare(const Imp& imp) const
|
bool Compare(const Imp& imp) const
|
||||||
{
|
{
|
||||||
CastVisitor_T<ElementTypeT> castVisitor;
|
CastVisitor<const ElementTypeT> castVisitor;
|
||||||
imp.Accept(castVisitor);
|
imp.Accept(castVisitor);
|
||||||
return castVisitor.element && m_Element == *castVisitor.element;
|
return castVisitor.element && m_Element == *castVisitor.element;
|
||||||
}
|
}
|
||||||
|
@ -88,31 +96,30 @@ UnknownElement::UnknownElement(const Null& null) : m_pImp( new Imp
|
||||||
|
|
||||||
UnknownElement::~UnknownElement() { delete m_pImp; }
|
UnknownElement::~UnknownElement() { delete m_pImp; }
|
||||||
|
|
||||||
UnknownElement::operator const Object& () const { return CastTo<Object>(); }
|
UnknownElement::operator Object const&() const { return CastTo<Object>(); }
|
||||||
UnknownElement::operator const Array& () const { return CastTo<Array>(); }
|
UnknownElement::operator Array const&() const { return CastTo<Array>(); }
|
||||||
UnknownElement::operator const Number& () const { return CastTo<Number>(); }
|
UnknownElement::operator Number const&() const { return CastTo<Number>(); }
|
||||||
UnknownElement::operator const Boolean& () const { return CastTo<Boolean>(); }
|
UnknownElement::operator Boolean const&() const { return CastTo<Boolean>(); }
|
||||||
UnknownElement::operator const String& () const { return CastTo<String>(); }
|
UnknownElement::operator String const&() const { return CastTo<String>(); }
|
||||||
UnknownElement::operator const Null& () const { return CastTo<Null>(); }
|
UnknownElement::operator Null const&() const { return CastTo<Null>(); }
|
||||||
|
|
||||||
UnknownElement::operator Object& () { return ConvertTo<Object>(); }
|
UnknownElement::operator Object&() { return CastTo<Object>(); }
|
||||||
UnknownElement::operator Array& () { return ConvertTo<Array>(); }
|
UnknownElement::operator Array&() { return CastTo<Array>(); }
|
||||||
UnknownElement::operator Number& () { return ConvertTo<Number>(); }
|
UnknownElement::operator Number&() { return CastTo<Number>(); }
|
||||||
UnknownElement::operator Boolean& () { return ConvertTo<Boolean>(); }
|
UnknownElement::operator Boolean&() { return CastTo<Boolean>(); }
|
||||||
UnknownElement::operator String& () { return ConvertTo<String>(); }
|
UnknownElement::operator String&() { return CastTo<String>(); }
|
||||||
UnknownElement::operator Null& () { return ConvertTo<Null>(); }
|
UnknownElement::operator Null&() { return CastTo<Null>(); }
|
||||||
|
|
||||||
UnknownElement& UnknownElement::operator = (const UnknownElement& unknown)
|
UnknownElement& UnknownElement::operator =(const UnknownElement& unknown)
|
||||||
{
|
{
|
||||||
delete m_pImp;
|
delete m_pImp;
|
||||||
m_pImp = unknown.m_pImp->Clone();
|
m_pImp = unknown.m_pImp->Clone();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnknownElement& UnknownElement::operator[] (const std::string& key)
|
UnknownElement& UnknownElement::operator[](const std::string& key)
|
||||||
{
|
{
|
||||||
// the people want an object. make us one if we aren't already
|
return CastTo<Object>()[key];
|
||||||
return ConvertTo<Object>()[key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const UnknownElement& UnknownElement::operator[] (const std::string& key) const
|
const UnknownElement& UnknownElement::operator[] (const std::string& key) const
|
||||||
|
@ -125,23 +132,14 @@ const UnknownElement& UnknownElement::operator[] (const std::string& key) const
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnknownElement& UnknownElement::operator[] (size_t index)
|
UnknownElement& UnknownElement::operator[](size_t index) { return CastTo<Array>()[index]; }
|
||||||
{
|
UnknownElement const& UnknownElement::operator[](size_t index) const { return CastTo<Array>()[index]; }
|
||||||
// the people want an array. make us one if we aren't already
|
|
||||||
return ConvertTo<Array>()[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
const UnknownElement& UnknownElement::operator[] (size_t index) const
|
|
||||||
{
|
|
||||||
// throws if we aren't an array
|
|
||||||
return CastTo<Array>()[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename ElementTypeT>
|
template <typename ElementTypeT>
|
||||||
const ElementTypeT& UnknownElement::CastTo() const
|
ElementTypeT const& UnknownElement::CastTo() const
|
||||||
{
|
{
|
||||||
CastVisitor_T<ElementTypeT> castVisitor;
|
CastVisitor<const ElementTypeT> castVisitor;
|
||||||
m_pImp->Accept(castVisitor);
|
m_pImp->Accept(castVisitor);
|
||||||
if (!castVisitor.element)
|
if (!castVisitor.element)
|
||||||
throw Exception("Bad cast");
|
throw Exception("Bad cast");
|
||||||
|
@ -149,17 +147,21 @@ const ElementTypeT& UnknownElement::CastTo() const
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ElementTypeT>
|
template <typename ElementTypeT>
|
||||||
ElementTypeT& UnknownElement::ConvertTo()
|
ElementTypeT& UnknownElement::CastTo()
|
||||||
{
|
{
|
||||||
CastVisitor_T<ElementTypeT> castVisitor;
|
CastVisitor<ElementTypeT> castVisitor;
|
||||||
Accept(castVisitor);
|
Accept(castVisitor);
|
||||||
if (!castVisitor.element)
|
|
||||||
{
|
// If this element is uninitialized, implicitly convert it to the desired type
|
||||||
// we're not the right type. fix it & try again
|
if (castVisitor.is_null) {
|
||||||
*this = ElementTypeT();
|
*this = ElementTypeT();
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
// Otherwise throw an exception
|
||||||
|
if (!castVisitor.element)
|
||||||
|
throw Exception("Bad cast");
|
||||||
|
return *castVisitor.element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); }
|
void UnknownElement::Accept(ConstVisitor& visitor) const { m_pImp->Accept(visitor); }
|
||||||
|
|
|
@ -123,7 +123,7 @@ void Reader::Read_i(ElementTypeT& element, std::istream& istr)
|
||||||
reader.Scan(tokens, inputStream);
|
reader.Scan(tokens, inputStream);
|
||||||
|
|
||||||
TokenStream tokenStream(tokens);
|
TokenStream tokenStream(tokens);
|
||||||
reader.Parse(element, tokenStream);
|
element = reader.Parse(tokenStream);
|
||||||
|
|
||||||
if (!tokenStream.EOS())
|
if (!tokenStream.EOS())
|
||||||
{
|
{
|
||||||
|
@ -304,131 +304,79 @@ void Reader::MatchNumber(std::string& sNumber, InputStream& inputStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Reader::Parse(UnknownElement& element, Reader::TokenStream& tokenStream)
|
UnknownElement Reader::Parse(Reader::TokenStream& tokenStream)
|
||||||
{
|
{
|
||||||
if (tokenStream.EOS()) {
|
if (tokenStream.EOS())
|
||||||
throw ParseException("Unexpected end of token stream", Location(), Location()); // nowhere to point to
|
throw ParseException("Unexpected end of token stream", Location(), Location()); // nowhere to point to
|
||||||
}
|
|
||||||
|
|
||||||
const Token& token = tokenStream.Peek();
|
Token const& token = tokenStream.Peek();
|
||||||
switch (token.nType) {
|
switch (token.nType) {
|
||||||
case Token::TOKEN_OBJECT_BEGIN:
|
case Token::TOKEN_OBJECT_BEGIN: return ParseObject(tokenStream);
|
||||||
{
|
case Token::TOKEN_ARRAY_BEGIN: return ParseArray(tokenStream);
|
||||||
// implicit non-const cast will perform conversion for us (if necessary)
|
case Token::TOKEN_STRING: return ParseString(tokenStream);
|
||||||
Object& object = element;
|
case Token::TOKEN_NUMBER: return ParseNumber(tokenStream);
|
||||||
Parse(object, tokenStream);
|
case Token::TOKEN_BOOLEAN: return ParseBoolean(tokenStream);
|
||||||
break;
|
case Token::TOKEN_NULL: return ParseNull(tokenStream);
|
||||||
}
|
|
||||||
|
|
||||||
case Token::TOKEN_ARRAY_BEGIN:
|
|
||||||
{
|
|
||||||
Array& array = element;
|
|
||||||
Parse(array, tokenStream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Token::TOKEN_STRING:
|
|
||||||
{
|
|
||||||
String& string = element;
|
|
||||||
Parse(string, tokenStream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Token::TOKEN_NUMBER:
|
|
||||||
{
|
|
||||||
Number& number = element;
|
|
||||||
Parse(number, tokenStream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Token::TOKEN_BOOLEAN:
|
|
||||||
{
|
|
||||||
Boolean& boolean = element;
|
|
||||||
Parse(boolean, tokenStream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Token::TOKEN_NULL:
|
|
||||||
{
|
|
||||||
Null& null = element;
|
|
||||||
Parse(null, tokenStream);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
|
||||||
throw ParseException("Unexpected token: " + token.sValue, token.locBegin, token.locEnd);
|
throw ParseException("Unexpected token: " + token.sValue, token.locBegin, token.locEnd);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object Reader::ParseObject(Reader::TokenStream& tokenStream)
|
||||||
void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
|
|
||||||
{
|
{
|
||||||
MatchExpectedToken(Token::TOKEN_OBJECT_BEGIN, tokenStream);
|
MatchExpectedToken(Token::TOKEN_OBJECT_BEGIN, tokenStream);
|
||||||
|
|
||||||
bool bContinue = (tokenStream.EOS() == false &&
|
Object object;
|
||||||
tokenStream.Peek().nType != Token::TOKEN_OBJECT_END);
|
|
||||||
while (bContinue)
|
while (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_OBJECT_END)
|
||||||
{
|
{
|
||||||
// first the member name. save the token in case we have to throw an exception
|
// first the member name. save the token in case we have to throw an exception
|
||||||
const Token& tokenName = tokenStream.Peek();
|
const Token& tokenName = tokenStream.Peek();
|
||||||
std::string const& name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
std::string const& name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
||||||
|
|
||||||
if (object.count(name))
|
if (object.count(name))
|
||||||
{
|
|
||||||
throw ParseException("Duplicate object member token: " + name, tokenName.locBegin, tokenName.locEnd);
|
throw ParseException("Duplicate object member token: " + name, tokenName.locBegin, tokenName.locEnd);
|
||||||
}
|
|
||||||
|
|
||||||
// ...then the key/value separator...
|
// ...then the key/value separator...
|
||||||
MatchExpectedToken(Token::TOKEN_MEMBER_ASSIGN, tokenStream);
|
MatchExpectedToken(Token::TOKEN_MEMBER_ASSIGN, tokenStream);
|
||||||
|
|
||||||
// ...then the value itself (can be anything).
|
// ...then the value itself (can be anything).
|
||||||
UnknownElement value;
|
object[name] = Parse(tokenStream);
|
||||||
Parse(value, tokenStream);
|
|
||||||
|
|
||||||
object[name] = value;
|
if (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_OBJECT_END)
|
||||||
|
|
||||||
bContinue = (tokenStream.EOS() == false &&
|
|
||||||
tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT);
|
|
||||||
if (bContinue)
|
|
||||||
MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream);
|
MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchExpectedToken(Token::TOKEN_OBJECT_END, tokenStream);
|
MatchExpectedToken(Token::TOKEN_OBJECT_END, tokenStream);
|
||||||
|
|
||||||
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array Reader::ParseArray(Reader::TokenStream& tokenStream)
|
||||||
void Reader::Parse(Array& array, Reader::TokenStream& tokenStream)
|
|
||||||
{
|
{
|
||||||
MatchExpectedToken(Token::TOKEN_ARRAY_BEGIN, tokenStream);
|
MatchExpectedToken(Token::TOKEN_ARRAY_BEGIN, tokenStream);
|
||||||
|
|
||||||
bool bContinue = (tokenStream.EOS() == false &&
|
Array array;
|
||||||
tokenStream.Peek().nType != Token::TOKEN_ARRAY_END);
|
|
||||||
while (bContinue)
|
|
||||||
{
|
|
||||||
// ...what's next? could be anything
|
|
||||||
array.push_back(UnknownElement());
|
|
||||||
UnknownElement& element = array.back();
|
|
||||||
Parse(element, tokenStream);
|
|
||||||
|
|
||||||
bContinue = (tokenStream.EOS() == false &&
|
while (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_ARRAY_END)
|
||||||
tokenStream.Peek().nType == Token::TOKEN_NEXT_ELEMENT);
|
{
|
||||||
if (bContinue)
|
array.push_back(Parse(tokenStream));
|
||||||
|
|
||||||
|
if (!tokenStream.EOS() && tokenStream.Peek().nType != Token::TOKEN_ARRAY_END)
|
||||||
MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream);
|
MatchExpectedToken(Token::TOKEN_NEXT_ELEMENT, tokenStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchExpectedToken(Token::TOKEN_ARRAY_END, tokenStream);
|
MatchExpectedToken(Token::TOKEN_ARRAY_END, tokenStream);
|
||||||
|
|
||||||
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String Reader::ParseString(Reader::TokenStream& tokenStream)
|
||||||
void Reader::Parse(String& string, Reader::TokenStream& tokenStream)
|
|
||||||
{
|
{
|
||||||
string = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
return MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Number Reader::ParseNumber(Reader::TokenStream& tokenStream)
|
||||||
void Reader::Parse(Number& number, Reader::TokenStream& tokenStream)
|
|
||||||
{
|
{
|
||||||
const Token& currentToken = tokenStream.Peek(); // might need this later for throwing exception
|
const Token& currentToken = tokenStream.Peek(); // might need this later for throwing exception
|
||||||
const std::string& sValue = MatchExpectedToken(Token::TOKEN_NUMBER, tokenStream);
|
const std::string& sValue = MatchExpectedToken(Token::TOKEN_NUMBER, tokenStream);
|
||||||
|
@ -438,25 +386,21 @@ void Reader::Parse(Number& number, Reader::TokenStream& tokenStream)
|
||||||
iStr >> dValue;
|
iStr >> dValue;
|
||||||
|
|
||||||
// did we consume all characters in the token?
|
// did we consume all characters in the token?
|
||||||
if (iStr.eof() == false)
|
if (!iStr.eof())
|
||||||
{
|
|
||||||
throw ParseException("Unexpected character in NUMBER token: " + iStr.peek(), currentToken.locBegin, currentToken.locEnd);
|
throw ParseException("Unexpected character in NUMBER token: " + iStr.peek(), currentToken.locBegin, currentToken.locEnd);
|
||||||
}
|
|
||||||
|
|
||||||
number = dValue;
|
return dValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Boolean Reader::ParseBoolean(Reader::TokenStream& tokenStream)
|
||||||
void Reader::Parse(Boolean& boolean, Reader::TokenStream& tokenStream)
|
|
||||||
{
|
{
|
||||||
const std::string& sValue = MatchExpectedToken(Token::TOKEN_BOOLEAN, tokenStream);
|
return MatchExpectedToken(Token::TOKEN_BOOLEAN, tokenStream) == "true";
|
||||||
boolean = (sValue == "true");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Null Reader::ParseNull(Reader::TokenStream& tokenStream)
|
||||||
void Reader::Parse(Null&, Reader::TokenStream& tokenStream)
|
|
||||||
{
|
{
|
||||||
MatchExpectedToken(Token::TOKEN_NULL, tokenStream);
|
MatchExpectedToken(Token::TOKEN_NULL, tokenStream);
|
||||||
|
return Null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
||||||
LOG_D("hotkey/init") << "Generating hotkeys.";
|
LOG_D("hotkey/init") << "Generating hotkeys.";
|
||||||
|
|
||||||
json::UnknownElement hotkey_root = agi::json_util::file(config_file, default_config);
|
json::UnknownElement hotkey_root = agi::json_util::file(config_file, default_config);
|
||||||
json::Object object = hotkey_root;
|
json::Object const& object = hotkey_root;
|
||||||
|
|
||||||
for (json::Object::const_iterator index(object.begin()); index != object.end(); ++index)
|
for (json::Object::const_iterator index(object.begin()); index != object.end(); ++index)
|
||||||
BuildHotkey(index->first, index->second);
|
BuildHotkey(index->first, index->second);
|
||||||
|
|
|
@ -93,6 +93,8 @@ LogSink::~LogSink() {
|
||||||
array.push_back(entry);
|
array.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root["timeval"] = json::Object();
|
||||||
|
|
||||||
json::Array timeval_open;
|
json::Array timeval_open;
|
||||||
timeval_open.push_back(time_start.tv_sec);
|
timeval_open.push_back(time_start.tv_sec);
|
||||||
timeval_open.push_back(time_start.tv_usec);
|
timeval_open.push_back(time_start.tv_usec);
|
||||||
|
|
|
@ -79,24 +79,24 @@ public:
|
||||||
UnknownElement& operator = (const UnknownElement& unknown);
|
UnknownElement& operator = (const UnknownElement& unknown);
|
||||||
|
|
||||||
// implicit cast to actual element type. throws on failure
|
// implicit cast to actual element type. throws on failure
|
||||||
operator const Object& () const;
|
operator Object const&() const;
|
||||||
operator const Array& () const;
|
operator Array const&() const;
|
||||||
operator const Number& () const;
|
operator Number const&() const;
|
||||||
operator const Boolean& () const;
|
operator Boolean const&() const;
|
||||||
operator const String& () const;
|
operator String const&() const;
|
||||||
operator const Null& () const;
|
operator Null const&() const;
|
||||||
|
operator Object&();
|
||||||
// implicit cast to actual element type. *converts* on failure, and always returns success
|
operator Array&();
|
||||||
operator Object& ();
|
operator Number&();
|
||||||
operator Array& ();
|
operator Boolean&();
|
||||||
operator Number& ();
|
operator String&();
|
||||||
operator Boolean& ();
|
operator Null&();
|
||||||
operator String& ();
|
|
||||||
operator Null& ();
|
|
||||||
|
|
||||||
// provides quick access to children when real element type is object
|
// provides quick access to children when real element type is object
|
||||||
UnknownElement& operator[] (const char *key) { return operator[](std::string(key)); }
|
template<int N>
|
||||||
const UnknownElement& operator[] (const char *key) const { return operator[](std::string(key)); }
|
UnknownElement& operator[] (const char (&key)[N]) { return operator[](std::string(key)); }
|
||||||
|
template<int N>
|
||||||
|
const UnknownElement& operator[] (const char (&key)[N]) const { return operator[](std::string(key)); }
|
||||||
UnknownElement& operator[] (const std::string& key);
|
UnknownElement& operator[] (const std::string& key);
|
||||||
const UnknownElement& operator[] (const std::string& key) const;
|
const UnknownElement& operator[] (const std::string& key) const;
|
||||||
|
|
||||||
|
@ -109,7 +109,8 @@ public:
|
||||||
void Accept(Visitor& visitor);
|
void Accept(Visitor& visitor);
|
||||||
|
|
||||||
// tests equality. first checks type, then value if possible
|
// tests equality. first checks type, then value if possible
|
||||||
bool operator == (const UnknownElement& element) const;
|
bool operator ==(const UnknownElement& element) const;
|
||||||
|
bool operator !=(const UnknownElement& element) const { return !(*this == element); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Imp;
|
class Imp;
|
||||||
|
@ -118,10 +119,10 @@ private:
|
||||||
class Imp_T;
|
class Imp_T;
|
||||||
|
|
||||||
template <typename ElementTypeT>
|
template <typename ElementTypeT>
|
||||||
const ElementTypeT& CastTo() const;
|
ElementTypeT const& CastTo() const;
|
||||||
|
|
||||||
template <typename ElementTypeT>
|
template <typename ElementTypeT>
|
||||||
ElementTypeT& ConvertTo();
|
ElementTypeT& CastTo();
|
||||||
|
|
||||||
Imp* m_pImp;
|
Imp* m_pImp;
|
||||||
};
|
};
|
||||||
|
|
|
@ -110,13 +110,13 @@ private:
|
||||||
void MatchExpectedString(const std::string& sExpected, InputStream& inputStream);
|
void MatchExpectedString(const std::string& sExpected, InputStream& inputStream);
|
||||||
|
|
||||||
// parsing token sequence into element structure
|
// parsing token sequence into element structure
|
||||||
void Parse(UnknownElement& element, TokenStream& tokenStream);
|
UnknownElement Parse(TokenStream& tokenStream);
|
||||||
void Parse(Object& object, TokenStream& tokenStream);
|
Object ParseObject(TokenStream& tokenStream);
|
||||||
void Parse(Array& array, TokenStream& tokenStream);
|
Array ParseArray(TokenStream& tokenStream);
|
||||||
void Parse(String& string, TokenStream& tokenStream);
|
String ParseString(TokenStream& tokenStream);
|
||||||
void Parse(Number& number, TokenStream& tokenStream);
|
Number ParseNumber(TokenStream& tokenStream);
|
||||||
void Parse(Boolean& boolean, TokenStream& tokenStream);
|
Boolean ParseBoolean(TokenStream& tokenStream);
|
||||||
void Parse(Null& null, TokenStream& tokenStream);
|
Null ParseNull(TokenStream& tokenStream);
|
||||||
|
|
||||||
const std::string& MatchExpectedToken(Token::Type nExpected, TokenStream& tokenStream);
|
const std::string& MatchExpectedToken(Token::Type nExpected, TokenStream& tokenStream);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue