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:
Thomas Goyne 2011-10-17 21:59:47 +00:00
parent 2f64a116a7
commit 9dc9047c11
10 changed files with 43 additions and 108 deletions

View file

@ -76,20 +76,18 @@ Hotkey::Hotkey(const std::string &file, const std::string &default_config)
json::Object object = hotkey_root;
for (json::Object::const_iterator index(object.begin()); index != object.end(); index++) {
const json::Object::Member& member = *index;
const json::Object& obj = member.element;
BuildHotkey(member.name, obj);
const json::Object& obj = index->second;
BuildHotkey(index->first, obj);
}
}
void Hotkey::BuildHotkey(std::string const& context, const json::Object& object) {
for (json::Object::const_iterator index(object.begin()); index != object.end(); index++) {
const json::Object::Member& member = *index;
const json::Array& array = member.element;
const json::Array& array = index->second;
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;

View file

@ -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());
for (; index_object != index_objectEnd; ++index_object) {
const json::Object::Member& member = *index_object;
const std::string &member_name = member.name;
const json::UnknownElement& element = member.element;
Load(member_name, (json::Array)element);
const std::string &member_name = index_object->first;
Load(member_name, (json::Array)index_object->second);
}
}

View file

@ -239,10 +239,10 @@ bool Options::PutOption(json::Object &obj, const std::string &path, const json::
// New key, make object.
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);
pos->element.Accept(visitor);
pos->second.Accept(visitor);
return visitor.result;
}
}

View file

@ -43,9 +43,8 @@ void ConfigVisitor::Visit(const json::Object& object) {
name += "/";
for (; index != index_end; ++index) {
const json::Object::Member& member = *index;
const std::string &member_name = member.name;
const json::UnknownElement& element = member.element;
const std::string &member_name = index->first;
const json::UnknownElement& element = index->second;
ConfigVisitor config_visitor(values, name + member_name);
@ -61,11 +60,10 @@ void ConfigVisitor::Visit(const json::Array& array) {
for (; index != indexEnd; ++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) {
const json::Object::Member& member = *index_object;
const std::string& member_name = member.name;
for (; it != index_objectEnd; ++it) {
const std::string& member_name = it->first;
// 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.
@ -86,27 +84,16 @@ void ConfigVisitor::Visit(const json::Array& array) {
}
try {
if (member_name == "string") {
std::string val = (json::String)member.element;
array_list->InsertString(val);
} else if (member_name == "int") {
int64_t val = (int64_t)(json::Number)member.element;
array_list->InsertInt(val);
} else if (member_name == "double") {
double val = (json::Number)member.element;
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);
}
if (member_name == "string")
array_list->InsertString((json::String)it->second);
else if (member_name == "int")
array_list->InsertInt((int64_t)(json::Number)it->second);
else if (member_name == "double")
array_list->InsertDouble((json::Number)it->second);
else if (member_name == "bool")
array_list->InsertBool((json::Boolean)it->second);
else if (member_name == "colour")
array_list->InsertColour((std::string)(json::String)it->second);
} catch (agi::Exception&) {
delete array_list;
throw OptionJsonValueArray("Attempt to insert value into array of wrong type");

View file

@ -185,17 +185,7 @@ private:
class Object
{
public:
struct Member {
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 std::map<std::string, UnknownElement> Members;
typedef Members::iterator iterator;
typedef Members::const_iterator const_iterator;
@ -209,10 +199,10 @@ public:
size_t size() const { return m_Members.size(); }
bool empty() const { return m_Members.empty(); }
iterator find(const std::string& name);
const_iterator find(const std::string& name) const;
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(const Member& member);
iterator insert(std::pair<std::string, UnknownElement> const& ele);
iterator erase(iterator it) { return m_Members.erase(it); }
void clear() { m_Members.clear(); }
@ -220,8 +210,6 @@ public:
const UnknownElement& operator [](const std::string& name) const;
private:
class Finder;
Members m_Members;
};

View file

@ -7,18 +7,10 @@ Author: Terry Caton
***********************************************/
#include "visitor.h"
#include "reader.h"
#include <cassert>
#include <algorithm>
#include <map>
/*
TODO:
* better documentation
*/
namespace json
{
@ -199,40 +191,13 @@ inline bool UnknownElement::operator == (const UnknownElement& element) const
//////////////////
// Object members
inline bool Object::Member::operator == (const Member& member) const
inline Object::iterator Object::insert(std::pair<std::string, UnknownElement> const& ele)
{
return name == member.name && element == member.element;
}
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);
iterator it = find(ele.first);
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 --it;
return m_Members.insert(ele).first;
}
inline UnknownElement& Object::operator [](const std::string& name)
@ -240,9 +205,9 @@ inline UnknownElement& Object::operator [](const std::string& name)
iterator it = find(name);
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
@ -250,7 +215,7 @@ 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->element;
return it->second;
}
/////////////////

View file

@ -402,17 +402,17 @@ inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
tokenStream.Peek().nType != Token::TOKEN_OBJECT_END);
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
const Token& tokenName = tokenStream.Peek();
member.name = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
member.first = MatchExpectedToken(Token::TOKEN_STRING, tokenStream);
// ...then the key/value separator...
MatchExpectedToken(Token::TOKEN_MEMBER_ASSIGN, tokenStream);
// ...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
@ -422,7 +422,7 @@ inline void Reader::Parse(Object& object, Reader::TokenStream& tokenStream)
catch (Exception&)
{
// 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 &&

View file

@ -82,8 +82,8 @@ inline void Writer::Write_i(const Object& object)
Object::const_iterator it(object.begin()),
itend(object.end());
while (it != itend) {
m_ostr << std::string(m_nTabDepth, '\t') << '"' << it->name << "\" : ";
Write_i(it->element);
m_ostr << std::string(m_nTabDepth, '\t') << '"' << it->first << "\" : ";
Write_i(it->second);
if (++it != itend)
m_ostr << ',';

View file

@ -231,7 +231,7 @@ struct CommandMenuBar : public wxMenuBar {
bool read_entry(json::Object const& obj, const char *name, std::string *value) {
json::Object::const_iterator it = obj.find(name);
if (it == obj.end()) return false;
*value = static_cast<json::String const&>(it->element);
*value = static_cast<json::String const&>(it->second);
return true;
}
@ -265,7 +265,7 @@ menu_items const& get_menu(std::string const& name) {
menu_map::const_iterator it = root.find(name);
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);

View file

@ -100,7 +100,7 @@ namespace {
int icon_size = OPT_GET("App/Toolbar Icon Size")->GetInt();
json::Array arr = it->element;
json::Array arr = it->second;
commands.reserve(arr.size());
bool needs_onidle = false;