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:
jbeder
2009-02-07 07:57:13 +00:00
parent 855d0d60df
commit 7297387015
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 Parse(Scanner *pScanner, const ParserState& state) = 0;
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) = 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::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const { return false; } virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
virtual bool GetEnd(std::vector <Node *>::const_iterator& it) const { return false; } virtual bool GetEnd(std::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const { return false; } virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }
virtual Node *GetNode(unsigned i) const { return 0; } virtual Node *GetNode(unsigned) const { return 0; }
virtual unsigned GetSize() const { return 0; } virtual unsigned GetSize() const { return 0; }
virtual bool IsScalar() const { return false; } virtual bool IsScalar() const { return false; }
virtual bool IsMap() const { return false; } virtual bool IsMap() const { return false; }
virtual bool IsSequence() const { return false; } virtual bool IsSequence() const { return false; }
// extraction // extraction
virtual bool Read(std::string& s) const { return false; } virtual bool Read(std::string&) const { return false; }
virtual bool Read(int& i) const { return false; } virtual bool Read(int&) const { return false; }
virtual bool Read(unsigned& u) const { return false; } virtual bool Read(unsigned&) const { return false; }
virtual bool Read(long& l) const { return false; } virtual bool Read(long&) const { return false; }
virtual bool Read(float& f) const { return false; } virtual bool Read(float&) const { return false; }
virtual bool Read(double& d) const { return false; } virtual bool Read(double&) const { return false; }
virtual bool Read(char& c) const { return false; } virtual bool Read(char&) const { return false; }
virtual bool Read(bool& b) const { return false; } virtual bool Read(bool&) const { return false; }
// ordering // ordering
virtual int Compare(Content *pContent) { return 0; } virtual int Compare(Content *) { return 0; }
virtual int Compare(Scalar *pScalar) { return 0; } virtual int Compare(Scalar *) { return 0; }
virtual int Compare(Sequence *pSeq) { return 0; } virtual int Compare(Sequence *) { return 0; }
virtual int Compare(Map *pMap) { return 0; } virtual int Compare(Map *) { return 0; }
protected: protected:
}; };

View File

@@ -23,8 +23,8 @@ namespace YAML
// ordering // ordering
virtual int Compare(Content *pContent); virtual int Compare(Content *pContent);
virtual int Compare(Scalar *pScalar) { return 1; } virtual int Compare(Scalar *) { return 1; }
virtual int Compare(Sequence *pSeq) { return 1; } virtual int Compare(Sequence *) { return 1; }
virtual int Compare(Map *pMap); virtual int Compare(Map *pMap);
private: private:

View File

@@ -37,6 +37,10 @@ namespace YAML
{ {
Clear(); Clear();
// an empty node *is* a possibility
if(pScanner->empty())
return;
// save location // save location
m_line = pScanner->peek().line; m_line = pScanner->peek().line;
m_column = pScanner->peek().column; m_column = pScanner->peek().column;

View File

@@ -90,7 +90,7 @@ namespace YAML
return Match(str) >= 0; return Match(str) >= 0;
} }
bool RegEx::Matches(const char *buffer) const bool RegEx::Matches(const Buffer& buffer) const
{ {
return Match(buffer) >= 0; return Match(buffer) >= 0;
} }
@@ -109,7 +109,7 @@ namespace YAML
int RegEx::Match(const std::string& str) const int RegEx::Match(const std::string& str) const
{ {
if(!m_pOp) 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); return m_pOp->Match(str, *this);
} }
@@ -121,15 +121,12 @@ namespace YAML
} }
// Match // Match
// . The stream version does the same thing as the string version; // . The buffer version does the same thing as the string version;
// REMEMBER that we only match from the start of the stream! // REMEMBER that we only match from the start of the buffer!
// . Note: the istream is not a const reference, but we guarantee int RegEx::Match(const Buffer& buffer) const
// 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
{ {
if(!m_pOp) if(!m_pOp)
return -1; return !buffer ? 0 : -1; // see above
return m_pOp->Match(buffer, *this); 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;
return 1; return 1;
} }
@@ -192,9 +189,9 @@ namespace YAML
return 1; 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;
return 1; return 1;
} }
@@ -210,7 +207,7 @@ namespace YAML
return -1; 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++) { for(unsigned i=0;i<regex.m_params.size();i++) {
int n = regex.m_params[i].Match(buffer); int n = regex.m_params[i].Match(buffer);
@@ -237,7 +234,7 @@ namespace YAML
return first; 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; int first = -1;
for(unsigned i=0;i<regex.m_params.size();i++) { for(unsigned i=0;i<regex.m_params.size();i++) {
@@ -260,7 +257,7 @@ namespace YAML
return 1; 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()) if(regex.m_params.empty())
return -1; return -1;
@@ -282,7 +279,7 @@ namespace YAML
return offset; 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; int offset = 0;
for(unsigned i=0;i<regex.m_params.size();i++) { for(unsigned i=0;i<regex.m_params.size();i++) {

View File

@@ -5,7 +5,8 @@
namespace YAML 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 }; 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 class RegEx
{ {
private: private:
// the operators
struct Operator { struct Operator {
virtual ~Operator() {} virtual ~Operator() {}
virtual int Match(const std::string& str, const RegEx& regex) const = 0; 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 { struct MatchOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; 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 { struct RangeOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; 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 { struct OrOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; 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 { struct AndOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; 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 { struct NotOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; 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 { struct SeqOperator: public Operator {
virtual int Match(const std::string& str, const RegEx& regex) const; 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: public:
@@ -65,10 +67,10 @@ namespace YAML
bool Matches(char ch) const; bool Matches(char ch) const;
bool Matches(const std::string& str) 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; bool Matches(const Stream& in) const;
int Match(const std::string& str) 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; int Match(const Stream& in) const;
friend RegEx operator ! (const RegEx& ex); friend RegEx operator ! (const RegEx& ex);

View File

@@ -29,8 +29,8 @@ namespace YAML
// ordering // ordering
virtual int Compare(Content *pContent); virtual int Compare(Content *pContent);
virtual int Compare(Scalar *pScalar); virtual int Compare(Scalar *pScalar);
virtual int Compare(Sequence *pSeq) { return -1; } virtual int Compare(Sequence *) { return -1; }
virtual int Compare(Map *pMap) { return -1; } virtual int Compare(Map *) { return -1; }
protected: protected:
std::string m_data; std::string m_data;

View File

@@ -28,7 +28,7 @@ namespace YAML
// ******************************** // ********************************
// Phase #1: scan until line ending // Phase #1: scan until line ending
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) { while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
if(INPUT.peek() == EOF) if(!INPUT)
break; break;
// document indicator? // document indicator?
@@ -60,7 +60,7 @@ namespace YAML
} }
// eof? if we're looking to eat something, then we throw // eof? if we're looking to eat something, then we throw
if(INPUT.peek() == EOF) { if(!INPUT) {
if(params.eatEnd) if(params.eatEnd)
throw ParserException(INPUT.line, INPUT.column, ErrorMsg::EOF_IN_SCALAR); throw ParserException(INPUT.line, INPUT.column, ErrorMsg::EOF_IN_SCALAR);
break; break;

View File

@@ -29,7 +29,7 @@ namespace YAML
INPUT.eat(1); INPUT.eat(1);
// read name // read name
while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT)) while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
name += INPUT.get(); name += INPUT.get();
// read parameters // read parameters
@@ -39,12 +39,12 @@ namespace YAML
INPUT.eat(1); INPUT.eat(1);
// break on newline or comment // 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; break;
// now read parameter // now read parameter
std::string param; std::string param;
while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT)) while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
param += INPUT.get(); param += INPUT.get();
params.push_back(param); 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); throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::ALIAS_NOT_FOUND : ErrorMsg::ANCHOR_NOT_FOUND);
// and needs to end correctly // 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); throw ParserException(INPUT.line, INPUT.column, alias ? ErrorMsg::CHAR_IN_ALIAS : ErrorMsg::CHAR_IN_ANCHOR);
// and we're done // and we're done
@@ -245,7 +245,7 @@ namespace YAML
handle += INPUT.get(); handle += INPUT.get();
// read the handle // 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(); handle += INPUT.get();
// is there a suffix? // is there a suffix?
@@ -254,7 +254,7 @@ namespace YAML
handle += INPUT.get(); handle += INPUT.get();
// then read it // then read it
while(INPUT.peek() != EOF && !Exp::BlankOrBreak.Matches(INPUT)) while(INPUT && !Exp::BlankOrBreak.Matches(INPUT))
suffix += INPUT.get(); suffix += INPUT.get();
} else { } else {
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix // 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 // ordering
virtual int Compare(Content *pContent); 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(Sequence *pSeq);
virtual int Compare(Map *pMap) { return -1; } virtual int Compare(Map *) { return -1; }
private: private:
void ParseBlock(Scanner *pScanner, const ParserState& state); 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) Stream::Stream(std::istream& input): buffer(0), pos(0), line(0), column(0), size(0)
{ {
if(!input)
return;
std::streambuf *pBuf = input.rdbuf(); std::streambuf *pBuf = input.rdbuf();
// store entire file in buffer // store entire file in buffer
size = pBuf->pubseekoff(0, std::ios::end, std::ios::in); size = pBuf->pubseekoff(0, std::ios::end, std::ios::in);
pBuf->pubseekpos(0, std::ios::in); pBuf->pubseekpos(0, std::ios::in);
buffer = new char[size]; 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() Stream::~Stream()

View File

@@ -5,6 +5,19 @@
namespace YAML 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 class Stream
{ {
public: public:
@@ -14,7 +27,7 @@ namespace YAML
operator bool() const; operator bool() const;
bool operator !() const { return !static_cast <bool>(*this); } 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 peek();
char get(); char get();
std::string get(int n); std::string get(int n);

View File

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

View File

@@ -47,7 +47,7 @@
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="3"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="4"
DebugInformationFormat="3" DebugInformationFormat="3"
/> />
<Tool <Tool
@@ -111,7 +111,7 @@
RuntimeLibrary="2" RuntimeLibrary="2"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="4"
DebugInformationFormat="3" DebugInformationFormat="3"
/> />
<Tool <Tool