summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/hiscores.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-25 08:58:25 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-03-25 08:58:25 +0000
commitec685f4e71424403b322d3971ac68b31821fe7e1 (patch)
tree11a11f0c7214a74048bcfa0a013a8b7beba204cf /crawl-ref/source/hiscores.cc
parenteb51ffff58cbb272a5332f946ca9ca903ec4695e (diff)
downloadcrawl-ref-ec685f4e71424403b322d3971ac68b31821fe7e1.tar.gz
crawl-ref-ec685f4e71424403b322d3971ac68b31821fe7e1.zip
Cleaned up hiscores xlog format (suggested by Shawn Moore). Breaks compatbility
with older xlogfiles. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1093 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/hiscores.cc')
-rw-r--r--crawl-ref/source/hiscores.cc425
1 files changed, 219 insertions, 206 deletions
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 72d6dbdac2..3455c3d5e1 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -624,10 +624,10 @@ bool scorefile_entry::parse(const std::string &line)
// 4) 0.2 and onwards, which are xlogfile format - no leading
// colon, fields separated by colons, each field specified as
// key=value. Colons are not allowed in key names, must be escaped to
- // | in values. Literal | must be escaped as || in values.
+ // :: in values.
//
// 0.2 only reads entries of type (3) and (4), and only writes entries of
- // type (4).
+ // type (4). 0.3 or 0.4 may discontinue read support for (3).
// Leading colon implies 4.0 style line:
if (line[0] == ':')
@@ -636,148 +636,24 @@ bool scorefile_entry::parse(const std::string &line)
return (parse_scoreline(line));
}
-// xlogfile escape: s/\\/\\\\/g, s/|/\\|/g, s/:/|/g,
-std::string scorefile_entry::xlog_escape(const std::string &s) const
-{
- return
- replace_all_of(
- replace_all_of(
- replace_all_of(s, "\\", "\\\\"),
- "|", "\\|" ),
- ":", "|" );
-}
-
-// xlogfile unescape: s/\\(.)/$1/g, s/|/:/g
-std::string scorefile_entry::xlog_unescape(const std::string &s) const
-{
- std::string unesc = s;
- bool escaped = false;
- for (int i = 0, size = unesc.size(); i < size; ++i)
- {
- const char c = unesc[i];
- if (escaped)
- {
- escaped = false;
- continue;
- }
-
- if (c == '|')
- unesc[i] = ':';
- else if (c == '\\')
- {
- escaped = true;
- unesc.erase(i--, 1);
- size--;
- }
- }
- return (unesc);
-}
-
std::string scorefile_entry::raw_string() const
{
set_score_fields();
if (!fields.get())
return ("");
-
- std::string line;
- for (int i = 0, size = fields->size(); i < size; ++i)
- {
- const std::pair<std::string, std::string> &f = (*fields)[i];
- // Don't write empty fields.
- if (f.second.empty())
- continue;
-
- if (!line.empty())
- line += ":";
-
- line += f.first;
- line += "=";
- line += xlog_escape(f.second);
- }
-
- return (line);
+ return fields->xlog_line();
}
bool scorefile_entry::parse_scoreline(const std::string &line)
{
- std::vector<std::string> rawfields = split_string(":", line);
- fields.reset(new hs_fields);
- for (int i = 0, size = rawfields.size(); i < size; ++i)
- {
- const std::string field = rawfields[i];
- std::string::size_type st = field.find('=');
- if (st == std::string::npos)
- continue;
-
- fields->push_back(
- std::pair<std::string, std::string>(
- field.substr(0, st),
- xlog_unescape(field.substr(st + 1)) ) );
- }
-
+ fields.reset(new xlog_fields(line));
init_with_fields();
return (true);
}
-void scorefile_entry::add_field(const std::string &key,
- const char *format,
- ...) const
-{
- char buf[400];
- va_list args;
- va_start(args, format);
- vsnprintf(buf, sizeof buf, format, args);
- va_end(args);
-
- fields->push_back(
- std::pair<std::string, std::string>( key, buf ) );
-}
-
-void scorefile_entry::add_auxkill_field() const
-{
- add_field("kaux", "%s", auxkilldata.c_str());
-}
-
-void scorefile_entry::read_auxkill_field()
-{
- auxkilldata = str_field("kaux");
-}
-
-std::string scorefile_entry::str_field(const std::string &s) const
-{
- hs_map::const_iterator i = fieldmap->find(s);
- if (i == fieldmap->end())
- return ("");
-
- return i->second;
-}
-
-int scorefile_entry::int_field(const std::string &s) const
-{
- std::string field = str_field(s);
- return atoi(field.c_str());
-}
-
-long scorefile_entry::long_field(const std::string &s) const
-{
- std::string field = str_field(s);
- return atol(field.c_str());
-}
-
-void scorefile_entry::map_fields()
-{
- fieldmap.reset(new hs_map);
- for (int i = 0, size = fields->size(); i < size; ++i)
- {
- const std::pair<std::string, std::string> f = (*fields)[i];
-
- (*fieldmap)[f.first] = f.second;
- }
-}
-
static const char *short_branch_name(int branch)
{
if (branch >= 0 && branch < NUM_BRANCHES)
@@ -830,113 +706,110 @@ static int str_to_god(const std::string &god)
void scorefile_entry::init_with_fields()
{
- map_fields();
- points = long_field("sc");
- name = str_field("name");
- uid = int_field("uid");
-
- race = str_to_species(str_field("race"));
- cls = get_class_index_by_name(str_field("cls").c_str());
-
- lvl = int_field("xl");
-
- best_skill = str_to_skill(str_field("sk"));
- best_skill_lvl = int_field("sklev");
- death_type = str_to_kill_method(str_field("ktyp"));
- death_source_name = str_field("killer");
-
- read_auxkill_field();
-
- branch = str_to_branch(str_field("br"));
- dlvl = int_field("lvl");
- level_type = str_to_level_area_type(str_field("ltyp"));
-
- final_hp = int_field("hp");
- final_max_hp = int_field("mhp");
- final_max_max_hp = int_field("mmhp");
- damage = int_field("dam");
- str = int_field("str");
- intel = int_field("int");
- dex = int_field("dex");
-
- god = str_to_god(str_field("god"));
- piety = int_field("piety");
- penance = int_field("pen");
- wiz_mode = int_field("wiz");
- birth_time = parse_time(str_field("start"));
- death_time = parse_time(str_field("end"));
- real_time = long_field("dur");
- num_turns = long_field("turn");
- num_diff_runes = int_field("urune");
- num_runes = int_field("nrune");
+ points = fields->long_field("sc");
+ name = fields->str_field("name");
+ uid = fields->int_field("uid");
+
+ race = str_to_species(fields->str_field("race"));
+ cls = get_class_index_by_name(fields->str_field("cls").c_str());
+
+ lvl = fields->int_field("xl");
+
+ best_skill = str_to_skill(fields->str_field("sk"));
+ best_skill_lvl = fields->int_field("sklev");
+ death_type = str_to_kill_method(fields->str_field("ktyp"));
+ death_source_name = fields->str_field("killer");
+ auxkilldata = fields->str_field("kaux");
+ branch = str_to_branch(fields->str_field("br"));
+ dlvl = fields->int_field("lvl");
+ level_type = str_to_level_area_type(fields->str_field("ltyp"));
+
+ final_hp = fields->int_field("hp");
+ final_max_hp = fields->int_field("mhp");
+ final_max_max_hp = fields->int_field("mmhp");
+ damage = fields->int_field("dam");
+ str = fields->int_field("str");
+ intel = fields->int_field("int");
+ dex = fields->int_field("dex");
+
+ god = str_to_god(fields->str_field("god"));
+ piety = fields->int_field("piety");
+ penance = fields->int_field("pen");
+ wiz_mode = fields->int_field("wiz");
+ birth_time = parse_time(fields->str_field("start"));
+ death_time = parse_time(fields->str_field("end"));
+ real_time = fields->long_field("dur");
+ num_turns = fields->long_field("turn");
+ num_diff_runes = fields->int_field("urune");
+ num_runes = fields->int_field("nrune");
}
void scorefile_entry::set_score_fields() const
{
- fields.reset(new hs_fields());
+ fields.reset(new xlog_fields);
if (!fields.get())
return;
- add_field("v", VER_NUM);
- add_field("lv", SCORE_VERSION);
- add_field("sc", "%ld", points);
- add_field("name", "%s", name.c_str());
- add_field("uid", "%d", uid);
- add_field("race", "%s", species_name(race, lvl));
- add_field("cls", "%s", get_class_name(cls));
- add_field("xl", "%d", lvl);
- add_field("sk", "%s", skill_name(best_skill));
- add_field("sklev", "%d", best_skill_lvl);
- add_field("title", "%s", skill_title( best_skill, best_skill_lvl,
+ fields->add_field("v", VER_NUM);
+ fields->add_field("lv", SCORE_VERSION);
+ fields->add_field("sc", "%ld", points);
+ fields->add_field("name", "%s", name.c_str());
+ fields->add_field("uid", "%d", uid);
+ fields->add_field("race", "%s", species_name(race, lvl));
+ fields->add_field("cls", "%s", get_class_name(cls));
+ fields->add_field("xl", "%d", lvl);
+ fields->add_field("sk", "%s", skill_name(best_skill));
+ fields->add_field("sklev", "%d", best_skill_lvl);
+ fields->add_field("title", "%s", skill_title( best_skill, best_skill_lvl,
race, str, dex, god ) );
- add_field("ktyp", ::kill_method_name(kill_method_type(death_type)));
- add_field("killer", death_source_desc());
+ fields->add_field("ktyp", ::kill_method_name(kill_method_type(death_type)));
+ fields->add_field("killer", death_source_desc());
- add_auxkill_field();
+ fields->add_field("kaux", "%s", auxkilldata.c_str());
- add_field("place", "%s",
+ fields->add_field("place", "%s",
place_name(get_packed_place(branch, dlvl, level_type),
false, true).c_str());
- add_field("br", "%s", short_branch_name(branch));
- add_field("lvl", "%d", dlvl);
- add_field("ltyp", "%s", level_area_type_name(level_type));
-
- add_field("hp", "%d", final_hp);
- add_field("mhp", "%d", final_max_hp);
- add_field("mmhp", "%d", final_max_max_hp);
- add_field("dam", "%d", damage);
- add_field("str", "%d", str);
- add_field("int", "%d", intel);
- add_field("dex", "%d", dex);
+ fields->add_field("br", "%s", short_branch_name(branch));
+ fields->add_field("lvl", "%d", dlvl);
+ fields->add_field("ltyp", "%s", level_area_type_name(level_type));
+
+ fields->add_field("hp", "%d", final_hp);
+ fields->add_field("mhp", "%d", final_max_hp);
+ fields->add_field("mmhp", "%d", final_max_max_hp);
+ fields->add_field("dam", "%d", damage);
+ fields->add_field("str", "%d", str);
+ fields->add_field("int", "%d", intel);
+ fields->add_field("dex", "%d", dex);
// Don't write No God to save some space.
if (god != -1)
- add_field("god", "%s", god == GOD_NO_GOD? "" : god_name(god));
+ fields->add_field("god", "%s", god == GOD_NO_GOD? "" : god_name(god));
if (piety > 0)
- add_field("piety", "%d", piety);
+ fields->add_field("piety", "%d", piety);
if (penance > 0)
- add_field("pen", "%d", penance);
+ fields->add_field("pen", "%d", penance);
if (wiz_mode)
- add_field("wiz", "%d", wiz_mode);
+ fields->add_field("wiz", "%d", wiz_mode);
- add_field("start", "%s", make_date_string(birth_time).c_str());
- add_field("end", "%s", make_date_string(death_time).c_str());
- add_field("dur", "%ld", real_time);
- add_field("turn", "%ld", num_turns);
+ fields->add_field("start", "%s", make_date_string(birth_time).c_str());
+ fields->add_field("end", "%s", make_date_string(death_time).c_str());
+ fields->add_field("dur", "%ld", real_time);
+ fields->add_field("turn", "%ld", num_turns);
if (num_diff_runes)
- add_field("urune", "%d", num_diff_runes);
+ fields->add_field("urune", "%d", num_diff_runes);
if (num_runes)
- add_field("nrune", "%d", num_runes);
+ fields->add_field("nrune", "%d", num_runes);
#ifdef DGL_EXTENDED_LOGFILES
const std::string short_msg = short_kill_message();
- add_field("tmsg", "%s", short_msg.c_str());
+ fields->add_field("tmsg", "%s", short_msg.c_str());
const std::string long_msg = long_kill_message();
if (long_msg != short_msg)
- add_field("vmsg", "%s", long_msg.c_str());
+ fields->add_field("vmsg", "%s", long_msg.c_str());
#endif
}
@@ -2058,3 +1931,143 @@ scorefile_entry::death_description(death_desc_verbosity verbosity) const
return (desc);
}
+
+//////////////////////////////////////////////////////////////////////////////
+// xlog_fields
+
+xlog_fields::xlog_fields() : fields(), fieldmap()
+{
+}
+
+xlog_fields::xlog_fields(const std::string &line) : fields(), fieldmap()
+{
+ init(line);
+}
+
+std::string::size_type
+xlog_fields::next_separator(const std::string &s,
+ std::string::size_type start) const
+{
+ std::string::size_type p = s.find(':', start);
+ if (p != std::string::npos && p < s.length() - 1 && s[p + 1] == ':')
+ return next_separator(s, p + 2);
+
+ return (p);
+}
+
+std::vector<std::string>
+xlog_fields::split_fields(const std::string &s) const
+{
+ std::string::size_type start = 0, end = 0;
+ std::vector<std::string> fs;
+
+ for ( ; (end = next_separator(s, start)) != std::string::npos;
+ start = end + 1 )
+ {
+ fs.push_back( s.substr(start, end - start) );
+ }
+
+ if (start < s.length())
+ fs.push_back( s.substr(start) );
+
+ return (fs);
+}
+
+void xlog_fields::init(const std::string &line)
+{
+ std::vector<std::string> rawfields = split_fields(line);
+ for (int i = 0, size = rawfields.size(); i < size; ++i)
+ {
+ const std::string field = rawfields[i];
+ std::string::size_type st = field.find('=');
+ if (st == std::string::npos)
+ continue;
+
+ fields.push_back(
+ std::pair<std::string, std::string>(
+ field.substr(0, st),
+ xlog_unescape(field.substr(st + 1)) ) );
+ }
+
+ map_fields();
+}
+
+// xlogfile escape: s/:/::/g
+std::string xlog_fields::xlog_escape(const std::string &s) const
+{
+ return replace_all(s, ":", "::");
+}
+
+// xlogfile unescape: s/::/:/g
+std::string xlog_fields::xlog_unescape(const std::string &s) const
+{
+ return replace_all(s, "::", ":");
+}
+
+void xlog_fields::add_field(const std::string &key,
+ const char *format,
+ ...)
+{
+ char buf[500];
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buf, sizeof buf, format, args);
+ va_end(args);
+
+ fields.push_back(
+ std::pair<std::string, std::string>( key, buf ) );
+ fieldmap[key] = buf;
+}
+
+std::string xlog_fields::str_field(const std::string &s) const
+{
+ xl_map::const_iterator i = fieldmap.find(s);
+ if (i == fieldmap.end())
+ return ("");
+
+ return i->second;
+}
+
+int xlog_fields::int_field(const std::string &s) const
+{
+ std::string field = str_field(s);
+ return atoi(field.c_str());
+}
+
+long xlog_fields::long_field(const std::string &s) const
+{
+ std::string field = str_field(s);
+ return atol(field.c_str());
+}
+
+void xlog_fields::map_fields() const
+{
+ fieldmap.clear();
+ for (int i = 0, size = fields.size(); i < size; ++i)
+ {
+ const std::pair<std::string, std::string> &f = fields[i];
+ fieldmap[f.first] = f.second;
+ }
+}
+
+std::string xlog_fields::xlog_line() const
+{
+ std::string line;
+ for (int i = 0, size = fields.size(); i < size; ++i)
+ {
+ const std::pair<std::string, std::string> &f = fields[i];
+
+ // Don't write empty fields.
+ if (f.second.empty())
+ continue;
+
+ if (!line.empty())
+ line += ":";
+
+ line += f.first;
+ line += "=";
+ line += xlog_escape(f.second);
+ }
+
+ return (line);
+}