Update to v094r17 release.

byuu says:

This updates higan to use the new Markup::Node changes. This is a really
big change, and one slight typo anywhere could break certain classes of
games from playing.

I don't have ananke hooked up again yet, so I don't have the ability to
test this much. If anyone with some v094 game folders wouldn't mind
testing, I'd help out a great deal.

I'm most concerned about testing one of each SNES special chip game.
Most notably, systems like the SA-1, HitachiDSP and NEC-DSP were using
the fancier lookups, eg node["rom[0]/name"], which I had to convert to
a rather ugly node["rom"].at(0)["name"], which I'm fairly confident
won't work. I'm going to blame that on the fumes from the shelves I just
stained >.> Might work with node.find("rom[0]/name")(0) though ...? But
so ugly ... ugh.

That aside, this WIP adds the accuracy-PPU inlining, so the accuracy
profile should run around 7.5% faster than before.
This commit is contained in:
Tim Allen
2015-05-02 23:05:46 +10:00
parent c335ee9d80
commit 39ca8a2fab
45 changed files with 709 additions and 566 deletions

View File

@@ -1,12 +1,17 @@
#ifdef NALL_STRING_INTERNAL_HPP
//BML v1.0 parser
//revision 0.03
//revision 0.04
namespace nall {
namespace BML {
struct Node : Markup::Node {
//metadata is used to store nesting level
struct ManagedNode;
using SharedNode = shared_pointer<ManagedNode>;
struct ManagedNode : Markup::ManagedNode {
protected:
//test to verify if a valid character for a node name
bool valid(char p) const { //A-Z, a-z, 0-9, -.
@@ -32,7 +37,7 @@ protected:
unsigned length = 0;
while(valid(p[length])) length++;
if(length == 0) throw "Invalid node name";
name = substr(p, 0, length);
_name = substr(p, 0, length);
p += length;
}
@@ -41,18 +46,18 @@ protected:
unsigned length = 2;
while(p[length] && p[length] != '\n' && p[length] != '\"') length++;
if(p[length] != '\"') throw "Unescaped value";
data = {substr(p, 2, length - 2), "\n"};
_value = {substr(p, 2, length - 2), "\n"};
p += length + 1;
} else if(*p == '=') {
unsigned length = 1;
while(p[length] && p[length] != '\n' && p[length] != '\"' && p[length] != ' ') length++;
if(p[length] == '\"') throw "Illegal character in value";
data = {substr(p, 1, length - 1), "\n"};
_value = {substr(p, 1, length - 1), "\n"};
p += length;
} else if(*p == ':') {
unsigned length = 1;
while(p[length] && p[length] != '\n') length++;
data = {substr(p, 1, length - 1), "\n"};
_value = {substr(p, 1, length - 1), "\n"};
p += length;
}
}
@@ -64,41 +69,40 @@ protected:
while(*p == ' ') p++; //skip excess spaces
if(*(p + 0) == '/' && *(p + 1) == '/') break; //skip comments
Node node;
node.attribute = true;
SharedNode node(new ManagedNode);
unsigned length = 0;
while(valid(p[length])) length++;
if(length == 0) throw "Invalid attribute name";
node.name = substr(p, 0, length);
node.parseData(p += length);
node.data.rtrim("\n");
children.append(node);
node->_name = substr(p, 0, length);
node->parseData(p += length);
node->_value.rtrim("\n");
_children.append(node);
}
}
//read a node and all of its child nodes
void parseNode(const lstring& text, unsigned& y) {
const char* p = text[y++];
level = parseDepth(p);
_metadata = parseDepth(p);
parseName(p);
parseData(p);
parseAttributes(p);
while(y < text.size()) {
unsigned depth = readDepth(text[y]);
if(depth <= level) break;
if(depth <= _metadata) break;
if(text[y][depth] == ':') {
data.append(substr(text[y++], depth + 1), "\n");
_value.append(substr(text[y++], depth + 1), "\n");
continue;
}
Node node;
node.parseNode(text, y);
children.append(node);
SharedNode node(new ManagedNode);
node->parseNode(text, y);
_children.append(node);
}
data.rtrim("\n");
_value.rtrim("\n");
}
//read top-level nodes
@@ -120,36 +124,58 @@ protected:
unsigned y = 0;
while(y < text.size()) {
Node node;
node.parseNode(text, y);
if(node.level > 0) throw "Root nodes cannot be indented";
children.append(node);
SharedNode node(new ManagedNode);
node->parseNode(text, y);
if(node->_metadata > 0) throw "Root nodes cannot be indented";
_children.append(node);
}
}
friend class Document;
friend auto unserialize(const string&) -> Markup::Node;
};
struct Document : Node {
string error;
inline auto unserialize(const string& markup) -> Markup::Node {
SharedNode node(new ManagedNode);
try {
node->parse(markup);
} catch(const char* error) {
node.reset();
}
return (Markup::SharedNode&)node;
}
bool load(const string& document) {
name = "", data = "";
try {
parse(document);
} catch(const char* error) {
this->error = error;
children.reset();
return false;
inline auto serialize(const Markup::Node& node, unsigned depth = 0) -> string {
if(!node.name()) {
string result;
for(auto leaf : node) {
result.append(serialize(leaf, depth));
}
return true;
return result;
}
Document(const string& document = "") {
load(document);
string padding;
padding.resize(depth * 2);
for(auto& byte : padding) byte = ' ';
lstring lines;
if(auto value = node.value()) lines = value.split("\n");
string result;
result.append(padding);
result.append(node.name());
if(lines.size() == 1) result.append(":", lines[0]);
result.append("\n");
if(lines.size() > 1) {
padding.append(" ");
for(auto& line : lines) {
result.append(padding, ":", line, "\n");
}
}
};
for(auto leaf : node) {
result.append(serialize(leaf, depth + 1));
}
return result;
}
}
}