mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Fixed several bugs from the new file i/o setup.
In particular: 1. Windows CR/LF weren't read properly (issue #11) 2. Scanning wasn't reading EOF properly 3. Documents may be empty (this was old, I think) Also fixed some VS2008 warnings on /W4.
This commit is contained in:
@@ -25,31 +25,31 @@ namespace YAML
|
||||
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
|
||||
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 *, 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 *, ltnode>::const_iterator& it) const { return false; }
|
||||
virtual Node *GetNode(unsigned i) const { return 0; }
|
||||
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
|
||||
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
|
||||
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const { return false; }
|
||||
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
|
||||
virtual Node *GetNode(unsigned) const { return 0; }
|
||||
virtual unsigned GetSize() const { return 0; }
|
||||
virtual bool IsScalar() const { return false; }
|
||||
virtual bool IsMap() const { return false; }
|
||||
virtual bool IsSequence() const { return false; }
|
||||
|
||||
// extraction
|
||||
virtual bool Read(std::string& s) const { return false; }
|
||||
virtual bool Read(int& i) const { return false; }
|
||||
virtual bool Read(unsigned& u) const { return false; }
|
||||
virtual bool Read(long& l) const { return false; }
|
||||
virtual bool Read(float& f) const { return false; }
|
||||
virtual bool Read(double& d) const { return false; }
|
||||
virtual bool Read(char& c) const { return false; }
|
||||
virtual bool Read(bool& b) const { return false; }
|
||||
virtual bool Read(std::string&) const { return false; }
|
||||
virtual bool Read(int&) const { return false; }
|
||||
virtual bool Read(unsigned&) const { return false; }
|
||||
virtual bool Read(long&) const { return false; }
|
||||
virtual bool Read(float&) const { return false; }
|
||||
virtual bool Read(double&) const { return false; }
|
||||
virtual bool Read(char&) const { return false; }
|
||||
virtual bool Read(bool&) const { return false; }
|
||||
|
||||
// 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; }
|
||||
virtual int Compare(Content *) { return 0; }
|
||||
virtual int Compare(Scalar *) { return 0; }
|
||||
virtual int Compare(Sequence *) { return 0; }
|
||||
virtual int Compare(Map *) { return 0; }
|
||||
|
||||
protected:
|
||||
};
|
||||
|
@@ -23,8 +23,8 @@ namespace YAML
|
||||
|
||||
// ordering
|
||||
virtual int Compare(Content *pContent);
|
||||
virtual int Compare(Scalar *pScalar) { return 1; }
|
||||
virtual int Compare(Sequence *pSeq) { return 1; }
|
||||
virtual int Compare(Scalar *) { return 1; }
|
||||
virtual int Compare(Sequence *) { return 1; }
|
||||
virtual int Compare(Map *pMap);
|
||||
|
||||
private:
|
||||
|
@@ -37,6 +37,10 @@ namespace YAML
|
||||
{
|
||||
Clear();
|
||||
|
||||
// an empty node *is* a possibility
|
||||
if(pScanner->empty())
|
||||
return;
|
||||
|
||||
// save location
|
||||
m_line = pScanner->peek().line;
|
||||
m_column = pScanner->peek().column;
|
||||
|
@@ -90,7 +90,7 @@ namespace YAML
|
||||
return Match(str) >= 0;
|
||||
}
|
||||
|
||||
bool RegEx::Matches(const char *buffer) const
|
||||
bool RegEx::Matches(const Buffer& buffer) const
|
||||
{
|
||||
return Match(buffer) >= 0;
|
||||
}
|
||||
@@ -109,7 +109,7 @@ namespace YAML
|
||||
int RegEx::Match(const std::string& str) const
|
||||
{
|
||||
if(!m_pOp)
|
||||
return 0;
|
||||
return str.empty() ? 0 : -1; // the empty regex only is successful on the empty string
|
||||
|
||||
return m_pOp->Match(str, *this);
|
||||
}
|
||||
@@ -121,15 +121,12 @@ namespace YAML
|
||||
}
|
||||
|
||||
// Match
|
||||
// . The stream version does the same thing as the string version;
|
||||
// REMEMBER that we only match from the start of the stream!
|
||||
// . Note: the istream is not a const reference, but we guarantee
|
||||
// that the pointer will be in the same spot, and we'll clear its
|
||||
// flags before we end.
|
||||
int RegEx::Match(const char *buffer) const
|
||||
// . The buffer version does the same thing as the string version;
|
||||
// REMEMBER that we only match from the start of the buffer!
|
||||
int RegEx::Match(const Buffer& buffer) const
|
||||
{
|
||||
if(!m_pOp)
|
||||
return -1;
|
||||
return !buffer ? 0 : -1; // see above
|
||||
|
||||
return m_pOp->Match(buffer, *this);
|
||||
}
|
||||
@@ -177,9 +174,9 @@ namespace YAML
|
||||
}
|
||||
|
||||
|
||||
int RegEx::MatchOperator::Match(const char *buffer, const RegEx& regex) const
|
||||
int RegEx::MatchOperator::Match(const Buffer& buffer, const RegEx& regex) const
|
||||
{
|
||||
if(buffer[0] != regex.m_a)
|
||||
if(!buffer || buffer[0] != regex.m_a)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
@@ -192,9 +189,9 @@ namespace YAML
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RegEx::RangeOperator::Match(const char *buffer, const RegEx& regex) const
|
||||
int RegEx::RangeOperator::Match(const Buffer& buffer, const RegEx& regex) const
|
||||
{
|
||||
if(regex.m_a > buffer[0] || regex.m_z < buffer[0])
|
||||
if(!buffer || regex.m_a > buffer[0] || regex.m_z < buffer[0])
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
@@ -210,7 +207,7 @@ namespace YAML
|
||||
return -1;
|
||||
}
|
||||
|
||||
int RegEx::OrOperator::Match(const char *buffer, const RegEx& regex) const
|
||||
int RegEx::OrOperator::Match(const Buffer& buffer, const RegEx& regex) const
|
||||
{
|
||||
for(unsigned i=0;i<regex.m_params.size();i++) {
|
||||
int n = regex.m_params[i].Match(buffer);
|
||||
@@ -237,7 +234,7 @@ namespace YAML
|
||||
return first;
|
||||
}
|
||||
|
||||
int RegEx::AndOperator::Match(const char *buffer, const RegEx& regex) const
|
||||
int RegEx::AndOperator::Match(const Buffer& buffer, const RegEx& regex) const
|
||||
{
|
||||
int first = -1;
|
||||
for(unsigned i=0;i<regex.m_params.size();i++) {
|
||||
@@ -260,7 +257,7 @@ namespace YAML
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RegEx::NotOperator::Match(const char *buffer, const RegEx& regex) const
|
||||
int RegEx::NotOperator::Match(const Buffer& buffer, const RegEx& regex) const
|
||||
{
|
||||
if(regex.m_params.empty())
|
||||
return -1;
|
||||
@@ -282,7 +279,7 @@ namespace YAML
|
||||
return offset;
|
||||
}
|
||||
|
||||
int RegEx::SeqOperator::Match(const char *buffer, const RegEx& regex) const
|
||||
int RegEx::SeqOperator::Match(const Buffer& buffer, const RegEx& regex) const
|
||||
{
|
||||
int offset = 0;
|
||||
for(unsigned i=0;i<regex.m_params.size();i++) {
|
||||
|
22
src/regex.h
22
src/regex.h
@@ -5,7 +5,8 @@
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
struct Stream;
|
||||
class Stream;
|
||||
struct Buffer;
|
||||
|
||||
enum REGEX_OP { REGEX_EMPTY, REGEX_MATCH, REGEX_RANGE, REGEX_OR, REGEX_AND, REGEX_NOT, REGEX_SEQ };
|
||||
|
||||
@@ -15,40 +16,41 @@ namespace YAML
|
||||
class RegEx
|
||||
{
|
||||
private:
|
||||
// the operators
|
||||
struct Operator {
|
||||
virtual ~Operator() {}
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const = 0;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const = 0;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const = 0;
|
||||
};
|
||||
|
||||
struct MatchOperator: public Operator {
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const;
|
||||
};
|
||||
|
||||
struct RangeOperator: public Operator {
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const;
|
||||
};
|
||||
|
||||
struct OrOperator: public Operator {
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const;
|
||||
};
|
||||
|
||||
struct AndOperator: public Operator {
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const;
|
||||
};
|
||||
|
||||
struct NotOperator: public Operator {
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const;
|
||||
};
|
||||
|
||||
struct SeqOperator: public Operator {
|
||||
virtual int Match(const std::string& str, const RegEx& regex) const;
|
||||
virtual int Match(const char *buffer, const RegEx& regex) const;
|
||||
virtual int Match(const Buffer& buffer, const RegEx& regex) const;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -65,10 +67,10 @@ namespace YAML
|
||||
|
||||
bool Matches(char ch) const;
|
||||
bool Matches(const std::string& str) const;
|
||||
bool Matches(const char *buffer) const;
|
||||
bool Matches(const Buffer& buffer) const;
|
||||
bool Matches(const Stream& in) const;
|
||||
int Match(const std::string& str) const;
|
||||
int Match(const char *buffer) const;
|
||||
int Match(const Buffer& buffer) const;
|
||||
int Match(const Stream& in) const;
|
||||
|
||||
friend RegEx operator ! (const RegEx& ex);
|
||||
|
@@ -29,8 +29,8 @@ namespace YAML
|
||||
// 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; }
|
||||
virtual int Compare(Sequence *) { return -1; }
|
||||
virtual int Compare(Map *) { return -1; }
|
||||
|
||||
protected:
|
||||
std::string m_data;
|
||||
|
@@ -28,7 +28,7 @@ namespace YAML
|
||||
// ********************************
|
||||
// Phase #1: scan until line ending
|
||||
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
|
||||
if(INPUT.peek() == EOF)
|
||||
if(!INPUT)
|
||||
break;
|
||||
|
||||
// document indicator?
|
||||
@@ -60,7 +60,7 @@ namespace YAML
|
||||
}
|
||||
|
||||
// eof? if we're looking to eat something, then we throw
|
||||
if(INPUT.peek() == EOF) {
|
||||
if(!INPUT) {
|
||||
if(params.eatEnd)
|
||||
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::EOF_IN_SCALAR);
|
||||
break;
|
||||
|
@@ -29,7 +29,7 @@ namespace YAML
|
||||
INPUT.eat(1);
|
||||
|
||||
// read name
|
||||
while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
name += INPUT.get();
|
||||
|
||||
// read parameters
|
||||
@@ -39,12 +39,12 @@ namespace YAML
|
||||
INPUT.eat(1);
|
||||
|
||||
// break on newline or comment
|
||||
if(INPUT.peek() == EOF || Exp::Break.Matches(INPUT) || Exp::Comment.Matches(INPUT))
|
||||
if(!INPUT || Exp::Break.Matches(INPUT) || Exp::Comment.Matches(INPUT))
|
||||
break;
|
||||
|
||||
// now read parameter
|
||||
std::string param;
|
||||
while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
param += INPUT.get();
|
||||
|
||||
params.push_back(param);
|
||||
@@ -221,7 +221,7 @@ namespace YAML
|
||||
throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
|
||||
|
||||
// and needs to end correctly
|
||||
if(INPUT.peek() != EOF && !Exp::AnchorEnd.Matches(INPUT))
|
||||
if(INPUT && !Exp::AnchorEnd.Matches(INPUT))
|
||||
throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
|
||||
|
||||
// and we're done
|
||||
@@ -245,7 +245,7 @@ namespace YAML
|
||||
handle += INPUT.get();
|
||||
|
||||
// read the handle
|
||||
while(INPUT.peek() != EOF && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
while(INPUT && INPUT.peek() != Keys::Tag && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
handle += INPUT.get();
|
||||
|
||||
// is there a suffix?
|
||||
@@ -254,7 +254,7 @@ namespace YAML
|
||||
handle += INPUT.get();
|
||||
|
||||
// then read it
|
||||
while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
|
||||
suffix += INPUT.get();
|
||||
} else {
|
||||
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix
|
||||
|
@@ -26,9 +26,9 @@ namespace YAML
|
||||
|
||||
// ordering
|
||||
virtual int Compare(Content *pContent);
|
||||
virtual int Compare(Scalar *pScalar) { return 1; }
|
||||
virtual int Compare(Scalar *) { return 1; }
|
||||
virtual int Compare(Sequence *pSeq);
|
||||
virtual int Compare(Map *pMap) { return -1; }
|
||||
virtual int Compare(Map *) { return -1; }
|
||||
|
||||
private:
|
||||
void ParseBlock(Scanner *pScanner, const ParserState& state);
|
||||
|
@@ -6,13 +6,18 @@ namespace YAML
|
||||
{
|
||||
Stream::Stream(std::istream& input): buffer(0), pos(0), line(0), column(0), size(0)
|
||||
{
|
||||
if(!input)
|
||||
return;
|
||||
|
||||
std::streambuf *pBuf = input.rdbuf();
|
||||
|
||||
// store entire file in buffer
|
||||
size = pBuf->pubseekoff(0, std::ios::end, std::ios::in);
|
||||
pBuf->pubseekpos(0, std::ios::in);
|
||||
buffer = new char[size];
|
||||
pBuf->sgetn(buffer, size);
|
||||
size = pBuf->sgetn(buffer, size); // Note: when reading a Windows CR/LF file,
|
||||
// pubseekoff() counts CR/LF as two characters,
|
||||
// setgn() reads CR/LF as a single LF character!
|
||||
}
|
||||
|
||||
Stream::~Stream()
|
||||
|
15
src/stream.h
15
src/stream.h
@@ -5,6 +5,19 @@
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
// a simple buffer wrapper that knows how big it is
|
||||
struct Buffer {
|
||||
Buffer(char *b, int s): buffer(b), size(s) {}
|
||||
|
||||
operator bool() const { return size > 0; }
|
||||
bool operator !() const { return !static_cast <bool> (*this); }
|
||||
char operator [] (int i) const { return buffer[i]; }
|
||||
const Buffer operator + (int offset) const { return Buffer(buffer + offset, size - offset); }
|
||||
|
||||
char *buffer;
|
||||
int size;
|
||||
};
|
||||
|
||||
class Stream
|
||||
{
|
||||
public:
|
||||
@@ -14,7 +27,7 @@ namespace YAML
|
||||
operator bool() const;
|
||||
bool operator !() const { return !static_cast <bool>(*this); }
|
||||
|
||||
const char *current() const { return buffer + pos; }
|
||||
const Buffer current() const { return Buffer(buffer + pos, size - pos); }
|
||||
char peek();
|
||||
char get();
|
||||
std::string get(int n);
|
||||
|
@@ -1 +1,2 @@
|
||||
- test
|
||||
---
|
||||
...
|
@@ -47,7 +47,7 @@
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarningLevel="4"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
@@ -111,7 +111,7 @@
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
WarningLevel="4"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
|
Reference in New Issue
Block a user