forked from mia/Aegisub
Change json::Object's backing store from a list to a map. Cajun used list to preserve order, but json objects do not guarantee that order will be preserved
Originally committed to SVN as r5747.
This commit is contained in:
parent
2f64a116a7
commit
9dc9047c11
10 changed files with 43 additions and 108 deletions
|
@ -76,20 +76,18 @@ Hotkey::Hotkey(const std::string &file, const std::string &default_config)
|
||||||
json::Object object = hotkey_root;
|
json::Object 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++) {
|
||||||
const json::Object::Member& member = *index;
|
const json::Object& obj = index->second;
|
||||||
const json::Object& obj = member.element;
|
BuildHotkey(index->first, obj);
|
||||||
BuildHotkey(member.name, obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Hotkey::BuildHotkey(std::string const& context, const json::Object& object) {
|
void Hotkey::BuildHotkey(std::string const& context, const json::Object& object) {
|
||||||
for (json::Object::const_iterator index(object.begin()); index != object.end(); index++) {
|
for (json::Object::const_iterator index(object.begin()); index != object.end(); index++) {
|
||||||
const json::Object::Member& member = *index;
|
const json::Array& array = index->second;
|
||||||
const json::Array& array = member.element;
|
|
||||||
|
|
||||||
for (json::Array::const_iterator arr_index(array.begin()); arr_index != array.end(); arr_index++) {
|
for (json::Array::const_iterator arr_index(array.begin()); arr_index != array.end(); arr_index++) {
|
||||||
Combo combo(context, member.name);
|
Combo combo(context, index->first);
|
||||||
|
|
||||||
const json::Object& obj = *arr_index;
|
const json::Object& obj = *arr_index;
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,8 @@ MRUManager::MRUManager(const std::string &config, const std::string &default_con
|
||||||
json::Object::const_iterator index_object(root_new.begin()), index_objectEnd(root_new.end());
|
json::Object::const_iterator index_object(root_new.begin()), index_objectEnd(root_new.end());
|
||||||
|
|
||||||
for (; index_object != index_objectEnd; ++index_object) {
|
for (; index_object != index_objectEnd; ++index_object) {
|
||||||
const json::Object::Member& member = *index_object;
|
const std::string &member_name = index_object->first;
|
||||||
const std::string &member_name = member.name;
|
Load(member_name, (json::Array)index_object->second);
|
||||||
const json::UnknownElement& element = member.element;
|
|
||||||
|
|
||||||
Load(member_name, (json::Array)element);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,10 +239,10 @@ bool Options::PutOption(json::Object &obj, const std::string &path, const json::
|
||||||
|
|
||||||
// New key, make object.
|
// New key, make object.
|
||||||
if (pos == obj.end())
|
if (pos == obj.end())
|
||||||
pos = obj.insert(json::Object::Member(thispart, json::Object()));
|
pos = obj.insert(make_pair(thispart, json::Object()));
|
||||||
|
|
||||||
PutOptionVisitor visitor(restpart, value);
|
PutOptionVisitor visitor(restpart, value);
|
||||||
pos->element.Accept(visitor);
|
pos->second.Accept(visitor);
|
||||||
return visitor.result;
|
return visitor.result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,8 @@ void ConfigVisitor::Visit(const json::Object& object) {
|
||||||
name += "/";
|
name += "/";
|
||||||
|
|
||||||
for (; index != index_end; ++index) {
|
for (; index != index_end; ++index) {
|
||||||
const json::Object::Member& member = *index;
|
const std::string &member_name = index->first;
|
||||||
const std::string &member_name = member.name;
|
const json::UnknownElement& element = index->second;
|
||||||
const json::UnknownElement& element = member.element;
|
|
||||||
|
|
||||||
ConfigVisitor config_visitor(values, name + member_name);
|
ConfigVisitor config_visitor(values, name + member_name);
|
||||||
|
|
||||||
|
@ -61,11 +60,10 @@ void ConfigVisitor::Visit(const json::Array& array) {
|
||||||
for (; index != indexEnd; ++index) {
|
for (; index != indexEnd; ++index) {
|
||||||
const json::Object& index_array = *index;
|
const json::Object& index_array = *index;
|
||||||
|
|
||||||
json::Object::const_iterator index_object(index_array.begin()), index_objectEnd(index_array.end());
|
json::Object::const_iterator it(index_array.begin()), index_objectEnd(index_array.end());
|
||||||
|
|
||||||
for (; index_object != index_objectEnd; ++index_object) {
|
for (; it != index_objectEnd; ++it) {
|
||||||
const json::Object::Member& member = *index_object;
|
const std::string& member_name = it->first;
|
||||||
const std::string& member_name = member.name;
|
|
||||||
|
|
||||||
// This can only happen once since a list must always be of the same
|
// This can only happen once since a list must always be of the same
|
||||||
// type, if we try inserting another type into it we want it to fail.
|
// type, if we try inserting another type into it we want it to fail.
|
||||||
|
@ -86,27 +84,16 @@ void ConfigVisitor::Visit(const json::Array& array) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (member_name == "string") {
|
if (member_name == "string")
|
||||||
std::string val = (json::String)member.element;
|
array_list->InsertString((json::String)it->second);
|
||||||
array_list->InsertString(val);
|
else if (member_name == "int")
|
||||||
|
array_list->InsertInt((int64_t)(json::Number)it->second);
|
||||||
} else if (member_name == "int") {
|
else if (member_name == "double")
|
||||||
int64_t val = (int64_t)(json::Number)member.element;
|
array_list->InsertDouble((json::Number)it->second);
|
||||||
array_list->InsertInt(val);
|
else if (member_name == "bool")
|
||||||
|
array_list->InsertBool((json::Boolean)it->second);
|
||||||
} else if (member_name == "double") {
|
else if (member_name == "colour")
|
||||||
double val = (json::Number)member.element;
|
array_list->InsertColour((std::string)(json::String)it->second);
|
||||||
array_list->InsertDouble(val);
|
|
||||||
|
|
||||||
} else if (member_name == "bool") {
|
|
||||||
bool val = (json::Boolean)member.element;
|
|
||||||
array_list->InsertBool(val);
|
|
||||||
|
|
||||||
} else if (member_name == "colour") {
|
|
||||||
std::string val = (json::String)member.element;
|
|
||||||
Colour col(val);
|
|
||||||
array_list->InsertColour(col);
|
|
||||||
}
|
|
||||||
} catch (agi::Exception&) {
|
} catch (agi::Exception&) {
|
||||||
delete array_list;
|
delete array_list;
|
||||||
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");
|
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");
|
||||||
|
|
|
@ -185,17 +185,7 @@ private:
|
||||||
class Object
|
class Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Member {
|
typedef std::map<std::string, UnknownElement> Members;
|
||||||
Member(const std::string& nameIn = std::string(), const UnknownElement& elementIn = UnknownElement())
|
|
||||||
: name(nameIn), element(elementIn) { }
|
|
||||||
|
|
||||||
bool operator == (const Member& member) const;
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
UnknownElement element;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::list<Member> Members; // map faster, but does not preserve order
|
|
||||||
typedef Members::iterator iterator;
|
typedef Members::iterator iterator;
|
||||||
typedef Members::const_iterator const_iterator;
|
typedef Members::const_iterator const_iterator;
|
||||||
|
|
||||||
|
@ -209,10 +199,10 @@ public:
|
||||||
size_t size() const { return m_Members.size(); }
|
size_t size() const { return m_Members.size(); }
|
||||||
bool empty() const { return m_Members.empty(); }
|
bool empty() const { return m_Members.empty(); }
|
||||||
|
|
||||||
iterator find(const std::string& name);
|
iterator find(const std::string& name) { return m_Members.find(name); }
|
||||||
const_iterator find(const std::string& name) const;
|
const_iterator find(const std::string& name) const { return m_Members.find(name); }
|
||||||
|
|
||||||
iterator insert(const Member& member);
|
iterator insert(std::pair<std::string, UnknownElement> const& ele);
|
||||||
iterator erase(iterator it) { return m_Members.erase(it); }
|
iterator erase(iterator it) { return m_Members.erase(it); }
|
||||||
void clear() { m_Members.clear(); }
|
void clear() { m_Members.clear(); }
|
||||||
|
|
||||||
|
@ -220,8 +210,6 @@ public:
|
||||||
const UnknownElement& operator [](const std::string& name) const;
|
const UnknownElement& operator [](const std::string& name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Finder;
|
|
||||||
|
|
||||||
Members m_Members;
|
Members m_Members;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,18 +7,10 @@ Author: Terry Caton
|
||||||
***********************************************/
|
***********************************************/
|
||||||
|
|
||||||
#include "visitor.h"
|
#include "visitor.h"
|
||||||
#include "reader.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
* better documentation
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace json
|
namespace json
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -199,40 +191,13 @@ inline bool UnknownElement::operator == (const UnknownElement& element) const
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// Object members
|
// Object members
|
||||||
|
inline Object::iterator Object::insert(std::pair<std::string, UnknownElement> const& ele)
|
||||||
inline bool Object::Member::operator == (const Member& member) const
|
|
||||||
{
|
{
|
||||||
return name == member.name && element == member.element;
|
iterator it = find(ele.first);
|
||||||
}
|
|
||||||
|
|
||||||
class Object::Finder : public std::unary_function<Object::Member, bool>
|
|
||||||
{
|
|
||||||
std::string m_name;
|
|
||||||
public:
|
|
||||||
Finder(const std::string& name) : m_name(name) {}
|
|
||||||
bool operator () (const Object::Member& member) {
|
|
||||||
return member.name == m_name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline Object::iterator Object::find(const std::string& name)
|
|
||||||
{
|
|
||||||
return std::find_if(m_Members.begin(), m_Members.end(), Finder(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Object::const_iterator Object::find(const std::string& name) const
|
|
||||||
{
|
|
||||||
return std::find_if(m_Members.begin(), m_Members.end(), Finder(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Object::iterator Object::insert(const Member& member)
|
|
||||||
{
|
|
||||||
iterator it = find(member.name);
|
|
||||||
if (it != m_Members.end())
|
if (it != m_Members.end())
|
||||||
throw Exception("Object member already exists: " + member.name);
|
throw Exception("Object member already exists: " + ele.first);
|
||||||
|
|
||||||
m_Members.push_back(member);
|
return m_Members.insert(ele).first;
|
||||||
return --it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UnknownElement& Object::operator [](const std::string& name)
|
inline UnknownElement& Object::operator [](const std::string& name)
|
||||||
|
@ -240,9 +205,9 @@ inline UnknownElement& Object::operator [](const std::string& name)
|
||||||
iterator it = find(name);
|
iterator it = find(name);
|
||||||
if (it == m_Members.end())
|
if (it == m_Members.end())
|
||||||
{
|
{
|
||||||
it = insert(Member(name));
|
it = insert(make_pair(name, UnknownElement()));
|
||||||
}
|
}
|
||||||
return it->element;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const UnknownElement& Object::operator [](const std::string& name) const
|
inline const UnknownElement& Object::operator [](const std::string& name) const
|
||||||
|
@ -250,7 +215,7 @@ inline const UnknownElement& Object::operator [](const std::string& name) const
|
||||||
const_iterator it = find(name);
|
const_iterator it = find(name);
|
||||||
if (it == end())
|
if (it == end())
|
||||||
throw Exception("Object member not found: " + name);
|
throw Exception("Object member not found: " + name);
|
||||||
return it->element;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
|
|
|
@ -402,17 +402,17 @@ inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
|
||||||
tokenStream.Peek().nType != Token::TOKEN_OBJECT_END);
|
tokenStream.Peek().nType != Token::TOKEN_OBJECT_END);
|
||||||
while (bContinue)
|
while (bContinue)
|
||||||
{
|
{
|
||||||
Object::Member member;
|
std::pair<std::string, UnknownElement> member;
|
||||||
|
|
||||||
// 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();
|
||||||
member.name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
member.first = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
|
||||||
|
|
||||||
// ...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).
|
||||||
Parse(member.element, tokenStream);
|
Parse(member.second, tokenStream);
|
||||||
|
|
||||||
// try adding it to the object (this could throw)
|
// try adding it to the object (this could throw)
|
||||||
try
|
try
|
||||||
|
@ -422,7 +422,7 @@ inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
|
||||||
catch (Exception&)
|
catch (Exception&)
|
||||||
{
|
{
|
||||||
// must be a duplicate name
|
// must be a duplicate name
|
||||||
throw ParseException("Duplicate object member token: " + member.name, tokenName.locBegin, tokenName.locEnd);
|
throw ParseException("Duplicate object member token: " + member.first, tokenName.locBegin, tokenName.locEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bContinue = (tokenStream.EOS() == false &&
|
bContinue = (tokenStream.EOS() == false &&
|
||||||
|
|
|
@ -82,8 +82,8 @@ inline void Writer::Write_i(const Object& object)
|
||||||
Object::const_iterator it(object.begin()),
|
Object::const_iterator it(object.begin()),
|
||||||
itend(object.end());
|
itend(object.end());
|
||||||
while (it != itend) {
|
while (it != itend) {
|
||||||
m_ostr << std::string(m_nTabDepth, '\t') << '"' << it->name << "\" : ";
|
m_ostr << std::string(m_nTabDepth, '\t') << '"' << it->first << "\" : ";
|
||||||
Write_i(it->element);
|
Write_i(it->second);
|
||||||
|
|
||||||
if (++it != itend)
|
if (++it != itend)
|
||||||
m_ostr << ',';
|
m_ostr << ',';
|
||||||
|
|
|
@ -231,7 +231,7 @@ struct CommandMenuBar : public wxMenuBar {
|
||||||
bool read_entry(json::Object const& obj, const char *name, std::string *value) {
|
bool read_entry(json::Object const& obj, const char *name, std::string *value) {
|
||||||
json::Object::const_iterator it = obj.find(name);
|
json::Object::const_iterator it = obj.find(name);
|
||||||
if (it == obj.end()) return false;
|
if (it == obj.end()) return false;
|
||||||
*value = static_cast<json::String const&>(it->element);
|
*value = static_cast<json::String const&>(it->second);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ menu_items const& get_menu(std::string const& name) {
|
||||||
|
|
||||||
menu_map::const_iterator it = root.find(name);
|
menu_map::const_iterator it = root.find(name);
|
||||||
if (it == root.end()) throw menu::UnknownMenu("Menu named " + name + " not found");
|
if (it == root.end()) throw menu::UnknownMenu("Menu named " + name + " not found");
|
||||||
return it->element;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMenu *build_menu(std::string const& name, agi::Context *c, CommandManager *cm, wxMenu *menu = 0);
|
wxMenu *build_menu(std::string const& name, agi::Context *c, CommandManager *cm, wxMenu *menu = 0);
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace {
|
||||||
|
|
||||||
int icon_size = OPT_GET("App/Toolbar Icon Size")->GetInt();
|
int icon_size = OPT_GET("App/Toolbar Icon Size")->GetInt();
|
||||||
|
|
||||||
json::Array arr = it->element;
|
json::Array arr = it->second;
|
||||||
commands.reserve(arr.size());
|
commands.reserve(arr.size());
|
||||||
bool needs_onidle = false;
|
bool needs_onidle = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue