mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
Added a (recursive) ordering, so we have a canonical output that we can compare.
This commit is contained in:
parent
2a0ddc8cb2
commit
115cf601e9
15 changed files with 217 additions and 51 deletions
14
content.h
14
content.h
|
@ -5,12 +5,16 @@
|
|||
#include <map>
|
||||
#include "parserstate.h"
|
||||
#include "exceptions.h"
|
||||
#include "ltnode.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
class Scanner;
|
||||
class Parser;
|
||||
class Node;
|
||||
class Scalar;
|
||||
class Sequence;
|
||||
class Map;
|
||||
|
||||
class Content
|
||||
{
|
||||
|
@ -22,9 +26,9 @@ namespace YAML
|
|||
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) = 0;
|
||||
|
||||
virtual bool GetBegin(std::vector <Node *>::const_iterator& it) const { return false; }
|
||||
virtual bool GetBegin(std::map <Node *, Node *>::const_iterator& it) const { return false; }
|
||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const { return false; }
|
||||
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const { return false; }
|
||||
virtual bool GetEnd(std::map <Node *, Node *>::const_iterator& it) const { return false; }
|
||||
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const { return false; }
|
||||
virtual Node *GetNode(unsigned i) const { return 0; }
|
||||
virtual unsigned GetSize() const { return 0; }
|
||||
|
||||
|
@ -37,6 +41,12 @@ namespace YAML
|
|||
virtual void Read(double& d) { throw InvalidScalar(); }
|
||||
virtual void Read(char& c) { throw InvalidScalar(); }
|
||||
|
||||
// ordering
|
||||
virtual int Compare(Content *pContent) { return 0; }
|
||||
virtual int Compare(Scalar *pScalar) { return 0; }
|
||||
virtual int Compare(Sequence *pSeq) { return 0; }
|
||||
virtual int Compare(Map *pMap) { return 0; }
|
||||
|
||||
protected:
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace YAML
|
|||
{
|
||||
}
|
||||
|
||||
Node::Iterator::Iterator(std::map <Node *, Node *>::const_iterator it): mapIter(it), type(IT_MAP)
|
||||
Node::Iterator::Iterator(std::map <Node *, Node *, ltnode>::const_iterator it): mapIter(it), type(IT_MAP)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
10
ltnode.h
Normal file
10
ltnode.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
class Node;
|
||||
|
||||
struct ltnode {
|
||||
bool operator()(const Node *pNode1, const Node *pNode2) const;
|
||||
};
|
||||
}
|
91
map.cpp
91
map.cpp
|
@ -24,13 +24,13 @@ namespace YAML
|
|||
m_data.clear();
|
||||
}
|
||||
|
||||
bool Map::GetBegin(std::map <Node *, Node *>::const_iterator& it) const
|
||||
bool Map::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const
|
||||
{
|
||||
it = m_data.begin();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Map::GetEnd(std::map <Node *, Node *>::const_iterator& it) const
|
||||
bool Map::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const
|
||||
{
|
||||
it = m_data.end();
|
||||
return true;
|
||||
|
@ -68,15 +68,22 @@ namespace YAML
|
|||
|
||||
Node *pKey = new Node;
|
||||
Node *pValue = new Node;
|
||||
m_data[pKey] = pValue;
|
||||
|
||||
// grab key
|
||||
pKey->Parse(pScanner, state);
|
||||
try {
|
||||
// grab key
|
||||
pKey->Parse(pScanner, state);
|
||||
|
||||
// now grab value (optional)
|
||||
if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
|
||||
pScanner->PopNextToken();
|
||||
pValue->Parse(pScanner, state);
|
||||
// now grab value (optional)
|
||||
if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
|
||||
pScanner->PopNextToken();
|
||||
pValue->Parse(pScanner, state);
|
||||
}
|
||||
|
||||
m_data[pKey] = pValue;
|
||||
} catch(Exception& e) {
|
||||
delete pKey;
|
||||
delete pValue;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,23 +112,31 @@ namespace YAML
|
|||
|
||||
Node *pKey = new Node;
|
||||
Node *pValue = new Node;
|
||||
m_data[pKey] = pValue;
|
||||
|
||||
// grab key
|
||||
pKey->Parse(pScanner, state);
|
||||
try {
|
||||
// grab key
|
||||
pKey->Parse(pScanner, state);
|
||||
|
||||
// now grab value (optional)
|
||||
if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
|
||||
pScanner->PopNextToken();
|
||||
pValue->Parse(pScanner, state);
|
||||
// now grab value (optional)
|
||||
if(pScanner->PeekNextToken() && pScanner->PeekNextToken()->type == TT_VALUE) {
|
||||
pScanner->PopNextToken();
|
||||
pValue->Parse(pScanner, state);
|
||||
}
|
||||
|
||||
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
|
||||
pToken = pScanner->PeekNextToken();
|
||||
if(pToken->type == TT_FLOW_ENTRY)
|
||||
pScanner->EatNextToken();
|
||||
else if(pToken->type != TT_FLOW_MAP_END)
|
||||
throw MapEndNotFound();
|
||||
|
||||
m_data[pKey] = pValue;
|
||||
} catch(Exception& e) {
|
||||
// clean up and rethrow
|
||||
delete pKey;
|
||||
delete pValue;
|
||||
throw e;
|
||||
}
|
||||
|
||||
// now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
|
||||
pToken = pScanner->PeekNextToken();
|
||||
if(pToken->type == TT_FLOW_ENTRY)
|
||||
pScanner->EatNextToken();
|
||||
else if(pToken->type != TT_FLOW_MAP_END)
|
||||
throw MapEndNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,4 +163,34 @@ namespace YAML
|
|||
if(m_data.empty())
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
int Map::Compare(Content *pContent)
|
||||
{
|
||||
return -pContent->Compare(this);
|
||||
}
|
||||
|
||||
int Map::Compare(Map *pMap)
|
||||
{
|
||||
node_map::const_iterator it = m_data.begin(), jt = pMap->m_data.begin();
|
||||
while(1) {
|
||||
if(it == m_data.end()) {
|
||||
if(jt == pMap->m_data.end())
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
if(jt == pMap->m_data.end())
|
||||
return 1;
|
||||
|
||||
int cmp = it->first->Compare(*jt->first);
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
|
||||
cmp = it->second->Compare(*jt->second);
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
12
map.h
12
map.h
|
@ -14,17 +14,23 @@ namespace YAML
|
|||
virtual ~Map();
|
||||
|
||||
void Clear();
|
||||
virtual bool GetBegin(std::map <Node *, Node *>::const_iterator& it) const;
|
||||
virtual bool GetEnd(std::map <Node *, Node *>::const_iterator& it) const;
|
||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
|
||||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
||||
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
|
||||
|
||||
// ordering
|
||||
virtual int Compare(Content *pContent);
|
||||
virtual int Compare(Scalar *pScalar) { return 1; }
|
||||
virtual int Compare(Sequence *pSeq) { return 1; }
|
||||
virtual int Compare(Map *pMap);
|
||||
|
||||
private:
|
||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
||||
void ParseFlow(Scanner *pScanner, const ParserState& state);
|
||||
|
||||
protected:
|
||||
typedef std::map <Node *, Node *> node_map;
|
||||
typedef std::map <Node *, Node *, ltnode> node_map;
|
||||
node_map m_data;
|
||||
};
|
||||
}
|
||||
|
|
30
node.cpp
30
node.cpp
|
@ -9,6 +9,12 @@
|
|||
|
||||
namespace YAML
|
||||
{
|
||||
// the ordering!
|
||||
bool ltnode::operator ()(const Node *pNode1, const Node *pNode2) const
|
||||
{
|
||||
return *pNode1 < *pNode2;
|
||||
}
|
||||
|
||||
Node::Node(): m_pContent(0), m_alias(false)
|
||||
{
|
||||
}
|
||||
|
@ -150,7 +156,7 @@ namespace YAML
|
|||
if(m_pContent->GetBegin(seqIter))
|
||||
return Iterator(seqIter);
|
||||
|
||||
std::map <Node *, Node *>::const_iterator mapIter;
|
||||
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
|
||||
if(m_pContent->GetBegin(mapIter))
|
||||
return Iterator(mapIter);
|
||||
|
||||
|
@ -168,7 +174,7 @@ namespace YAML
|
|||
if(m_pContent->GetEnd(seqIter))
|
||||
return Iterator(seqIter);
|
||||
|
||||
std::map <Node *, Node *>::const_iterator mapIter;
|
||||
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
|
||||
if(m_pContent->GetEnd(mapIter))
|
||||
return Iterator(mapIter);
|
||||
|
||||
|
@ -274,4 +280,24 @@ namespace YAML
|
|||
node.Write(out, 0, false, false);
|
||||
return out;
|
||||
}
|
||||
|
||||
int Node::Compare(const Node& rhs) const
|
||||
{
|
||||
// Step 1: no content is the smallest
|
||||
if(!m_pContent) {
|
||||
if(rhs.m_pContent)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if(!rhs.m_pContent)
|
||||
return 1;
|
||||
|
||||
return m_pContent->Compare(rhs.m_pContent);
|
||||
}
|
||||
|
||||
bool operator < (const Node& n1, const Node& n2)
|
||||
{
|
||||
return n1.Compare(n2) < 0;
|
||||
}
|
||||
}
|
||||
|
|
9
node.h
9
node.h
|
@ -6,6 +6,7 @@
|
|||
#include <map>
|
||||
#include "parserstate.h"
|
||||
#include "exceptions.h"
|
||||
#include "ltnode.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
|
@ -20,7 +21,7 @@ namespace YAML
|
|||
public:
|
||||
Iterator();
|
||||
Iterator(std::vector <Node *>::const_iterator it);
|
||||
Iterator(std::map <Node *, Node *>::const_iterator it);
|
||||
Iterator(std::map <Node *, Node *, ltnode>::const_iterator it);
|
||||
~Iterator();
|
||||
|
||||
friend bool operator == (const Iterator& it, const Iterator& jt);
|
||||
|
@ -37,7 +38,7 @@ namespace YAML
|
|||
ITER_TYPE type;
|
||||
|
||||
std::vector <Node *>::const_iterator seqIter;
|
||||
std::map <Node *, Node *>::const_iterator mapIter;
|
||||
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -95,6 +96,10 @@ namespace YAML
|
|||
// insertion
|
||||
friend std::ostream& operator << (std::ostream& out, const Node& node);
|
||||
|
||||
// ordering
|
||||
int Compare(const Node& rhs) const;
|
||||
friend bool operator < (const Node& n1, const Node& n2);
|
||||
|
||||
private:
|
||||
void ParseHeader(Scanner *pScanner, const ParserState& state);
|
||||
void ParseTag(Scanner *pScanner, const ParserState& state);
|
||||
|
|
15
scalar.cpp
15
scalar.cpp
|
@ -88,4 +88,19 @@ namespace YAML
|
|||
if(!data)
|
||||
throw InvalidScalar();
|
||||
}
|
||||
|
||||
int Scalar::Compare(Content *pContent)
|
||||
{
|
||||
return -pContent->Compare(this);
|
||||
}
|
||||
|
||||
int Scalar::Compare(Scalar *pScalar)
|
||||
{
|
||||
if(m_data < pScalar->m_data)
|
||||
return -1;
|
||||
else if(m_data > pScalar->m_data)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
6
scalar.h
6
scalar.h
|
@ -23,6 +23,12 @@ namespace YAML
|
|||
virtual void Read(double& d);
|
||||
virtual void Read(char& c);
|
||||
|
||||
// ordering
|
||||
virtual int Compare(Content *pContent);
|
||||
virtual int Compare(Scalar *pScalar);
|
||||
virtual int Compare(Sequence *pSeq) { return -1; }
|
||||
virtual int Compare(Map *pMap) { return -1; }
|
||||
|
||||
protected:
|
||||
std::string m_data;
|
||||
};
|
||||
|
|
22
sequence.cpp
22
sequence.cpp
|
@ -151,4 +151,26 @@ namespace YAML
|
|||
if(m_data.empty())
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
int Sequence::Compare(Content *pContent)
|
||||
{
|
||||
return -pContent->Compare(this);
|
||||
}
|
||||
|
||||
int Sequence::Compare(Sequence *pSeq)
|
||||
{
|
||||
unsigned n = m_data.size(), m = pSeq->m_data.size();
|
||||
if(n < m)
|
||||
return -1;
|
||||
else if(n > m)
|
||||
return 1;
|
||||
|
||||
for(unsigned i=0;i<n;i++) {
|
||||
int cmp = m_data[i]->Compare(*pSeq->m_data[i]);
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,12 @@ namespace YAML
|
|||
virtual void Parse(Scanner *pScanner, const ParserState& state);
|
||||
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
|
||||
|
||||
// ordering
|
||||
virtual int Compare(Content *pContent);
|
||||
virtual int Compare(Scalar *pScalar) { return 1; }
|
||||
virtual int Compare(Sequence *pSeq);
|
||||
virtual int Compare(Map *pMap) { return -1; }
|
||||
|
||||
private:
|
||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
||||
void ParseImplicit(Scanner *pScanner, const ParserState& state);
|
||||
|
|
20
test.yaml
20
test.yaml
|
@ -1,17 +1,3 @@
|
|||
literal: |
|
||||
Here's a literal scalar.
|
||||
That's a newline.
|
||||
|
||||
Let's go...
|
||||
folded: >
|
||||
Here's a folded scalar that
|
||||
wraps over to a newline.
|
||||
|
||||
Let's go...
|
||||
regular: Here's a regular
|
||||
scalar that keeps
|
||||
on wrapping...
|
||||
|
||||
|
||||
Let's go!
|
||||
and last key: so it doesn't go bonkers
|
||||
abeginning: value
|
||||
zend: value
|
||||
middle: value
|
|
@ -15,6 +15,7 @@ namespace YAML
|
|||
std::vector <std::string> files;
|
||||
files.push_back("tests/simple.yaml");
|
||||
files.push_back("tests/mixed.yaml");
|
||||
files.push_back("tests/scalars.yaml");
|
||||
|
||||
bool passed = true;
|
||||
for(unsigned i=0;i<files.size();i++) {
|
||||
|
@ -63,7 +64,7 @@ namespace YAML
|
|||
if(firstTry == secondTry)
|
||||
return true;
|
||||
|
||||
std::ofstream fout("out.yaml");
|
||||
std::ofstream fout("tests/out.yaml");
|
||||
fout << "---\n";
|
||||
fout << firstTry << std::endl;
|
||||
fout << "---\n";
|
||||
|
|
24
tests/scalars.yaml
Normal file
24
tests/scalars.yaml
Normal file
|
@ -0,0 +1,24 @@
|
|||
- normal scalar, but
|
||||
over several lines
|
||||
- |
|
||||
literal scalar - so we can draw ASCII:
|
||||
|
||||
- -
|
||||
| - |
|
||||
------
|
||||
- >
|
||||
and a folded scalar... so we
|
||||
can just keep writing various
|
||||
things. And if we want to keep indentation:
|
||||
|
||||
we just indent a little
|
||||
see, this stays indented
|
||||
- >-
|
||||
Here's a folded scalar
|
||||
that gets chomped.
|
||||
- |-
|
||||
And here's a literal scalar
|
||||
that gets chomped.
|
||||
- >2
|
||||
Here's a folded scalar
|
||||
that starts with some indentation.
|
|
@ -302,6 +302,10 @@
|
|||
RelativePath=".\content.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ltnode.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\map.h"
|
||||
>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue