1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
/// @file Some uninteresting helper functions used by ss_extract.
#include <boost/algorithm/string.hpp>
#include <libxml++/libxml++.h>
#include <glibmm/convert.h>
#include "pak.h"
// LibXML2 logging facility
extern "C" void xmlLogger(void* logger, char const* msg, ...) { if (logger) *(std::ostream*)logger << msg; }
void enableXMLLogger(std::ostream& os = std::cerr) { xmlSetGenericErrorFunc(&os, xmlLogger); }
void disableXMLLogger() { xmlSetGenericErrorFunc(NULL, xmlLogger); }
#if BOOST_FILESYSTEM_VERSION < 3
std::string filename(boost::filesystem::path const& p) { return *--p.end(); }
#else
std::string filename(boost::filesystem::path const& p) { return p.filename().string(); }
#endif
/** Fix Singstar's b0rked XML **/
std::string xmlFix(std::vector<char> const& data) {
std::string ret;
for(std::size_t i = 0; i < data.size(); ++i) {
if (data[i] != '&') ret += data[i]; else ret += "&";
}
return ret;
}
struct SSDom: public xmlpp::DomParser {
xmlpp::Node::PrefixNsMap nsmap;
SSDom(PakFile const& file) {
std::vector<char> tmp;
file.get(tmp);
std::string buf = xmlFix(tmp);
load(buf);
}
SSDom() {}
void load(std::string const& buf) {
set_substitute_entities();
try {
struct DisableLogger {
DisableLogger() { disableXMLLogger(); }
~DisableLogger() { enableXMLLogger(); }
} disabler;
parse_memory(buf);
} catch (...) {
std::string buf2 = Glib::convert(buf, "UTF-8", "ISO-8859-1"); // Convert to UTF-8
parse_memory(buf2);
}
nsmap["ss"] = get_document()->get_root_node()->get_namespace_uri();
}
bool find(xmlpp::Element& elem, std::string xpath, xmlpp::NodeSet& n) {
if (nsmap["ss"].empty()) boost::erase_all(xpath, "ss:");
n = elem.find(xpath, nsmap);
return !n.empty();
}
bool find(std::string const& xpath, xmlpp::NodeSet& n) {
return find(*get_document()->get_root_node(), xpath, n);
}
bool getValue(std::string const& xpath, std::string& result) {
xmlpp::NodeSet n;
if (!find(xpath, n)) return false;
result = dynamic_cast<xmlpp::Element&>(*n[0]).get_child_text()->get_content();
return true;
}
};
/** Erase all occurences of del from str. **/
void safeErase(Glib::ustring& str, Glib::ustring const& del) {
do {
Glib::ustring::size_type pos = str.find(del);
if (pos != Glib::ustring::npos) { str.erase(pos, del.size()); continue; }
} while (0);
}
/** Normalize whitespace **/
Glib::ustring normalize(Glib::ustring const& str) {
Glib::ustring ret;
bool first = true;
bool ws = true;
for (Glib::ustring::const_iterator it = str.begin(); it != str.end(); ++it) {
if (std::isspace(*it)) { ws = true; continue; }
if (first) {
first = false;
ws = false;
ret = Glib::ustring(1, *it).uppercase();
continue;
}
if (ws) { ws = false; ret += ' '; }
ret += *it;
}
return ret;
}
/** Sanitize a string into a form that can be safely used as a filename. **/
std::string safename(Glib::ustring const& str) {
Glib::ustring ret;
Glib::ustring forbidden("\"*/:;<>?\\^`|~");
for (Glib::ustring::const_iterator it = str.begin(); it != str.end(); ++it) {
bool first = it == str.begin();
if (*it < 0x20) continue; // Control characters
if (*it >= 0x7F && *it < 0xA0) continue; // Additional control characters
if (first && *it == '.') continue;
if (first && *it == '-') continue;
if (*it == '&') { ret += " and "; continue; }
if (*it == '%') { ret += " percent "; continue; }
if (*it == '$') { ret += " dollar "; continue; }
if (forbidden.find(*it) != Glib::ustring::npos) { ret += "_"; continue; }
ret += *it;
}
return normalize(ret);
}
/** Fix inconsistencies in SS edition names **/
Glib::ustring prettyEdition(Glib::ustring str) {
str = normalize(str);
safeErase(str, "®");
safeErase(str, "™");
if (str == "SingStar") return "SingStar Original";
if (str == "SingStar '80s") return "SingStar 80s";
if (str == "SingStar Schlager") return "SingStar Svenska Hits Schlager";
if (str == "SingStar Suomi Rock") return "SingStar SuomiRock";
return str;
}
|