From dd46c7af7fd85c195ef0bce422db8c66021f115e Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 17 Oct 2011 22:00:38 +0000 Subject: [PATCH] Completely ditch json::Array and json::Object's custom implementations and switch to typedefs to STL types. Originally committed to SVN as r5752. --- aegisub/libaegisub/common/option.cpp | 2 +- .../include/libaegisub/cajun/elements.h | 74 +----------- .../include/libaegisub/cajun/elements.inl | 53 +-------- .../include/libaegisub/cajun/reader.inl | 106 +++++++----------- .../libaegisub/include/libaegisub/hotkey.h | 5 +- aegisub/libaegisub/include/libaegisub/mru.h | 3 +- .../libaegisub/include/libaegisub/option.h | 2 +- 7 files changed, 56 insertions(+), 189 deletions(-) diff --git a/aegisub/libaegisub/common/option.cpp b/aegisub/libaegisub/common/option.cpp index 8e2ed64ae..17fa75608 100644 --- a/aegisub/libaegisub/common/option.cpp +++ b/aegisub/libaegisub/common/option.cpp @@ -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); diff --git a/aegisub/libaegisub/include/libaegisub/cajun/elements.h b/aegisub/libaegisub/include/libaegisub/cajun/elements.h index e1162a01f..d532fd39c 100644 --- a/aegisub/libaegisub/include/libaegisub/cajun/elements.h +++ b/aegisub/libaegisub/include/libaegisub/cajun/elements.h @@ -20,6 +20,7 @@ namespace json // forward declarations (more info further below) class Visitor; class ConstVisitor; +class UnknownElement; template class TrivialType_T; @@ -27,9 +28,9 @@ class TrivialType_T; typedef double Number; typedef bool Boolean; typedef std::string String; +typedef std::deque Array; +typedef std::map Object; -class Object; -class Array; class Null; @@ -130,75 +131,6 @@ private: Imp* m_pImp; }; -class Array : private std::deque -{ -public: - using std::deque::back; - using std::deque::begin; - using std::deque::clear; - using std::deque::const_iterator; - using std::deque::const_reference; - using std::deque::const_reverse_iterator; - using std::deque::difference_type; - using std::deque::empty; - using std::deque::end; - using std::deque::front; - using std::deque::iterator; - using std::deque::max_size; - using std::deque::pointer; - using std::deque::pop_back; - using std::deque::pop_front; - using std::deque::push_back; - using std::deque::push_front; - using std::deque::rbegin; - using std::deque::reference; - using std::deque::rend; - using std::deque::reverse_iterator; - using std::deque::size; - using std::deque::size_type; - using std::deque::swap; - using std::deque::value_type; - - UnknownElement& operator[](size_t idx); - const UnknownElement& operator[](size_t idx) const; - bool operator==(Array const& rgt) const; -}; - -///////////////////////////////////////////////////////////////////////////////// -// Object - mimics std::map. The member value -// contents are effectively heterogeneous thanks to the UnknownElement class - -class Object -{ -public: - typedef std::map 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 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 diff --git a/aegisub/libaegisub/include/libaegisub/cajun/elements.inl b/aegisub/libaegisub/include/libaegisub/cajun/elements.inl index 9825c6157..cec52a130 100644 --- a/aegisub/libaegisub/include/libaegisub/cajun/elements.inl +++ b/aegisub/libaegisub/include/libaegisub/cajun/elements.inl @@ -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()[key]; + Object const& obj = CastTo(); + 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 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::operator[](idx); -} - -inline const UnknownElement& Array::operator[](size_t idx) const { - if (idx >= size()) - throw Exception("Array out of bounds"); - return std::deque::operator[](idx); -} - -inline bool Array::operator==(Array const& rgt) const { - return *static_cast *>(this) == rgt; -} - } // end namespace diff --git a/aegisub/libaegisub/include/libaegisub/cajun/reader.inl b/aegisub/libaegisub/include/libaegisub/cajun/reader.inl index 6b5abd43f..b445ec6da 100644 --- a/aegisub/libaegisub/include/libaegisub/cajun/reader.inl +++ b/aegisub/libaegisub/include/libaegisub/cajun/reader.inl @@ -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 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; diff --git a/aegisub/libaegisub/include/libaegisub/hotkey.h b/aegisub/libaegisub/include/libaegisub/hotkey.h index cadc9a4e6..4fccec64e 100644 --- a/aegisub/libaegisub/include/libaegisub/hotkey.h +++ b/aegisub/libaegisub/include/libaegisub/hotkey.h @@ -26,7 +26,10 @@ #include #endif -namespace json { class Object; } +namespace json { + class UnknownElement; + typedef std::map Object; +} namespace agi { namespace hotkey { diff --git a/aegisub/libaegisub/include/libaegisub/mru.h b/aegisub/libaegisub/include/libaegisub/mru.h index 4458d9e01..9f8fa5857 100644 --- a/aegisub/libaegisub/include/libaegisub/mru.h +++ b/aegisub/libaegisub/include/libaegisub/mru.h @@ -27,7 +27,8 @@ #include namespace json { - class Array; + class UnknownElement; + typedef std::deque Array; } namespace agi { diff --git a/aegisub/libaegisub/include/libaegisub/option.h b/aegisub/libaegisub/include/libaegisub/option.h index d8853b5c6..d93507c85 100644 --- a/aegisub/libaegisub/include/libaegisub/option.h +++ b/aegisub/libaegisub/include/libaegisub/option.h @@ -28,8 +28,8 @@ #include namespace json { - class Object; class UnknownElement; + typedef std::map Object; } namespace agi {