"test/vscode:/vscode.git/clone" did not exist on "a7a7908dc5b025c0cc41c2a8f02de4f2b9b2205c"
Commit d45bb667 authored by Jesse Beder's avatar Jesse Beder
Browse files

Small changes in the iterator code.

Changed the public interface of Scanner to resemble an STL container.
parent cc87c83b
#pragma once #pragma once
// for memory leaks // for detecting memory leaks
#ifdef _DEBUG #ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC
......
...@@ -13,15 +13,16 @@ namespace YAML ...@@ -13,15 +13,16 @@ namespace YAML
Iterator(const Iterator& rhs); Iterator(const Iterator& rhs);
~Iterator(); ~Iterator();
friend bool operator == (const Iterator& it, const Iterator& jt);
friend bool operator != (const Iterator& it, const Iterator& jt);
Iterator& operator = (const Iterator& rhs); Iterator& operator = (const Iterator& rhs);
Iterator& operator ++ (); Iterator& operator ++ ();
Iterator operator ++ (int); Iterator operator ++ (int);
const Node& operator * (); const Node& operator * () const;
const Node *operator -> (); const Node *operator -> () const;
const Node& first(); const Node& first() const;
const Node& second(); const Node& second() const;
friend bool operator == (const Iterator& it, const Iterator& jt);
friend bool operator != (const Iterator& it, const Iterator& jt);
private: private:
IterPriv *m_pData; IterPriv *m_pData;
......
...@@ -30,6 +30,11 @@ namespace YAML ...@@ -30,6 +30,11 @@ namespace YAML
void HandleYamlDirective(Token *pToken); void HandleYamlDirective(Token *pToken);
void HandleTagDirective(Token *pToken); void HandleTagDirective(Token *pToken);
private:
// can't copy this
Parser(const Parser& rhs) {}
Parser& operator = (const Parser& rhs) { return *this; }
private: private:
Scanner *m_pScanner; Scanner *m_pScanner;
ParserState m_state; ParserState m_state;
......
...@@ -56,7 +56,7 @@ namespace YAML ...@@ -56,7 +56,7 @@ namespace YAML
return temp; return temp;
} }
const Node& Iterator::operator * () const Node& Iterator::operator * () const
{ {
if(m_pData->type == IterPriv::IT_SEQ) if(m_pData->type == IterPriv::IT_SEQ)
return **m_pData->seqIter; return **m_pData->seqIter;
...@@ -64,15 +64,15 @@ namespace YAML ...@@ -64,15 +64,15 @@ namespace YAML
throw BadDereference(); throw BadDereference();
} }
const Node *Iterator::operator -> () const Node *Iterator::operator -> () const
{ {
if(m_pData->type == IterPriv::IT_SEQ) if(m_pData->type == IterPriv::IT_SEQ)
return &**m_pData->seqIter; return *m_pData->seqIter;
throw BadDereference(); throw BadDereference();
} }
const Node& Iterator::first() const Node& Iterator::first() const
{ {
if(m_pData->type == IterPriv::IT_MAP) if(m_pData->type == IterPriv::IT_MAP)
return *m_pData->mapIter->first; return *m_pData->mapIter->first;
...@@ -80,7 +80,7 @@ namespace YAML ...@@ -80,7 +80,7 @@ namespace YAML
throw BadDereference(); throw BadDereference();
} }
const Node& Iterator::second() const Node& Iterator::second() const
{ {
if(m_pData->type == IterPriv::IT_MAP) if(m_pData->type == IterPriv::IT_MAP)
return *m_pData->mapIter->second; return *m_pData->mapIter->second;
......
#include "crt.h"
#include "iterpriv.h"
namespace YAML
{
IterPriv::IterPriv(): type(IT_NONE)
{
}
IterPriv::IterPriv(std::vector <Node *>::const_iterator it): seqIter(it), type(IT_SEQ)
{
}
IterPriv::IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): mapIter(it), type(IT_MAP)
{
}
}
...@@ -8,11 +8,13 @@ namespace YAML ...@@ -8,11 +8,13 @@ namespace YAML
{ {
class Node; class Node;
// IterPriv
// . The implementation for iterators - essentially a union of sequence and map iterators.
struct IterPriv struct IterPriv
{ {
IterPriv(); IterPriv(): type(IT_NONE) {}
IterPriv(std::vector <Node *>::const_iterator it); IterPriv(std::vector <Node *>::const_iterator it): seqIter(it), type(IT_SEQ) {}
IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it); IterPriv(std::map <Node *, Node *, ltnode>::const_iterator it): mapIter(it), type(IT_MAP) {}
enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP }; enum ITER_TYPE { IT_NONE, IT_SEQ, IT_MAP };
ITER_TYPE type; ITER_TYPE type;
......
...@@ -42,9 +42,7 @@ namespace YAML ...@@ -42,9 +42,7 @@ namespace YAML
Clear(); Clear();
// split based on start token // split based on start token
Token& token = pScanner->PeekToken(); switch(pScanner->peek().type) {
switch(token.type) {
case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break; case TT_BLOCK_MAP_START: ParseBlock(pScanner, state); break;
case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break; case TT_FLOW_MAP_START: ParseFlow(pScanner, state); break;
} }
...@@ -53,17 +51,17 @@ namespace YAML ...@@ -53,17 +51,17 @@ namespace YAML
void Map::ParseBlock(Scanner *pScanner, const ParserState& state) void Map::ParseBlock(Scanner *pScanner, const ParserState& state)
{ {
// eat start token // eat start token
pScanner->PopToken(); pScanner->pop();
while(1) { while(1) {
if(pScanner->IsEmpty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP); throw ParserException(-1, -1, ErrorMsg::END_OF_MAP);
Token token = pScanner->PeekToken(); Token token = pScanner->peek();
if(token.type != TT_KEY && token.type != TT_BLOCK_END) if(token.type != TT_KEY && token.type != TT_BLOCK_END)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP); throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP);
pScanner->PopToken(); pScanner->pop();
if(token.type == TT_BLOCK_END) if(token.type == TT_BLOCK_END)
break; break;
...@@ -75,8 +73,8 @@ namespace YAML ...@@ -75,8 +73,8 @@ namespace YAML
pKey->Parse(pScanner, state); pKey->Parse(pScanner, state);
// now grab value (optional) // now grab value (optional)
if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) { if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
pScanner->PopToken(); pScanner->pop();
pValue->Parse(pScanner, state); pValue->Parse(pScanner, state);
} }
...@@ -92,16 +90,16 @@ namespace YAML ...@@ -92,16 +90,16 @@ namespace YAML
void Map::ParseFlow(Scanner *pScanner, const ParserState& state) void Map::ParseFlow(Scanner *pScanner, const ParserState& state)
{ {
// eat start token // eat start token
pScanner->PopToken(); pScanner->pop();
while(1) { while(1) {
if(pScanner->IsEmpty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW); throw ParserException(-1, -1, ErrorMsg::END_OF_MAP_FLOW);
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
// first check for end // first check for end
if(token.type == TT_FLOW_MAP_END) { if(token.type == TT_FLOW_MAP_END) {
pScanner->PopToken(); pScanner->pop();
break; break;
} }
...@@ -109,7 +107,7 @@ namespace YAML ...@@ -109,7 +107,7 @@ namespace YAML
if(token.type != TT_KEY) if(token.type != TT_KEY)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW); throw ParserException(token.line, token.column, ErrorMsg::END_OF_MAP_FLOW);
pScanner->PopToken(); pScanner->pop();
Node *pKey = new Node; Node *pKey = new Node;
Node *pValue = new Node; Node *pValue = new Node;
...@@ -119,15 +117,15 @@ namespace YAML ...@@ -119,15 +117,15 @@ namespace YAML
pKey->Parse(pScanner, state); pKey->Parse(pScanner, state);
// now grab value (optional) // now grab value (optional)
if(!pScanner->IsEmpty() && pScanner->PeekToken().type == TT_VALUE) { if(!pScanner->empty() && pScanner->peek().type == TT_VALUE) {
pScanner->PopToken(); pScanner->pop();
pValue->Parse(pScanner, state); 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) // now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
Token& nextToken = pScanner->PeekToken(); Token& nextToken = pScanner->peek();
if(nextToken.type == TT_FLOW_ENTRY) if(nextToken.type == TT_FLOW_ENTRY)
pScanner->PopToken(); pScanner->pop();
else if(nextToken.type != TT_FLOW_MAP_END) else if(nextToken.type != TT_FLOW_MAP_END)
throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW); throw ParserException(nextToken.line, nextToken.column, ErrorMsg::END_OF_MAP_FLOW);
......
...@@ -44,7 +44,7 @@ namespace YAML ...@@ -44,7 +44,7 @@ namespace YAML
return; return;
// now split based on what kind of node we should be // now split based on what kind of node we should be
switch(pScanner->PeekToken().type) { switch(pScanner->peek().type) {
case TT_SCALAR: case TT_SCALAR:
m_pContent = new Scalar; m_pContent = new Scalar;
m_pContent->Parse(pScanner, state); m_pContent->Parse(pScanner, state);
...@@ -68,10 +68,10 @@ namespace YAML ...@@ -68,10 +68,10 @@ namespace YAML
void Node::ParseHeader(Scanner *pScanner, const ParserState& state) void Node::ParseHeader(Scanner *pScanner, const ParserState& state)
{ {
while(1) { while(1) {
if(pScanner->IsEmpty()) if(pScanner->empty())
return; return;
switch(pScanner->PeekToken().type) { switch(pScanner->peek().type) {
case TT_TAG: ParseTag(pScanner, state); break; case TT_TAG: ParseTag(pScanner, state); break;
case TT_ANCHOR: ParseAnchor(pScanner, state); break; case TT_ANCHOR: ParseAnchor(pScanner, state); break;
case TT_ALIAS: ParseAlias(pScanner, state); break; case TT_ALIAS: ParseAlias(pScanner, state); break;
...@@ -82,7 +82,7 @@ namespace YAML ...@@ -82,7 +82,7 @@ namespace YAML
void Node::ParseTag(Scanner *pScanner, const ParserState& state) void Node::ParseTag(Scanner *pScanner, const ParserState& state)
{ {
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
if(m_tag != "") if(m_tag != "")
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_TAGS); throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_TAGS);
...@@ -90,23 +90,23 @@ namespace YAML ...@@ -90,23 +90,23 @@ namespace YAML
for(unsigned i=0;i<token.params.size();i++) for(unsigned i=0;i<token.params.size();i++)
m_tag += token.params[i]; m_tag += token.params[i];
pScanner->PopToken(); pScanner->pop();
} }
void Node::ParseAnchor(Scanner *pScanner, const ParserState& state) void Node::ParseAnchor(Scanner *pScanner, const ParserState& state)
{ {
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
if(m_anchor != "") if(m_anchor != "")
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ANCHORS); throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ANCHORS);
m_anchor = token.value; m_anchor = token.value;
m_alias = false; m_alias = false;
pScanner->PopToken(); pScanner->pop();
} }
void Node::ParseAlias(Scanner *pScanner, const ParserState& state) void Node::ParseAlias(Scanner *pScanner, const ParserState& state)
{ {
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
if(m_anchor != "") if(m_anchor != "")
throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ALIASES); throw ParserException(token.line, token.column, ErrorMsg::MULTIPLE_ALIASES);
if(m_tag != "") if(m_tag != "")
...@@ -114,7 +114,7 @@ namespace YAML ...@@ -114,7 +114,7 @@ namespace YAML
m_anchor = token.value; m_anchor = token.value;
m_alias = true; m_alias = true;
pScanner->PopToken(); pScanner->pop();
} }
void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const
......
...@@ -19,7 +19,7 @@ namespace YAML ...@@ -19,7 +19,7 @@ namespace YAML
Parser::operator bool() const Parser::operator bool() const
{ {
return !m_pScanner->IsEmpty(); return !m_pScanner->empty();
} }
void Parser::Load(std::istream& in) void Parser::Load(std::istream& in)
...@@ -41,19 +41,19 @@ namespace YAML ...@@ -41,19 +41,19 @@ namespace YAML
ParseDirectives(); ParseDirectives();
// we better have some tokens in the queue // we better have some tokens in the queue
if(m_pScanner->IsEmpty()) if(m_pScanner->empty())
return; return;
// first eat doc start (optional) // first eat doc start (optional)
if(m_pScanner->PeekToken().type == TT_DOC_START) if(m_pScanner->peek().type == TT_DOC_START)
m_pScanner->PopToken(); m_pScanner->pop();
// now parse our root node // now parse our root node
document.Parse(m_pScanner, m_state); document.Parse(m_pScanner, m_state);
// and finally eat any doc ends we see // and finally eat any doc ends we see
while(!m_pScanner->IsEmpty() && m_pScanner->PeekToken().type == TT_DOC_END) while(!m_pScanner->empty() && m_pScanner->peek().type == TT_DOC_END)
m_pScanner->PopToken(); m_pScanner->pop();
} }
// ParseDirectives // ParseDirectives
...@@ -63,10 +63,10 @@ namespace YAML ...@@ -63,10 +63,10 @@ namespace YAML
bool readDirective = false; bool readDirective = false;
while(1) { while(1) {
if(m_pScanner->IsEmpty()) if(m_pScanner->empty())
break; break;
Token& token = m_pScanner->PeekToken(); Token& token = m_pScanner->peek();
if(token.type != TT_DIRECTIVE) if(token.type != TT_DIRECTIVE)
break; break;
...@@ -77,7 +77,7 @@ namespace YAML ...@@ -77,7 +77,7 @@ namespace YAML
readDirective = true; readDirective = true;
HandleDirective(&token); HandleDirective(&token);
m_pScanner->PopToken(); m_pScanner->pop();
} }
} }
...@@ -123,11 +123,11 @@ namespace YAML ...@@ -123,11 +123,11 @@ namespace YAML
void Parser::PrintTokens(std::ostream& out) void Parser::PrintTokens(std::ostream& out)
{ {
while(1) { while(1) {
if(m_pScanner->IsEmpty()) if(m_pScanner->empty())
break; break;
out << m_pScanner->PeekToken() << std::endl; out << m_pScanner->peek() << std::endl;
m_pScanner->PopToken(); m_pScanner->pop();
} }
} }
} }
...@@ -17,9 +17,9 @@ namespace YAML ...@@ -17,9 +17,9 @@ namespace YAML
void Scalar::Parse(Scanner *pScanner, const ParserState& state) void Scalar::Parse(Scanner *pScanner, const ParserState& state)
{ {
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
m_data = token.value; m_data = token.value;
pScanner->PopToken(); pScanner->pop();
} }
void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) void Scalar::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "token.h" #include "token.h"
#include "exceptions.h" #include "exceptions.h"
#include "exp.h" #include "exp.h"
#include <cassert>
namespace YAML namespace YAML
{ {
...@@ -15,34 +16,46 @@ namespace YAML ...@@ -15,34 +16,46 @@ namespace YAML
{ {
} }
// IsEmpty // empty
// . Returns true if there are no more tokens to be read // . Returns true if there are no more tokens to be read
bool Scanner::IsEmpty() bool Scanner::empty()
{ {
PeekToken(); // to ensure that there are tokens in the queue, if possible EnsureTokensInQueue();
return m_tokens.empty(); return m_tokens.empty();
} }
// PopToken // pop
// . Simply removes the next token on the queue. // . Simply removes the next token on the queue.
void Scanner::PopToken() void Scanner::pop()
{ {
PeekToken(); // to ensure that there are tokens in the queue EnsureTokensInQueue();
if(!m_tokens.empty()) if(!m_tokens.empty())
m_tokens.pop(); m_tokens.pop();
} }
// PeekToken // peek
// . Returns (but does not remove) the next token on the queue, and scans if only we need to. // . Returns (but does not remove) the next token on the queue.
Token& Scanner::PeekToken() Token& Scanner::peek()
{
EnsureTokensInQueue();
assert(!m_tokens.empty()); // should we be asserting here? I mean, we really just be checking
// if it's empty before peeking.
return m_tokens.front();
}
// EnsureTokensInQueue
// . Scan until there's a valid token at the front of the queue,
// or we're sure the queue is empty.
void Scanner::EnsureTokensInQueue()
{ {
while(1) { while(1) {
if(!m_tokens.empty()) { if(!m_tokens.empty()) {
Token& token = m_tokens.front(); Token& token = m_tokens.front();
// return this guy if it's valid // if this guy's valid, then we're done
if(token.status == TS_VALID) if(token.status == TS_VALID)
return token; return;
// here's where we clean up the impossible tokens // here's where we clean up the impossible tokens
if(token.status == TS_INVALID) { if(token.status == TS_INVALID) {
...@@ -55,13 +68,11 @@ namespace YAML ...@@ -55,13 +68,11 @@ namespace YAML
// no token? maybe we've actually finished // no token? maybe we've actually finished
if(m_endedStream) if(m_endedStream)
break; return;
// no? then scan... // no? then scan...
ScanNextToken(); ScanNextToken();
} }
// TODO: find something to return here, or assert (but can't do that! maybe split into two functions?)
} }
// ScanNextToken // ScanNextToken
......
...@@ -16,16 +16,18 @@ namespace YAML ...@@ -16,16 +16,18 @@ namespace YAML
Scanner(std::istream& in); Scanner(std::istream& in);
~Scanner(); ~Scanner();
bool IsEmpty(); // token queue management (hopefully this looks kinda stl-ish)
void PopToken(); bool empty();
Token& PeekToken(); void pop();
Token& peek();
private: private:
// scanning // scanning
void StartStream(); void EnsureTokensInQueue();
void EndStream();
void ScanNextToken(); void ScanNextToken();
void ScanToNextToken(); void ScanToNextToken();
void StartStream();
void EndStream();
Token *PushIndentTo(int column, bool sequence); Token *PushIndentTo(int column, bool sequence);
void PopIndentTo(int column); void PopIndentTo(int column);
......
...@@ -52,9 +52,7 @@ namespace YAML ...@@ -52,9 +52,7 @@ namespace YAML
Clear(); Clear();
// split based on start token // split based on start token
Token& token = pScanner->PeekToken(); switch(pScanner->peek().type) {
switch(token.type) {
case TT_BLOCK_SEQ_START: ParseBlock(pScanner, state); break; case TT_BLOCK_SEQ_START: ParseBlock(pScanner, state); break;
case TT_BLOCK_ENTRY: ParseImplicit(pScanner, state); break; case TT_BLOCK_ENTRY: ParseImplicit(pScanner, state); break;
case TT_FLOW_SEQ_START: ParseFlow(pScanner, state); break; case TT_FLOW_SEQ_START: ParseFlow(pScanner, state); break;
...@@ -64,17 +62,17 @@ namespace YAML ...@@ -64,17 +62,17 @@ namespace YAML
void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state) void Sequence::ParseBlock(Scanner *pScanner, const ParserState& state)
{ {
// eat start token // eat start token
pScanner->PopToken(); pScanner->pop();
while(1) { while(1) {
if(pScanner->IsEmpty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ); throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ);
Token token = pScanner->PeekToken(); Token token = pScanner->peek();
if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END) if(token.type != TT_BLOCK_ENTRY && token.type != TT_BLOCK_END)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ); throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ);
pScanner->PopToken(); pScanner->pop();
if(token.type == TT_BLOCK_END) if(token.type == TT_BLOCK_END)
break; break;
...@@ -88,15 +86,15 @@ namespace YAML ...@@ -88,15 +86,15 @@ namespace YAML
{ {
while(1) { while(1) {
// we're actually *allowed* to have no tokens at some point // we're actually *allowed* to have no tokens at some point
if(pScanner->IsEmpty()) if(pScanner->empty())
break; break;
// and we end at anything other than a block entry // and we end at anything other than a block entry
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
if(token.type != TT_BLOCK_ENTRY) if(token.type != TT_BLOCK_ENTRY)
break; break;
pScanner->PopToken(); pScanner->pop();
Node *pNode = new Node; Node *pNode = new Node;
m_data.push_back(pNode); m_data.push_back(pNode);
...@@ -107,15 +105,15 @@ namespace YAML ...@@ -107,15 +105,15 @@ namespace YAML
void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state) void Sequence::ParseFlow(Scanner *pScanner, const ParserState& state)
{ {
// eat start token // eat start token
pScanner->PopToken(); pScanner->pop();
while(1) { while(1) {
if(pScanner->IsEmpty()) if(pScanner->empty())
throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW); throw ParserException(-1, -1, ErrorMsg::END_OF_SEQ_FLOW);
// first check for end // first check for end
if(pScanner->PeekToken().type == TT_FLOW_SEQ_END) { if(pScanner->peek().type == TT_FLOW_SEQ_END) {
pScanner->PopToken(); pScanner->pop();
break; break;
} }
...@@ -125,9 +123,9 @@ namespace YAML ...@@ -125,9 +123,9 @@ namespace YAML
pNode->Parse(pScanner, state); pNode->Parse(pScanner, state);
// now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node) // now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
Token& token = pScanner->PeekToken(); Token& token = pScanner->peek();
if(token.type == TT_FLOW_ENTRY) if(token.type == TT_FLOW_ENTRY)
pScanner->PopToken(); pScanner->pop();
else if(token.type != TT_FLOW_SEQ_END) else if(token.type != TT_FLOW_SEQ_END)
throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW); throw ParserException(token.line, token.column, ErrorMsg::END_OF_SEQ_FLOW);
} }
......
...@@ -175,10 +175,6 @@ ...@@ -175,10 +175,6 @@
RelativePath=".\src\iterator.cpp" RelativePath=".\src\iterator.cpp"
> >
</File> </File>
<File
RelativePath=".\src\iterpriv.cpp"
>
</File>
<File <File
RelativePath=".\src\map.cpp" RelativePath=".\src\map.cpp"
> >
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment