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:
Jesse Beder
2009-02-07 07:57:13 +00:00
parent f9c0725684
commit 9d0e0c6a48
13 changed files with 85 additions and 63 deletions

View File

@@ -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:
};

View File

@@ -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:

View File

@@ -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;

View File

@@ -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++) {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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()

View File

@@ -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);

View File

@@ -1 +1,2 @@
- test
---
...

View File

@@ -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