Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
yaml-cpp
Commits
45322566
Commit
45322566
authored
Sep 03, 2008
by
Jesse Beder
Browse files
Set the eol style to native for all files.
parent
a45f083e
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1673 additions
and
1673 deletions
+1673
-1673
include/crt.h
include/crt.h
+11
-11
include/exceptions.h
include/exceptions.h
+59
-59
include/iterator.h
include/iterator.h
+30
-30
include/node.h
include/node.h
+92
-92
include/parser.h
include/parser.h
+42
-42
include/parserstate.h
include/parserstate.h
+20
-20
include/yaml.h
include/yaml.h
+8
-8
src/content.cpp
src/content.cpp
+13
-13
src/content.h
src/content.h
+55
-55
src/exp.cpp
src/exp.cpp
+113
-113
src/exp.h
src/exp.h
+71
-71
src/iterator.cpp
src/iterator.cpp
+108
-108
src/iterpriv.h
src/iterpriv.h
+25
-25
src/ltnode.h
src/ltnode.h
+10
-10
src/map.cpp
src/map.cpp
+196
-196
src/map.h
src/map.h
+38
-38
src/node.cpp
src/node.cpp
+317
-317
src/parser.cpp
src/parser.cpp
+133
-133
src/parserstate.cpp
src/parserstate.cpp
+26
-26
src/regex.cpp
src/regex.cpp
+306
-306
No files found.
include/crt.h
View file @
45322566
#pragma once
// for detecting memory leaks
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif // _DEBUG
#pragma once
// for detecting memory leaks
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif // _DEBUG
include/exceptions.h
View file @
45322566
#pragma once
#include <exception>
#include <string>
namespace
YAML
{
class
Exception
:
public
std
::
exception
{};
class
ParserException
:
public
Exception
{
public:
ParserException
(
int
line_
,
int
column_
,
const
std
::
string
&
msg_
)
:
line
(
line_
),
column
(
column_
),
msg
(
msg_
)
{}
virtual
~
ParserException
()
throw
()
{}
int
line
,
column
;
std
::
string
msg
;
};
class
RepresentationException
:
public
Exception
{};
// representation exceptions
class
InvalidScalar
:
public
RepresentationException
{};
class
BadDereference
:
public
RepresentationException
{};
// error messages
namespace
ErrorMsg
{
const
std
::
string
YAML_DIRECTIVE_ARGS
=
"YAML directives must have exactly one argument"
;
const
std
::
string
YAML_VERSION
=
"bad YAML version: "
;
const
std
::
string
YAML_MAJOR_VERSION
=
"YAML major version too large"
;
const
std
::
string
TAG_DIRECTIVE_ARGS
=
"TAG directives must have exactly two arguments"
;
const
std
::
string
END_OF_MAP
=
"end of map not found"
;
const
std
::
string
END_OF_MAP_FLOW
=
"end of map flow not found"
;
const
std
::
string
END_OF_SEQ
=
"end of sequence not found"
;
const
std
::
string
END_OF_SEQ_FLOW
=
"end of sequence flow not found"
;
const
std
::
string
MULTIPLE_TAGS
=
"cannot assign multiple tags to the same node"
;
const
std
::
string
MULTIPLE_ANCHORS
=
"cannot assign multiple anchors to the same node"
;
const
std
::
string
MULTIPLE_ALIASES
=
"cannot assign multiple aliases to the same node"
;
const
std
::
string
ALIAS_CONTENT
=
"aliases can't have any content, *including* tags"
;
const
std
::
string
INVALID_HEX
=
"bad character found while scanning hex number"
;
const
std
::
string
INVALID_UNICODE
=
"invalid unicode: "
;
const
std
::
string
INVALID_ESCAPE
=
"unknown escape character: "
;
const
std
::
string
UNKNOWN_TOKEN
=
"unknown token"
;
const
std
::
string
DOC_IN_SCALAR
=
"illegal document indicator in scalar"
;
const
std
::
string
EOF_IN_SCALAR
=
"illegal EOF in scalar"
;
const
std
::
string
CHAR_IN_SCALAR
=
"illegal character in scalar"
;
const
std
::
string
TAB_IN_INDENTATION
=
"illegal tab when looking for indentation"
;
const
std
::
string
FLOW_END
=
"illegal flow end"
;
const
std
::
string
BLOCK_ENTRY
=
"illegal block entry"
;
const
std
::
string
MAP_KEY
=
"illegal map key"
;
const
std
::
string
MAP_VALUE
=
"illegal map value"
;
const
std
::
string
ALIAS_NOT_FOUND
=
"alias not found after *"
;
const
std
::
string
ANCHOR_NOT_FOUND
=
"anchor not found after &"
;
const
std
::
string
CHAR_IN_ALIAS
=
"illegal character found while scanning alias"
;
const
std
::
string
CHAR_IN_ANCHOR
=
"illegal character found while scanning anchor"
;
const
std
::
string
ZERO_INDENT_IN_BLOCK
=
"cannot set zero indentation for a block scalar"
;
const
std
::
string
CHAR_IN_BLOCK
=
"unexpected character in block scalar"
;
}
}
#pragma once
#include <exception>
#include <string>
namespace
YAML
{
class
Exception
:
public
std
::
exception
{};
class
ParserException
:
public
Exception
{
public:
ParserException
(
int
line_
,
int
column_
,
const
std
::
string
&
msg_
)
:
line
(
line_
),
column
(
column_
),
msg
(
msg_
)
{}
virtual
~
ParserException
()
throw
()
{}
int
line
,
column
;
std
::
string
msg
;
};
class
RepresentationException
:
public
Exception
{};
// representation exceptions
class
InvalidScalar
:
public
RepresentationException
{};
class
BadDereference
:
public
RepresentationException
{};
// error messages
namespace
ErrorMsg
{
const
std
::
string
YAML_DIRECTIVE_ARGS
=
"YAML directives must have exactly one argument"
;
const
std
::
string
YAML_VERSION
=
"bad YAML version: "
;
const
std
::
string
YAML_MAJOR_VERSION
=
"YAML major version too large"
;
const
std
::
string
TAG_DIRECTIVE_ARGS
=
"TAG directives must have exactly two arguments"
;
const
std
::
string
END_OF_MAP
=
"end of map not found"
;
const
std
::
string
END_OF_MAP_FLOW
=
"end of map flow not found"
;
const
std
::
string
END_OF_SEQ
=
"end of sequence not found"
;
const
std
::
string
END_OF_SEQ_FLOW
=
"end of sequence flow not found"
;
const
std
::
string
MULTIPLE_TAGS
=
"cannot assign multiple tags to the same node"
;
const
std
::
string
MULTIPLE_ANCHORS
=
"cannot assign multiple anchors to the same node"
;
const
std
::
string
MULTIPLE_ALIASES
=
"cannot assign multiple aliases to the same node"
;
const
std
::
string
ALIAS_CONTENT
=
"aliases can't have any content, *including* tags"
;
const
std
::
string
INVALID_HEX
=
"bad character found while scanning hex number"
;
const
std
::
string
INVALID_UNICODE
=
"invalid unicode: "
;
const
std
::
string
INVALID_ESCAPE
=
"unknown escape character: "
;
const
std
::
string
UNKNOWN_TOKEN
=
"unknown token"
;
const
std
::
string
DOC_IN_SCALAR
=
"illegal document indicator in scalar"
;
const
std
::
string
EOF_IN_SCALAR
=
"illegal EOF in scalar"
;
const
std
::
string
CHAR_IN_SCALAR
=
"illegal character in scalar"
;
const
std
::
string
TAB_IN_INDENTATION
=
"illegal tab when looking for indentation"
;
const
std
::
string
FLOW_END
=
"illegal flow end"
;
const
std
::
string
BLOCK_ENTRY
=
"illegal block entry"
;
const
std
::
string
MAP_KEY
=
"illegal map key"
;
const
std
::
string
MAP_VALUE
=
"illegal map value"
;
const
std
::
string
ALIAS_NOT_FOUND
=
"alias not found after *"
;
const
std
::
string
ANCHOR_NOT_FOUND
=
"anchor not found after &"
;
const
std
::
string
CHAR_IN_ALIAS
=
"illegal character found while scanning alias"
;
const
std
::
string
CHAR_IN_ANCHOR
=
"illegal character found while scanning anchor"
;
const
std
::
string
ZERO_INDENT_IN_BLOCK
=
"cannot set zero indentation for a block scalar"
;
const
std
::
string
CHAR_IN_BLOCK
=
"unexpected character in block scalar"
;
}
}
include/iterator.h
View file @
45322566
#pragma once
namespace
YAML
{
class
Node
;
struct
IterPriv
;
class
Iterator
{
public:
Iterator
();
Iterator
(
IterPriv
*
pData
);
Iterator
(
const
Iterator
&
rhs
);
~
Iterator
();
Iterator
&
operator
=
(
const
Iterator
&
rhs
);
Iterator
&
operator
++
();
Iterator
operator
++
(
int
);
const
Node
&
operator
*
()
const
;
const
Node
*
operator
->
()
const
;
const
Node
&
first
()
const
;
const
Node
&
second
()
const
;
friend
bool
operator
==
(
const
Iterator
&
it
,
const
Iterator
&
jt
);
friend
bool
operator
!=
(
const
Iterator
&
it
,
const
Iterator
&
jt
);
private:
IterPriv
*
m_pData
;
};
}
#pragma once
namespace
YAML
{
class
Node
;
struct
IterPriv
;
class
Iterator
{
public:
Iterator
();
Iterator
(
IterPriv
*
pData
);
Iterator
(
const
Iterator
&
rhs
);
~
Iterator
();
Iterator
&
operator
=
(
const
Iterator
&
rhs
);
Iterator
&
operator
++
();
Iterator
operator
++
(
int
);
const
Node
&
operator
*
()
const
;
const
Node
*
operator
->
()
const
;
const
Node
&
first
()
const
;
const
Node
&
second
()
const
;
friend
bool
operator
==
(
const
Iterator
&
it
,
const
Iterator
&
jt
);
friend
bool
operator
!=
(
const
Iterator
&
it
,
const
Iterator
&
jt
);
private:
IterPriv
*
m_pData
;
};
}
include/node.h
View file @
45322566
#pragma once
#include <string>
#include <ios>
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
#include "iterator.h"
namespace
YAML
{
class
Content
;
class
Scanner
;
enum
CONTENT_TYPE
{
CT_NONE
,
CT_SCALAR
,
CT_SEQUENCE
,
CT_MAP
};
class
Node
{
public:
Node
();
~
Node
();
void
Clear
();
void
Parse
(
Scanner
*
pScanner
,
const
ParserState
&
state
);
void
Write
(
std
::
ostream
&
out
,
int
indent
,
bool
startedLine
,
bool
onlyOneCharOnLine
)
const
;
CONTENT_TYPE
GetType
()
const
;
// accessors
Iterator
begin
()
const
;
Iterator
end
()
const
;
unsigned
size
()
const
;
template
<
typename
T
>
const
Node
&
GetValue
(
const
T
&
key
)
const
{
if
(
!
m_pContent
)
throw
BadDereference
();
for
(
Iterator
it
=
begin
();
it
!=
end
();
++
it
)
{
T
t
;
try
{
it
.
first
()
>>
t
;
if
(
key
==
t
)
return
it
.
second
();
}
catch
(
RepresentationException
&
)
{
}
}
throw
BadDereference
();
}
template
<
typename
T
>
const
Node
&
operator
[]
(
const
T
&
key
)
const
{
return
GetValue
(
key
);
}
const
Node
&
operator
[]
(
const
char
*
key
)
const
{
return
GetValue
(
std
::
string
(
key
));
}
const
Node
&
operator
[]
(
unsigned
u
)
const
;
const
Node
&
operator
[]
(
int
i
)
const
;
// extraction
friend
void
operator
>>
(
const
Node
&
node
,
std
::
string
&
s
);
friend
void
operator
>>
(
const
Node
&
node
,
int
&
i
);
friend
void
operator
>>
(
const
Node
&
node
,
unsigned
&
u
);
friend
void
operator
>>
(
const
Node
&
node
,
long
&
l
);
friend
void
operator
>>
(
const
Node
&
node
,
float
&
f
);
friend
void
operator
>>
(
const
Node
&
node
,
double
&
d
);
friend
void
operator
>>
(
const
Node
&
node
,
char
&
c
);
// 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
);
void
ParseAnchor
(
Scanner
*
pScanner
,
const
ParserState
&
state
);
void
ParseAlias
(
Scanner
*
pScanner
,
const
ParserState
&
state
);
private:
std
::
string
m_anchor
,
m_tag
;
Content
*
m_pContent
;
bool
m_alias
;
};
}
#pragma once
#include <string>
#include <ios>
#include <vector>
#include <map>
#include "parserstate.h"
#include "exceptions.h"
#include "iterator.h"
namespace
YAML
{
class
Content
;
class
Scanner
;
enum
CONTENT_TYPE
{
CT_NONE
,
CT_SCALAR
,
CT_SEQUENCE
,
CT_MAP
};
class
Node
{
public:
Node
();
~
Node
();
void
Clear
();
void
Parse
(
Scanner
*
pScanner
,
const
ParserState
&
state
);
void
Write
(
std
::
ostream
&
out
,
int
indent
,
bool
startedLine
,
bool
onlyOneCharOnLine
)
const
;
CONTENT_TYPE
GetType
()
const
;
// accessors
Iterator
begin
()
const
;
Iterator
end
()
const
;
unsigned
size
()
const
;
template
<
typename
T
>
const
Node
&
GetValue
(
const
T
&
key
)
const
{
if
(
!
m_pContent
)
throw
BadDereference
();
for
(
Iterator
it
=
begin
();
it
!=
end
();
++
it
)
{
T
t
;
try
{
it
.
first
()
>>
t
;
if
(
key
==
t
)
return
it
.
second
();
}
catch
(
RepresentationException
&
)
{
}
}
throw
BadDereference
();
}
template
<
typename
T
>
const
Node
&
operator
[]
(
const
T
&
key
)
const
{
return
GetValue
(
key
);
}
const
Node
&
operator
[]
(
const
char
*
key
)
const
{
return
GetValue
(
std
::
string
(
key
));
}
const
Node
&
operator
[]
(
unsigned
u
)
const
;
const
Node
&
operator
[]
(
int
i
)
const
;
// extraction
friend
void
operator
>>
(
const
Node
&
node
,
std
::
string
&
s
);
friend
void
operator
>>
(
const
Node
&
node
,
int
&
i
);
friend
void
operator
>>
(
const
Node
&
node
,
unsigned
&
u
);
friend
void
operator
>>
(
const
Node
&
node
,
long
&
l
);
friend
void
operator
>>
(
const
Node
&
node
,
float
&
f
);
friend
void
operator
>>
(
const
Node
&
node
,
double
&
d
);
friend
void
operator
>>
(
const
Node
&
node
,
char
&
c
);
// 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
);
void
ParseAnchor
(
Scanner
*
pScanner
,
const
ParserState
&
state
);
void
ParseAlias
(
Scanner
*
pScanner
,
const
ParserState
&
state
);
private:
std
::
string
m_anchor
,
m_tag
;
Content
*
m_pContent
;
bool
m_alias
;
};
}
include/parser.h
View file @
45322566
#pragma once
#include <ios>
#include <string>
#include <vector>
#include <map>
#include "node.h"
#include "parserstate.h"
namespace
YAML
{
class
Scanner
;
struct
Token
;
class
Parser
{
public:
Parser
(
std
::
istream
&
in
);
~
Parser
();
operator
bool
()
const
;
void
Load
(
std
::
istream
&
in
);
void
GetNextDocument
(
Node
&
document
);
void
PrintTokens
(
std
::
ostream
&
out
);
private:
void
ParseDirectives
();
void
HandleDirective
(
Token
*
pToken
);
void
HandleYamlDirective
(
Token
*
pToken
);
void
HandleTagDirective
(
Token
*
pToken
);
private:
// can't copy this
Parser
(
const
Parser
&
rhs
)
{}
Parser
&
operator
=
(
const
Parser
&
rhs
)
{
return
*
this
;
}
private:
Scanner
*
m_pScanner
;
ParserState
m_state
;
};
}
#pragma once
#include <ios>
#include <string>
#include <vector>
#include <map>
#include "node.h"
#include "parserstate.h"
namespace
YAML
{
class
Scanner
;
struct
Token
;
class
Parser
{
public:
Parser
(
std
::
istream
&
in
);
~
Parser
();
operator
bool
()
const
;
void
Load
(
std
::
istream
&
in
);
void
GetNextDocument
(
Node
&
document
);
void
PrintTokens
(
std
::
ostream
&
out
);
private:
void
ParseDirectives
();
void
HandleDirective
(
Token
*
pToken
);
void
HandleYamlDirective
(
Token
*
pToken
);
void
HandleTagDirective
(
Token
*
pToken
);
private:
// can't copy this
Parser
(
const
Parser
&
rhs
)
{}
Parser
&
operator
=
(
const
Parser
&
rhs
)
{
return
*
this
;
}
private:
Scanner
*
m_pScanner
;
ParserState
m_state
;
};
}
include/parserstate.h
View file @
45322566
#pragma once
#include <string>
#include <map>
namespace
YAML
{
struct
Version
{
int
major
,
minor
;
};
struct
ParserState
{
Version
version
;
std
::
map
<
std
::
string
,
std
::
string
>
tags
;
void
Reset
();
std
::
string
TranslateTag
(
const
std
::
string
&
handle
)
const
;
};
}
#pragma once
#include <string>
#include <map>
namespace
YAML
{
struct
Version
{
int
major
,
minor
;
};
struct
ParserState
{
Version
version
;
std
::
map
<
std
::
string
,
std
::
string
>
tags
;
void
Reset
();
std
::
string
TranslateTag
(
const
std
::
string
&
handle
)
const
;
};
}
include/yaml.h
View file @
45322566
#pragma once
#include "crt.h"
#include "parser.h"
#include "node.h"
#include "iterator.h"
#include "exceptions.h"
#pragma once
#include "crt.h"
#include "parser.h"
#include "node.h"
#include "iterator.h"
#include "exceptions.h"
src/content.cpp
View file @
45322566
#include "crt.h"
#include "content.h"
namespace
YAML
{
Content
::
Content
()
{
}
Content
::~
Content
()
{
}
}
#include "crt.h"
#include "content.h"
namespace
YAML
{
Content
::
Content
()
{
}
Content
::~
Content
()
{
}
}
src/content.h
View file @
45322566
#pragma once
#include <ios>
#include <vector>
#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
{
public:
Content
();
virtual
~
Content
();
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
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
void
Read
(
std
::
string
&
s
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
int
&
i
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
unsigned
&
u
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
long
&
l
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
float
&
f
)
{
throw
InvalidScalar
();
}
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:
};
}
#pragma once
#include <ios>
#include <vector>
#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
{
public:
Content
();
virtual
~
Content
();
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
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
void
Read
(
std
::
string
&
s
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
int
&
i
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
unsigned
&
u
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
long
&
l
)
{
throw
InvalidScalar
();
}
virtual
void
Read
(
float
&
f
)
{
throw
InvalidScalar
();
}
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:
};
}
src/exp.cpp
View file @
45322566
#include "crt.h"
#include "exp.h"
#include "exceptions.h"
#include <sstream>
namespace
YAML
{
namespace
Exp
{
unsigned
ParseHex
(
const
std
::
string
&
str
,
int
line
,
int
column
)
{
unsigned
value
=
0
;
for
(
unsigned
i
=
0
;
i
<
str
.
size
();
i
++
)
{
char
ch
=
str
[
i
];
int
digit
=
0
;
if
(
'a'
<=
ch
&&
ch
<=
'f'
)
digit
=
ch
-
'a'
+
10
;
else
if
(
'A'
<=
ch
&&
ch
<=
'F'
)
digit
=
ch
-
'A'
+
10
;
else
if
(
'0'
<=
ch
&&
ch
<=
'9'
)
digit
=
ch
-
'0'
;
else
throw
ParserException
(
line
,
column
,
ErrorMsg
::
INVALID_HEX
);
value
=
(
value
<<
4
)
+
digit
;
}
return
value
;
}
std
::
string
Str
(
char
ch
)
{
return
std
::
string
(
""
)
+
ch
;
}
// Escape
// . Translates the next 'codeLength' characters into a hex number and returns the result.
// . Throws if it's not actually hex.
std
::
string
Escape
(
Stream
&
in
,
int
codeLength
)
{
// grab string
std
::
string
str
;
for
(
int
i
=
0
;
i
<
codeLength
;
i
++
)
str
+=
in
.
get
();
// get the value
unsigned
value
=
ParseHex
(
str
,
in
.
line
,
in
.
column
);
// legal unicode?
if
((
value
>=
0xD800
&&
value
<=
0xDFFF
)
||
value
>
0x10FFFF
)
{
std
::
stringstream
msg
;
msg
<<
ErrorMsg
::
INVALID_UNICODE
<<
value
;
throw
ParserException
(
in
.
line
,
in
.
column
,
msg
.
str
());
}
// now break it up into chars
if
(
value
<=
0x7F
)
return
Str
(
value
);
else
if
(
value
<=
0x7FF
)
return
Str
(
0xC0
+
(
value
>>
6
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
if
(
value
<=
0xFFFF
)
return
Str
(
0xE0
+
(
value
>>
12
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
return
Str
(
0xF0
+
(
value
>>
18
))
+
Str
(
0x80
+
((
value
>>
12
)
&
0x3F
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
}
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote)
// and returns the result.
// . Throws if it's an unknown escape character.
std
::
string
Escape
(
Stream
&
in
)
{
// eat slash
char
escape
=
in
.
get
();
// switch on escape character
char
ch
=
in
.
get
();
// first do single quote, since it's easier
if
(
escape
==
'\''
&&
ch
==
'\''
)
return
"
\'
"
;
// now do the slash (we're not gonna check if it's a slash - you better pass one!)
switch
(
ch
)
{
case
'0'
:
return
"
\0
"
;
case
'a'
:
return
"
\x07
"
;
case
'b'
:
return
"
\x08
"
;
case
't'
:
case
'\t'
:
return
"
\x09
"
;
case
'n'
:
return
"
\x0A
"
;
case
'v'
:
return
"
\x0B
"
;
case
'f'
:
return
"
\x0C
"
;
case
'r'
:
return
"
\x0D
"
;
case
'e'
:
return
"
\x1B
"
;
case
' '
:
return
"
\x20
"
;
case
'\"'
:
return
"
\"
"
;
case
'\''
:
return
"
\'
"
;
case
'\\'
:
return
"
\\
"
;
case
'N'
:
return
"
\xC2\x85
"
;
// NEL (#x85)
case
'_'
:
return
"
\xC2\xA0
"
;
// #xA0
case
'L'
:
return
"
\xE2\x80\xA8
"
;
// LS (#x2028)
case
'P'
:
return
"
\xE2\x80\xA9
"
;
// PS (#x2029)
case
'x'
:
return
Escape
(
in
,
2
);
case
'u'
:
return
Escape
(
in
,
4
);
case
'U'
:
return
Escape
(
in
,
8
);
}
std
::
stringstream
msg
;
throw
ParserException
(
in
.
line
,
in
.
column
,
ErrorMsg
::
INVALID_ESCAPE
+
ch
);
}
}
}
#include "crt.h"
#include "exp.h"
#include "exceptions.h"
#include <sstream>
namespace
YAML
{
namespace
Exp
{
unsigned
ParseHex
(
const
std
::
string
&
str
,
int
line
,
int
column
)
{
unsigned
value
=
0
;
for
(
unsigned
i
=
0
;
i
<
str
.
size
();
i
++
)
{
char
ch
=
str
[
i
];
int
digit
=
0
;
if
(
'a'
<=
ch
&&
ch
<=
'f'
)
digit
=
ch
-
'a'
+
10
;
else
if
(
'A'
<=
ch
&&
ch
<=
'F'
)
digit
=
ch
-
'A'
+
10
;
else
if
(
'0'
<=
ch
&&
ch
<=
'9'
)
digit
=
ch
-
'0'
;
else
throw
ParserException
(
line
,
column
,
ErrorMsg
::
INVALID_HEX
);
value
=
(
value
<<
4
)
+
digit
;
}
return
value
;
}
std
::
string
Str
(
char
ch
)
{
return
std
::
string
(
""
)
+
ch
;
}
// Escape
// . Translates the next 'codeLength' characters into a hex number and returns the result.
// . Throws if it's not actually hex.
std
::
string
Escape
(
Stream
&
in
,
int
codeLength
)
{
// grab string
std
::
string
str
;
for
(
int
i
=
0
;
i
<
codeLength
;
i
++
)
str
+=
in
.
get
();
// get the value
unsigned
value
=
ParseHex
(
str
,
in
.
line
,
in
.
column
);
// legal unicode?
if
((
value
>=
0xD800
&&
value
<=
0xDFFF
)
||
value
>
0x10FFFF
)
{
std
::
stringstream
msg
;
msg
<<
ErrorMsg
::
INVALID_UNICODE
<<
value
;
throw
ParserException
(
in
.
line
,
in
.
column
,
msg
.
str
());
}
// now break it up into chars
if
(
value
<=
0x7F
)
return
Str
(
value
);
else
if
(
value
<=
0x7FF
)
return
Str
(
0xC0
+
(
value
>>
6
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
if
(
value
<=
0xFFFF
)
return
Str
(
0xE0
+
(
value
>>
12
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
else
return
Str
(
0xF0
+
(
value
>>
18
))
+
Str
(
0x80
+
((
value
>>
12
)
&
0x3F
))
+
Str
(
0x80
+
((
value
>>
6
)
&
0x3F
))
+
Str
(
0x80
+
(
value
&
0x3F
));
}
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\' or single quote)
// and returns the result.
// . Throws if it's an unknown escape character.
std
::
string
Escape
(
Stream
&
in
)
{
// eat slash
char
escape
=
in
.
get
();
// switch on escape character
char
ch
=
in
.
get
();
// first do single quote, since it's easier
if
(
escape
==
'\''
&&
ch
==
'\''
)
return
"
\'
"
;
// now do the slash (we're not gonna check if it's a slash - you better pass one!)
switch
(
ch
)
{
case
'0'
:
return
"
\0
"
;
case
'a'
:
return
"
\x07
"
;
case
'b'
:
return
"
\x08
"
;
case
't'
:
case
'\t'
:
return
"
\x09
"
;
case
'n'
:
return
"
\x0A
"
;
case
'v'
:
return
"
\x0B
"
;
case
'f'
:
return
"
\x0C
"
;
case
'r'
:
return
"
\x0D
"
;
case
'e'
:
return
"
\x1B
"
;
case
' '
:
return
"
\x20
"
;
case
'\"'
:
return
"
\"
"
;
case
'\''
:
return
"
\'
"
;
case
'\\'
:
return
"
\\
"
;
case
'N'
:
return
"
\xC2\x85
"
;
// NEL (#x85)
case
'_'
:
return
"
\xC2\xA0
"
;
// #xA0
case
'L'
:
return
"
\xE2\x80\xA8
"
;
// LS (#x2028)
case
'P'
:
return
"
\xE2\x80\xA9
"
;
// PS (#x2029)
case
'x'
:
return
Escape
(
in
,
2
);
case
'u'
:
return
Escape
(
in
,
4
);
case
'U'
:
return
Escape
(
in
,
8
);
}
std
::
stringstream
msg
;
throw
ParserException
(
in
.
line
,
in
.
column
,
ErrorMsg
::
INVALID_ESCAPE
+
ch
);
}
}
}
src/exp.h
View file @
45322566
#pragma once
#include "regex.h"
#include <string>
#include <ios>
#include "stream.h"
namespace
YAML
{
////////////////////////////////////////////////////////////////////////////////
// Here we store a bunch of expressions for matching different parts of the file.
namespace
Exp
{
// misc
const
RegEx
Blank
=
RegEx
(
' '
)
||
RegEx
(
'\t'
);
const
RegEx
Break
=
RegEx
(
'\n'
)
||
RegEx
(
"
\r\n
"
);
const
RegEx
BlankOrBreak
=
Blank
||
Break
;
const
RegEx
Digit
=
RegEx
(
'0'
,
'9'
);
const
RegEx
Alpha
=
RegEx
(
'a'
,
'z'
)
||
RegEx
(
'A'
,
'Z'
);
const
RegEx
AlphaNumeric
=
Alpha
||
Digit
;
const
RegEx
Hex
=
Digit
||
RegEx
(
'A'
,
'F'
)
||
RegEx
(
'a'
,
'f'
);
// actual tags
const
RegEx
DocStart
=
RegEx
(
"---"
)
+
(
BlankOrBreak
||
RegEx
(
EOF
)
||
RegEx
());
const
RegEx
DocEnd
=
RegEx
(
"..."
)
+
(
BlankOrBreak
||
RegEx
(
EOF
)
||
RegEx
());
const
RegEx
DocIndicator
=
DocStart
||
DocEnd
;
const
RegEx
BlockEntry
=
RegEx
(
'-'
)
+
(
BlankOrBreak
||
RegEx
(
EOF
));
const
RegEx
Key
=
RegEx
(
'?'
),
KeyInFlow
=
RegEx
(
'?'
)
+
BlankOrBreak
;
const
RegEx
Value
=
RegEx
(
':'
)
+
BlankOrBreak
,
ValueInFlow
=
RegEx
(
':'
)
+
BlankOrBreak
;
const
RegEx
Comment
=
RegEx
(
'#'
);
const
RegEx
AnchorEnd
=
RegEx
(
"?:,]}%@`"
,
REGEX_OR
)
||
BlankOrBreak
;
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a space.
const
RegEx
PlainScalar
=
!
(
BlankOrBreak
||
RegEx
(
",[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-?:"
,
REGEX_OR
)
+
Blank
)),
PlainScalarInFlow
=
!
(
BlankOrBreak
||
RegEx
(
"?,[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-:"
,
REGEX_OR
)
+
Blank
));
const
RegEx
EndScalar
=
RegEx
(
':'
)
+
BlankOrBreak
,
EndScalarInFlow
=
(
RegEx
(
':'
)
+
BlankOrBreak
)
||
RegEx
(
",?[]{}"
,
REGEX_OR
);
const
RegEx
EscSingleQuote
=
RegEx
(
"
\'\'
"
);
const
RegEx
EscBreak
=
RegEx
(
'\\'
)
+
Break
;
const
RegEx
ChompIndicator
=
RegEx
(
"+-"
,
REGEX_OR
);
const
RegEx
Chomp
=
(
ChompIndicator
+
Digit
)
||
(
Digit
+
ChompIndicator
)
||
ChompIndicator
||
Digit
;
// and some functions
std
::
string
Escape
(
Stream
&
in
);
}
namespace
Keys
{
const
char
Directive
=
'%'
;
const
char
FlowSeqStart
=
'['
;
const
char
FlowSeqEnd
=
']'
;
const
char
FlowMapStart
=
'{'
;
const
char
FlowMapEnd
=
'}'
;
const
char
FlowEntry
=
','
;
const
char
Alias
=
'*'
;
const
char
Anchor
=
'&'
;
const
char
Tag
=
'!'
;
const
char
LiteralScalar
=
'|'
;
const
char
FoldedScalar
=
'>'
;
}
}
#pragma once
#include "regex.h"
#include <string>
#include <ios>
#include "stream.h"
namespace
YAML
{
////////////////////////////////////////////////////////////////////////////////
// Here we store a bunch of expressions for matching different parts of the file.
namespace
Exp
{
// misc
const
RegEx
Blank
=
RegEx
(
' '
)
||
RegEx
(
'\t'
);
const
RegEx
Break
=
RegEx
(
'\n'
)
||
RegEx
(
"
\r\n
"
);
const
RegEx
BlankOrBreak
=
Blank
||
Break
;
const
RegEx
Digit
=
RegEx
(
'0'
,
'9'
);
const
RegEx
Alpha
=
RegEx
(
'a'
,
'z'
)
||
RegEx
(
'A'
,
'Z'
);
const
RegEx
AlphaNumeric
=
Alpha
||
Digit
;
const
RegEx
Hex
=
Digit
||
RegEx
(
'A'
,
'F'
)
||
RegEx
(
'a'
,
'f'
);
// actual tags
const
RegEx
DocStart
=
RegEx
(
"---"
)
+
(
BlankOrBreak
||
RegEx
(
EOF
)
||
RegEx
());
const
RegEx
DocEnd
=
RegEx
(
"..."
)
+
(
BlankOrBreak
||
RegEx
(
EOF
)
||
RegEx
());
const
RegEx
DocIndicator
=
DocStart
||
DocEnd
;
const
RegEx
BlockEntry
=
RegEx
(
'-'
)
+
(
BlankOrBreak
||
RegEx
(
EOF
));
const
RegEx
Key
=
RegEx
(
'?'
),
KeyInFlow
=
RegEx
(
'?'
)
+
BlankOrBreak
;
const
RegEx
Value
=
RegEx
(
':'
)
+
BlankOrBreak
,
ValueInFlow
=
RegEx
(
':'
)
+
BlankOrBreak
;
const
RegEx
Comment
=
RegEx
(
'#'
);
const
RegEx
AnchorEnd
=
RegEx
(
"?:,]}%@`"
,
REGEX_OR
)
||
BlankOrBreak
;
// Plain scalar rules:
// . Cannot start with a blank.
// . Can never start with any of , [ ] { } # & * ! | > \' \" % @ `
// . In the block context - ? : must be not be followed with a space.
// . In the flow context ? is illegal and : and - must not be followed with a space.
const
RegEx
PlainScalar
=
!
(
BlankOrBreak
||
RegEx
(
",[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-?:"
,
REGEX_OR
)
+
Blank
)),
PlainScalarInFlow
=
!
(
BlankOrBreak
||
RegEx
(
"?,[]{}#&*!|>
\'\"
%@`"
,
REGEX_OR
)
||
(
RegEx
(
"-:"
,
REGEX_OR
)
+
Blank
));
const
RegEx
EndScalar
=
RegEx
(
':'
)
+
BlankOrBreak
,
EndScalarInFlow
=
(
RegEx
(
':'
)
+
BlankOrBreak
)
||
RegEx
(
",?[]{}"
,
REGEX_OR
);
const
RegEx
EscSingleQuote
=
RegEx
(
"
\'\'
"
);
const
RegEx
EscBreak
=
RegEx
(
'\\'
)
+
Break
;
const
RegEx
ChompIndicator
=
RegEx
(
"+-"
,
REGEX_OR
);
const
RegEx
Chomp
=
(
ChompIndicator
+
Digit
)
||
(
Digit
+
ChompIndicator
)
||
ChompIndicator
||
Digit
;
// and some functions
std
::
string
Escape
(
Stream
&
in
);
}
namespace
Keys
{
const
char
Directive
=
'%'
;
const
char
FlowSeqStart
=
'['
;
const
char
FlowSeqEnd
=
']'
;
const
char
FlowMapStart
=
'{'
;
const
char
FlowMapEnd
=
'}'
;
const
char
FlowEntry
=
','
;
const
char
Alias
=
'*'
;
const
char
Anchor
=
'&'
;
const
char
Tag
=
'!'
;
const
char
LiteralScalar
=
'|'
;
const
char
FoldedScalar
=
'>'
;
}
}
src/iterator.cpp
View file @
45322566
#include "crt.h"
#include "node.h"
#include "exceptions.h"
#include "iterpriv.h"
namespace
YAML
{
Iterator
::
Iterator
()
:
m_pData
(
0
)
{
m_pData
=
new
IterPriv
;
}
Iterator
::
Iterator
(
IterPriv
*
pData
)
:
m_pData
(
pData
)
{
}
Iterator
::
Iterator
(
const
Iterator
&
rhs
)
:
m_pData
(
0
)
{
m_pData
=
new
IterPriv
(
*
rhs
.
m_pData
);
}
Iterator
&
Iterator
::
operator
=
(
const
Iterator
&
rhs
)
{
if
(
this
==
&
rhs
)
return
*
this
;
delete
m_pData
;
m_pData
=
new
IterPriv
(
*
rhs
.
m_pData
);
return
*
this
;
}
Iterator
::~
Iterator
()
{
delete
m_pData
;
}
Iterator
&
Iterator
::
operator
++
()
{
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
++
m_pData
->
seqIter
;
else
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
++
m_pData
->
mapIter
;
return
*
this
;
}
Iterator
Iterator
::
operator
++
(
int
)
{
Iterator
temp
=
*
this
;
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
++
m_pData
->
seqIter
;
else
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
++
m_pData
->
mapIter
;
return
temp
;
}
const
Node
&
Iterator
::
operator
*
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
return
**
m_pData
->
seqIter
;
throw
BadDereference
();
}
const
Node
*
Iterator
::
operator
->
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
return
*
m_pData
->
seqIter
;
throw
BadDereference
();
}
const
Node
&
Iterator
::
first
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
return
*
m_pData
->
mapIter
->
first
;
throw
BadDereference
();
}
const
Node
&
Iterator
::
second
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
return
*
m_pData
->
mapIter
->
second
;
throw
BadDereference
();
}
bool
operator
==
(
const
Iterator
&
it
,
const
Iterator
&
jt
)
{
if
(
it
.
m_pData
->
type
!=
jt
.
m_pData
->
type
)
return
false
;
if
(
it
.
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
return
it
.
m_pData
->
seqIter
==
jt
.
m_pData
->
seqIter
;
else
if
(
it
.
m_pData
->
type
==
IterPriv
::
IT_MAP
)
return
it
.
m_pData
->
mapIter
==
jt
.
m_pData
->
mapIter
;
return
true
;
}
bool
operator
!=
(
const
Iterator
&
it
,
const
Iterator
&
jt
)
{
return
!
(
it
==
jt
);
}
}
#include "crt.h"
#include "node.h"
#include "exceptions.h"
#include "iterpriv.h"
namespace
YAML
{
Iterator
::
Iterator
()
:
m_pData
(
0
)
{
m_pData
=
new
IterPriv
;
}
Iterator
::
Iterator
(
IterPriv
*
pData
)
:
m_pData
(
pData
)
{
}
Iterator
::
Iterator
(
const
Iterator
&
rhs
)
:
m_pData
(
0
)
{
m_pData
=
new
IterPriv
(
*
rhs
.
m_pData
);
}
Iterator
&
Iterator
::
operator
=
(
const
Iterator
&
rhs
)
{
if
(
this
==
&
rhs
)
return
*
this
;
delete
m_pData
;
m_pData
=
new
IterPriv
(
*
rhs
.
m_pData
);
return
*
this
;
}
Iterator
::~
Iterator
()
{
delete
m_pData
;
}
Iterator
&
Iterator
::
operator
++
()
{
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
++
m_pData
->
seqIter
;
else
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
++
m_pData
->
mapIter
;
return
*
this
;
}
Iterator
Iterator
::
operator
++
(
int
)
{
Iterator
temp
=
*
this
;
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
++
m_pData
->
seqIter
;
else
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
++
m_pData
->
mapIter
;
return
temp
;
}
const
Node
&
Iterator
::
operator
*
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
return
**
m_pData
->
seqIter
;
throw
BadDereference
();
}
const
Node
*
Iterator
::
operator
->
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
return
*
m_pData
->
seqIter
;
throw
BadDereference
();
}
const
Node
&
Iterator
::
first
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
return
*
m_pData
->
mapIter
->
first
;
throw
BadDereference
();
}
const
Node
&
Iterator
::
second
()
const
{
if
(
m_pData
->
type
==
IterPriv
::
IT_MAP
)
return
*
m_pData
->
mapIter
->
second
;
throw
BadDereference
();
}
bool
operator
==
(
const
Iterator
&
it
,
const
Iterator
&
jt
)
{
if
(
it
.
m_pData
->
type
!=
jt
.
m_pData
->
type
)
return
false
;
if
(
it
.
m_pData
->
type
==
IterPriv
::
IT_SEQ
)
return
it
.
m_pData
->
seqIter
==
jt
.
m_pData
->
seqIter
;
else
if
(
it
.
m_pData
->
type
==
IterPriv
::
IT_MAP
)
return
it
.
m_pData
->
mapIter
==
jt
.
m_pData
->
mapIter
;
return
true
;
}
bool
operator
!=
(
const
Iterator
&
it
,
const
Iterator
&
jt
)
{
return
!
(
it
==
jt
);
}
}
src/iterpriv.h
View file @
45322566
#pragma once
#include "ltnode.h"
#include <vector>
#include <map>
namespace
YAML
{
class
Node
;
// IterPriv
// . The implementation for iterators - essentially a union of sequence and map iterators.
struct
IterPriv
{
IterPriv
()
:
type
(
IT_NONE
)
{}
IterPriv
(
std
::
vector
<
Node
*>::
const_iterator
it
)
:
type
(
IT_SEQ
),
seqIter
(
it
)
{}
IterPriv
(
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
it
)
:
type
(
IT_MAP
),
mapIter
(
it
)
{}
enum
ITER_TYPE
{
IT_NONE
,
IT_SEQ
,
IT_MAP
};
ITER_TYPE
type
;
std
::
vector
<
Node
*>::
const_iterator
seqIter
;
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
mapIter
;
};
}
#pragma once
#include "ltnode.h"
#include <vector>
#include <map>
namespace
YAML
{
class
Node
;
// IterPriv
// . The implementation for iterators - essentially a union of sequence and map iterators.
struct
IterPriv
{
IterPriv
()
:
type
(
IT_NONE
)
{}
IterPriv
(
std
::
vector
<
Node
*>::
const_iterator
it
)
:
type
(
IT_SEQ
),
seqIter
(
it
)
{}
IterPriv
(
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
it
)
:
type
(
IT_MAP
),
mapIter
(
it
)
{}
enum
ITER_TYPE
{
IT_NONE
,
IT_SEQ
,
IT_MAP
};
ITER_TYPE
type
;
std
::
vector
<
Node
*>::
const_iterator
seqIter
;
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
mapIter
;
};
}
src/ltnode.h
View file @
45322566
#pragma once
namespace
YAML
{
class
Node
;
struct
ltnode
{
bool
operator
()(
const
Node
*
pNode1
,
const
Node
*
pNode2
)
const
;
};
}
#pragma once
namespace
YAML
{
class
Node
;
struct
ltnode
{
bool
operator
()(
const
Node
*
pNode1
,
const
Node
*
pNode2
)
const
;
};
}
src/map.cpp
View file @
45322566
#include "crt.h"
#include "map.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <iostream>
namespace
YAML
{
Map
::
Map
()
{
}
Map
::~
Map
()
{
Clear
();
}
void
Map
::
Clear
()
{
for
(
node_map
::
const_iterator
it
=
m_data
.
begin
();
it
!=
m_data
.
end
();
++
it
)
{
delete
it
->
first
;
delete
it
->
second
;
}
m_data
.
clear
();
}
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
*
,
ltnode
>::
const_iterator
&
it
)
const
{
it
=
m_data
.
end
();
return
true
;
}
void
Map
::
Parse
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Clear
();
// split based on start token
switch
(
pScanner
->
peek
().
type
)
{
case
TT_BLOCK_MAP_START
:
ParseBlock
(
pScanner
,
state
);
break
;
case
TT_FLOW_MAP_START
:
ParseFlow
(
pScanner
,
state
);
break
;
}
}
void
Map
::
ParseBlock
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
// eat start token
pScanner
->
pop
();
while
(
1
)
{
if
(
pScanner
->
empty
())
throw
ParserException
(
-
1
,
-
1
,
ErrorMsg
::
END_OF_MAP
);
Token
token
=
pScanner
->
peek
();
if
(
token
.
type
!=
TT_KEY
&&
token
.
type
!=
TT_BLOCK_END
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
END_OF_MAP
);
pScanner
->
pop
();
if
(
token
.
type
==
TT_BLOCK_END
)
break
;
Node
*
pKey
=
new
Node
;
Node
*
pValue
=
new
Node
;
try
{
// grab key
pKey
->
Parse
(
pScanner
,
state
);
// now grab value (optional)
if
(
!
pScanner
->
empty
()
&&
pScanner
->
peek
().
type
==
TT_VALUE
)
{
pScanner
->
pop
();
pValue
->
Parse
(
pScanner
,
state
);
}
m_data
[
pKey
]
=
pValue
;
}
catch
(
Exception
&
e
)
{
delete
pKey
;
delete
pValue
;
throw
e
;
}
}
}
void
Map
::
ParseFlow
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
// eat start token
pScanner
->
pop
();
while
(
1
)
{
if
(
pScanner
->
empty
())
throw
ParserException
(
-
1
,
-
1
,
ErrorMsg
::
END_OF_MAP_FLOW
);
Token
&
token
=
pScanner
->
peek
();
// first check for end
if
(
token
.
type
==
TT_FLOW_MAP_END
)
{
pScanner
->
pop
();
break
;
}
// now it better be a key
if
(
token
.
type
!=
TT_KEY
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
END_OF_MAP_FLOW
);
pScanner
->
pop
();
Node
*
pKey
=
new
Node
;
Node
*
pValue
=
new
Node
;
try
{
// grab key
pKey
->
Parse
(
pScanner
,
state
);
// now grab value (optional)
if
(
!
pScanner
->
empty
()
&&
pScanner
->
peek
().
type
==
TT_VALUE
)
{
pScanner
->
pop
();
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)
Token
&
nextToken
=
pScanner
->
peek
();
if
(
nextToken
.
type
==
TT_FLOW_ENTRY
)
pScanner
->
pop
();
else
if
(
nextToken
.
type
!=
TT_FLOW_MAP_END
)
throw
ParserException
(
nextToken
.
line
,
nextToken
.
column
,
ErrorMsg
::
END_OF_MAP_FLOW
);
m_data
[
pKey
]
=
pValue
;
}
catch
(
Exception
&
e
)
{
// clean up and rethrow
delete
pKey
;
delete
pValue
;
throw
e
;
}
}
}
void
Map
::
Write
(
std
::
ostream
&
out
,
int
indent
,
bool
startedLine
,
bool
onlyOneCharOnLine
)
{
if
(
startedLine
&&
!
onlyOneCharOnLine
)
out
<<
"
\n
"
;
for
(
node_map
::
const_iterator
it
=
m_data
.
begin
();
it
!=
m_data
.
end
();
++
it
)
{
if
((
startedLine
&&
!
onlyOneCharOnLine
)
||
it
!=
m_data
.
begin
())
{
for
(
int
i
=
0
;
i
<
indent
;
i
++
)
out
<<
" "
;
}
out
<<
"? "
;
it
->
first
->
Write
(
out
,
indent
+
1
,
true
,
it
!=
m_data
.
begin
()
||
!
startedLine
||
onlyOneCharOnLine
);
for
(
int
i
=
0
;
i
<
indent
;
i
++
)
out
<<
" "
;
out
<<
": "
;
it
->
second
->
Write
(
out
,
indent
+
1
,
true
,
true
);
}
if
(
m_data
.
empty
())
out
<<
"
\n
"
;
}
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
;
}
}
#include "crt.h"
#include "map.h"
#include "node.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <iostream>
namespace
YAML
{
Map
::
Map
()
{
}
Map
::~
Map
()
{
Clear
();
}
void
Map
::
Clear
()
{
for
(
node_map
::
const_iterator
it
=
m_data
.
begin
();
it
!=
m_data
.
end
();
++
it
)
{
delete
it
->
first
;
delete
it
->
second
;
}
m_data
.
clear
();
}
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
*
,
ltnode
>::
const_iterator
&
it
)
const
{
it
=
m_data
.
end
();
return
true
;
}
void
Map
::
Parse
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Clear
();
// split based on start token
switch
(
pScanner
->
peek
().
type
)
{
case
TT_BLOCK_MAP_START
:
ParseBlock
(
pScanner
,
state
);
break
;
case
TT_FLOW_MAP_START
:
ParseFlow
(
pScanner
,
state
);
break
;
}
}
void
Map
::
ParseBlock
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
// eat start token
pScanner
->
pop
();
while
(
1
)
{
if
(
pScanner
->
empty
())
throw
ParserException
(
-
1
,
-
1
,
ErrorMsg
::
END_OF_MAP
);
Token
token
=
pScanner
->
peek
();
if
(
token
.
type
!=
TT_KEY
&&
token
.
type
!=
TT_BLOCK_END
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
END_OF_MAP
);
pScanner
->
pop
();
if
(
token
.
type
==
TT_BLOCK_END
)
break
;
Node
*
pKey
=
new
Node
;
Node
*
pValue
=
new
Node
;
try
{
// grab key
pKey
->
Parse
(
pScanner
,
state
);
// now grab value (optional)
if
(
!
pScanner
->
empty
()
&&
pScanner
->
peek
().
type
==
TT_VALUE
)
{
pScanner
->
pop
();
pValue
->
Parse
(
pScanner
,
state
);
}
m_data
[
pKey
]
=
pValue
;
}
catch
(
Exception
&
e
)
{
delete
pKey
;
delete
pValue
;
throw
e
;
}
}
}
void
Map
::
ParseFlow
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
// eat start token
pScanner
->
pop
();
while
(
1
)
{
if
(
pScanner
->
empty
())
throw
ParserException
(
-
1
,
-
1
,
ErrorMsg
::
END_OF_MAP_FLOW
);
Token
&
token
=
pScanner
->
peek
();
// first check for end
if
(
token
.
type
==
TT_FLOW_MAP_END
)
{
pScanner
->
pop
();
break
;
}
// now it better be a key
if
(
token
.
type
!=
TT_KEY
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
END_OF_MAP_FLOW
);
pScanner
->
pop
();
Node
*
pKey
=
new
Node
;
Node
*
pValue
=
new
Node
;
try
{
// grab key
pKey
->
Parse
(
pScanner
,
state
);
// now grab value (optional)
if
(
!
pScanner
->
empty
()
&&
pScanner
->
peek
().
type
==
TT_VALUE
)
{
pScanner
->
pop
();
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)
Token
&
nextToken
=
pScanner
->
peek
();
if
(
nextToken
.
type
==
TT_FLOW_ENTRY
)
pScanner
->
pop
();
else
if
(
nextToken
.
type
!=
TT_FLOW_MAP_END
)
throw
ParserException
(
nextToken
.
line
,
nextToken
.
column
,
ErrorMsg
::
END_OF_MAP_FLOW
);
m_data
[
pKey
]
=
pValue
;
}
catch
(
Exception
&
e
)
{
// clean up and rethrow
delete
pKey
;
delete
pValue
;
throw
e
;
}
}
}
void
Map
::
Write
(
std
::
ostream
&
out
,
int
indent
,
bool
startedLine
,
bool
onlyOneCharOnLine
)
{
if
(
startedLine
&&
!
onlyOneCharOnLine
)
out
<<
"
\n
"
;
for
(
node_map
::
const_iterator
it
=
m_data
.
begin
();
it
!=
m_data
.
end
();
++
it
)
{
if
((
startedLine
&&
!
onlyOneCharOnLine
)
||
it
!=
m_data
.
begin
())
{
for
(
int
i
=
0
;
i
<
indent
;
i
++
)
out
<<
" "
;
}
out
<<
"? "
;
it
->
first
->
Write
(
out
,
indent
+
1
,
true
,
it
!=
m_data
.
begin
()
||
!
startedLine
||
onlyOneCharOnLine
);
for
(
int
i
=
0
;
i
<
indent
;
i
++
)
out
<<
" "
;
out
<<
": "
;
it
->
second
->
Write
(
out
,
indent
+
1
,
true
,
true
);
}
if
(
m_data
.
empty
())
out
<<
"
\n
"
;
}
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
;
}
}
src/map.h
View file @
45322566
#pragma once
#include "content.h"
#include <map>
namespace
YAML
{
class
Node
;
class
Map
:
public
Content
{
public:
Map
();
virtual
~
Map
();
void
Clear
();
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
);
virtual
bool
IsMap
()
const
{
return
true
;
}
// 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
*
,
ltnode
>
node_map
;
node_map
m_data
;
};
}
#pragma once
#include "content.h"
#include <map>
namespace
YAML
{
class
Node
;
class
Map
:
public
Content
{
public:
Map
();
virtual
~
Map
();
void
Clear
();
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
);
virtual
bool
IsMap
()
const
{
return
true
;
}
// 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
*
,
ltnode
>
node_map
;
node_map
m_data
;
};
}
src/node.cpp
View file @
45322566
#include "crt.h"
#include "node.h"
#include "token.h"
#include "scanner.h"
#include "content.h"
#include "parser.h"
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "iterpriv.h"
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
)
{
}
Node
::~
Node
()
{
Clear
();
}
void
Node
::
Clear
()
{
delete
m_pContent
;
m_pContent
=
0
;
m_alias
=
false
;
}
void
Node
::
Parse
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Clear
();
ParseHeader
(
pScanner
,
state
);
// is this an alias? if so, it can have no content
if
(
m_alias
)
return
;
// now split based on what kind of node we should be
switch
(
pScanner
->
peek
().
type
)
{
case
TT_SCALAR
:
m_pContent
=
new
Scalar
;
m_pContent
->
Parse
(
pScanner
,
state
);
break
;
case
TT_FLOW_SEQ_START
:
case
TT_BLOCK_SEQ_START
:
case
TT_BLOCK_ENTRY
:
m_pContent
=
new
Sequence
;
m_pContent
->
Parse
(
pScanner
,
state
);
break
;
case
TT_FLOW_MAP_START
:
case
TT_BLOCK_MAP_START
:
m_pContent
=
new
Map
;
m_pContent
->
Parse
(
pScanner
,
state
);
break
;
}
}
// ParseHeader
// . Grabs any tag, alias, or anchor tokens and deals with them.
void
Node
::
ParseHeader
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
while
(
1
)
{
if
(
pScanner
->
empty
())
return
;
switch
(
pScanner
->
peek
().
type
)
{
case
TT_TAG
:
ParseTag
(
pScanner
,
state
);
break
;
case
TT_ANCHOR
:
ParseAnchor
(
pScanner
,
state
);
break
;
case
TT_ALIAS
:
ParseAlias
(
pScanner
,
state
);
break
;
default:
return
;
}
}
}
void
Node
::
ParseTag
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Token
&
token
=
pScanner
->
peek
();
if
(
m_tag
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
MULTIPLE_TAGS
);
m_tag
=
state
.
TranslateTag
(
token
.
value
);
for
(
unsigned
i
=
0
;
i
<
token
.
params
.
size
();
i
++
)
m_tag
+=
token
.
params
[
i
];
pScanner
->
pop
();
}
void
Node
::
ParseAnchor
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Token
&
token
=
pScanner
->
peek
();
if
(
m_anchor
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
MULTIPLE_ANCHORS
);
m_anchor
=
token
.
value
;
m_alias
=
false
;
pScanner
->
pop
();
}
void
Node
::
ParseAlias
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Token
&
token
=
pScanner
->
peek
();
if
(
m_anchor
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
MULTIPLE_ALIASES
);
if
(
m_tag
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
ALIAS_CONTENT
);
m_anchor
=
token
.
value
;
m_alias
=
true
;
pScanner
->
pop
();
}
void
Node
::
Write
(
std
::
ostream
&
out
,
int
indent
,
bool
startedLine
,
bool
onlyOneCharOnLine
)
const
{
// write anchor/alias
if
(
m_anchor
!=
""
)
{
if
(
m_alias
)
out
<<
std
::
string
(
"*"
);
else
out
<<
std
::
string
(
"&"
);
out
<<
m_anchor
<<
std
::
string
(
" "
);
startedLine
=
true
;
onlyOneCharOnLine
=
false
;
}
// write tag
if
(
m_tag
!=
""
)
{
out
<<
std
::
string
(
"!<"
)
<<
m_tag
<<
std
::
string
(
"> "
);
startedLine
=
true
;
onlyOneCharOnLine
=
false
;
}
if
(
!
m_pContent
)
{
out
<<
std
::
string
(
"
\n
"
);
}
else
{
m_pContent
->
Write
(
out
,
indent
,
startedLine
,
onlyOneCharOnLine
);
}
}
CONTENT_TYPE
Node
::
GetType
()
const
{
if
(
!
m_pContent
)
return
CT_NONE
;
if
(
m_pContent
->
IsScalar
())
return
CT_SCALAR
;
else
if
(
m_pContent
->
IsSequence
())
return
CT_SEQUENCE
;
else
if
(
m_pContent
->
IsMap
())
return
CT_MAP
;
return
CT_NONE
;
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Iterator
Node
::
begin
()
const
{
if
(
!
m_pContent
)
return
Iterator
();
std
::
vector
<
Node
*>::
const_iterator
seqIter
;
if
(
m_pContent
->
GetBegin
(
seqIter
))
return
Iterator
(
new
IterPriv
(
seqIter
));
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
mapIter
;
if
(
m_pContent
->
GetBegin
(
mapIter
))
return
Iterator
(
new
IterPriv
(
mapIter
));
return
Iterator
();
}
// end
// . Returns an iterator to the end of this (sequence or map).
Iterator
Node
::
end
()
const
{
if
(
!
m_pContent
)
return
Iterator
();
std
::
vector
<
Node
*>::
const_iterator
seqIter
;
if
(
m_pContent
->
GetEnd
(
seqIter
))
return
Iterator
(
new
IterPriv
(
seqIter
));
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
mapIter
;
if
(
m_pContent
->
GetEnd
(
mapIter
))
return
Iterator
(
new
IterPriv
(
mapIter
));
return
Iterator
();
}
// size
// . Returns the size of this node, if it's a sequence node.
// . Otherwise, returns zero.
unsigned
Node
::
size
()
const
{
if
(
!
m_pContent
)
return
0
;
return
m_pContent
->
GetSize
();
}
const
Node
&
Node
::
operator
[]
(
unsigned
u
)
const
{
if
(
!
m_pContent
)
throw
BadDereference
();
Node
*
pNode
=
m_pContent
->
GetNode
(
u
);
if
(
pNode
)
return
*
pNode
;
return
GetValue
(
u
);
}
const
Node
&
Node
::
operator
[]
(
int
i
)
const
{
if
(
!
m_pContent
)
throw
BadDereference
();
Node
*
pNode
=
m_pContent
->
GetNode
(
i
);
if
(
pNode
)
return
*
pNode
;
return
GetValue
(
i
);
}
///////////////////////////////////////////////////////
// Extraction
void
operator
>>
(
const
Node
&
node
,
std
::
string
&
s
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
s
);
}
void
operator
>>
(
const
Node
&
node
,
int
&
i
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
i
);
}
void
operator
>>
(
const
Node
&
node
,
unsigned
&
u
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
u
);
}
void
operator
>>
(
const
Node
&
node
,
long
&
l
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
l
);
}
void
operator
>>
(
const
Node
&
node
,
float
&
f
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
f
);
}
void
operator
>>
(
const
Node
&
node
,
double
&
d
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
d
);
}
void
operator
>>
(
const
Node
&
node
,
char
&
c
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
c
);
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
Node
&
node
)
{
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
;
}
}
#include "crt.h"
#include "node.h"
#include "token.h"
#include "scanner.h"
#include "content.h"
#include "parser.h"
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "iterpriv.h"
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
)
{
}
Node
::~
Node
()
{
Clear
();
}
void
Node
::
Clear
()
{
delete
m_pContent
;
m_pContent
=
0
;
m_alias
=
false
;
}
void
Node
::
Parse
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Clear
();
ParseHeader
(
pScanner
,
state
);
// is this an alias? if so, it can have no content
if
(
m_alias
)
return
;
// now split based on what kind of node we should be
switch
(
pScanner
->
peek
().
type
)
{
case
TT_SCALAR
:
m_pContent
=
new
Scalar
;
m_pContent
->
Parse
(
pScanner
,
state
);
break
;
case
TT_FLOW_SEQ_START
:
case
TT_BLOCK_SEQ_START
:
case
TT_BLOCK_ENTRY
:
m_pContent
=
new
Sequence
;
m_pContent
->
Parse
(
pScanner
,
state
);
break
;
case
TT_FLOW_MAP_START
:
case
TT_BLOCK_MAP_START
:
m_pContent
=
new
Map
;
m_pContent
->
Parse
(
pScanner
,
state
);
break
;
}
}
// ParseHeader
// . Grabs any tag, alias, or anchor tokens and deals with them.
void
Node
::
ParseHeader
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
while
(
1
)
{
if
(
pScanner
->
empty
())
return
;
switch
(
pScanner
->
peek
().
type
)
{
case
TT_TAG
:
ParseTag
(
pScanner
,
state
);
break
;
case
TT_ANCHOR
:
ParseAnchor
(
pScanner
,
state
);
break
;
case
TT_ALIAS
:
ParseAlias
(
pScanner
,
state
);
break
;
default:
return
;
}
}
}
void
Node
::
ParseTag
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Token
&
token
=
pScanner
->
peek
();
if
(
m_tag
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
MULTIPLE_TAGS
);
m_tag
=
state
.
TranslateTag
(
token
.
value
);
for
(
unsigned
i
=
0
;
i
<
token
.
params
.
size
();
i
++
)
m_tag
+=
token
.
params
[
i
];
pScanner
->
pop
();
}
void
Node
::
ParseAnchor
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Token
&
token
=
pScanner
->
peek
();
if
(
m_anchor
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
MULTIPLE_ANCHORS
);
m_anchor
=
token
.
value
;
m_alias
=
false
;
pScanner
->
pop
();
}
void
Node
::
ParseAlias
(
Scanner
*
pScanner
,
const
ParserState
&
state
)
{
Token
&
token
=
pScanner
->
peek
();
if
(
m_anchor
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
MULTIPLE_ALIASES
);
if
(
m_tag
!=
""
)
throw
ParserException
(
token
.
line
,
token
.
column
,
ErrorMsg
::
ALIAS_CONTENT
);
m_anchor
=
token
.
value
;
m_alias
=
true
;
pScanner
->
pop
();
}
void
Node
::
Write
(
std
::
ostream
&
out
,
int
indent
,
bool
startedLine
,
bool
onlyOneCharOnLine
)
const
{
// write anchor/alias
if
(
m_anchor
!=
""
)
{
if
(
m_alias
)
out
<<
std
::
string
(
"*"
);
else
out
<<
std
::
string
(
"&"
);
out
<<
m_anchor
<<
std
::
string
(
" "
);
startedLine
=
true
;
onlyOneCharOnLine
=
false
;
}
// write tag
if
(
m_tag
!=
""
)
{
out
<<
std
::
string
(
"!<"
)
<<
m_tag
<<
std
::
string
(
"> "
);
startedLine
=
true
;
onlyOneCharOnLine
=
false
;
}
if
(
!
m_pContent
)
{
out
<<
std
::
string
(
"
\n
"
);
}
else
{
m_pContent
->
Write
(
out
,
indent
,
startedLine
,
onlyOneCharOnLine
);
}
}
CONTENT_TYPE
Node
::
GetType
()
const
{
if
(
!
m_pContent
)
return
CT_NONE
;
if
(
m_pContent
->
IsScalar
())
return
CT_SCALAR
;
else
if
(
m_pContent
->
IsSequence
())
return
CT_SEQUENCE
;
else
if
(
m_pContent
->
IsMap
())
return
CT_MAP
;
return
CT_NONE
;
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Iterator
Node
::
begin
()
const
{
if
(
!
m_pContent
)
return
Iterator
();
std
::
vector
<
Node
*>::
const_iterator
seqIter
;
if
(
m_pContent
->
GetBegin
(
seqIter
))
return
Iterator
(
new
IterPriv
(
seqIter
));
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
mapIter
;
if
(
m_pContent
->
GetBegin
(
mapIter
))
return
Iterator
(
new
IterPriv
(
mapIter
));
return
Iterator
();
}
// end
// . Returns an iterator to the end of this (sequence or map).
Iterator
Node
::
end
()
const
{
if
(
!
m_pContent
)
return
Iterator
();
std
::
vector
<
Node
*>::
const_iterator
seqIter
;
if
(
m_pContent
->
GetEnd
(
seqIter
))
return
Iterator
(
new
IterPriv
(
seqIter
));
std
::
map
<
Node
*
,
Node
*
,
ltnode
>::
const_iterator
mapIter
;
if
(
m_pContent
->
GetEnd
(
mapIter
))
return
Iterator
(
new
IterPriv
(
mapIter
));
return
Iterator
();
}
// size
// . Returns the size of this node, if it's a sequence node.
// . Otherwise, returns zero.
unsigned
Node
::
size
()
const
{
if
(
!
m_pContent
)
return
0
;
return
m_pContent
->
GetSize
();
}
const
Node
&
Node
::
operator
[]
(
unsigned
u
)
const
{
if
(
!
m_pContent
)
throw
BadDereference
();
Node
*
pNode
=
m_pContent
->
GetNode
(
u
);
if
(
pNode
)
return
*
pNode
;
return
GetValue
(
u
);
}
const
Node
&
Node
::
operator
[]
(
int
i
)
const
{
if
(
!
m_pContent
)
throw
BadDereference
();
Node
*
pNode
=
m_pContent
->
GetNode
(
i
);
if
(
pNode
)
return
*
pNode
;
return
GetValue
(
i
);
}
///////////////////////////////////////////////////////
// Extraction
void
operator
>>
(
const
Node
&
node
,
std
::
string
&
s
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
s
);
}
void
operator
>>
(
const
Node
&
node
,
int
&
i
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
i
);
}
void
operator
>>
(
const
Node
&
node
,
unsigned
&
u
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
u
);
}
void
operator
>>
(
const
Node
&
node
,
long
&
l
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
l
);
}
void
operator
>>
(
const
Node
&
node
,
float
&
f
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
f
);
}
void
operator
>>
(
const
Node
&
node
,
double
&
d
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
d
);
}
void
operator
>>
(
const
Node
&
node
,
char
&
c
)
{
if
(
!
node
.
m_pContent
)
throw
;
node
.
m_pContent
->
Read
(
c
);
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
Node
&
node
)
{
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
;
}
}
src/parser.cpp
View file @
45322566
#include "crt.h"
#include "parser.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <sstream>
namespace
YAML
{
Parser
::
Parser
(
std
::
istream
&
in
)
:
m_pScanner
(
0
)
{
Load
(
in
);
}
Parser
::~
Parser
()
{
delete
m_pScanner
;
}
Parser
::
operator
bool
()
const
{
return
!
m_pScanner
->
empty
();
}
void
Parser
::
Load
(
std
::
istream
&
in
)
{
delete
m_pScanner
;
m_pScanner
=
new
Scanner
(
in
);
m_state
.
Reset
();
}
// GetNextDocument
// . Reads the next document in the queue (of tokens).
// . Throws a ParserException on error.
void
Parser
::
GetNextDocument
(
Node
&
document
)
{
// clear node
document
.
Clear
();
// first read directives
ParseDirectives
();
// we better have some tokens in the queue
if
(
m_pScanner
->
empty
())
return
;
// first eat doc start (optional)
if
(
m_pScanner
->
peek
().
type
==
TT_DOC_START
)
m_pScanner
->
pop
();
// now parse our root node
document
.
Parse
(
m_pScanner
,
m_state
);
// and finally eat any doc ends we see
while
(
!
m_pScanner
->
empty
()
&&
m_pScanner
->
peek
().
type
==
TT_DOC_END
)
m_pScanner
->
pop
();
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void
Parser
::
ParseDirectives
()
{
bool
readDirective
=
false
;
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
Token
&
token
=
m_pScanner
->
peek
();
if
(
token
.
type
!=
TT_DIRECTIVE
)
break
;
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if
(
!
readDirective
)
m_state
.
Reset
();
readDirective
=
true
;
HandleDirective
(
&
token
);
m_pScanner
->
pop
();
}
}
void
Parser
::
HandleDirective
(
Token
*
pToken
)
{
if
(
pToken
->
value
==
"YAML"
)
HandleYamlDirective
(
pToken
);
else
if
(
pToken
->
value
==
"TAG"
)
HandleTagDirective
(
pToken
);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void
Parser
::
HandleYamlDirective
(
Token
*
pToken
)
{
if
(
pToken
->
params
.
size
()
!=
1
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
YAML_DIRECTIVE_ARGS
);
std
::
stringstream
str
(
pToken
->
params
[
0
]);
str
>>
m_state
.
version
.
major
;
str
.
get
();
str
>>
m_state
.
version
.
minor
;
if
(
!
str
||
str
.
peek
()
!=
EOF
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
YAML_VERSION
+
pToken
->
params
[
0
]);
if
(
m_state
.
version
.
major
>
1
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
YAML_MAJOR_VERSION
);
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void
Parser
::
HandleTagDirective
(
Token
*
pToken
)
{
if
(
pToken
->
params
.
size
()
!=
2
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
TAG_DIRECTIVE_ARGS
);
std
::
string
handle
=
pToken
->
params
[
0
],
prefix
=
pToken
->
params
[
1
];
m_state
.
tags
[
handle
]
=
prefix
;
}
void
Parser
::
PrintTokens
(
std
::
ostream
&
out
)
{
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
out
<<
m_pScanner
->
peek
()
<<
"
\n
"
;
m_pScanner
->
pop
();
}
}
}
#include "crt.h"
#include "parser.h"
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <sstream>
namespace
YAML
{
Parser
::
Parser
(
std
::
istream
&
in
)
:
m_pScanner
(
0
)
{
Load
(
in
);
}
Parser
::~
Parser
()
{
delete
m_pScanner
;
}
Parser
::
operator
bool
()
const
{
return
!
m_pScanner
->
empty
();
}
void
Parser
::
Load
(
std
::
istream
&
in
)
{
delete
m_pScanner
;
m_pScanner
=
new
Scanner
(
in
);
m_state
.
Reset
();
}
// GetNextDocument
// . Reads the next document in the queue (of tokens).
// . Throws a ParserException on error.
void
Parser
::
GetNextDocument
(
Node
&
document
)
{
// clear node
document
.
Clear
();
// first read directives
ParseDirectives
();
// we better have some tokens in the queue
if
(
m_pScanner
->
empty
())
return
;
// first eat doc start (optional)
if
(
m_pScanner
->
peek
().
type
==
TT_DOC_START
)
m_pScanner
->
pop
();
// now parse our root node
document
.
Parse
(
m_pScanner
,
m_state
);
// and finally eat any doc ends we see
while
(
!
m_pScanner
->
empty
()
&&
m_pScanner
->
peek
().
type
==
TT_DOC_END
)
m_pScanner
->
pop
();
}
// ParseDirectives
// . Reads any directives that are next in the queue.
void
Parser
::
ParseDirectives
()
{
bool
readDirective
=
false
;
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
Token
&
token
=
m_pScanner
->
peek
();
if
(
token
.
type
!=
TT_DIRECTIVE
)
break
;
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
if
(
!
readDirective
)
m_state
.
Reset
();
readDirective
=
true
;
HandleDirective
(
&
token
);
m_pScanner
->
pop
();
}
}
void
Parser
::
HandleDirective
(
Token
*
pToken
)
{
if
(
pToken
->
value
==
"YAML"
)
HandleYamlDirective
(
pToken
);
else
if
(
pToken
->
value
==
"TAG"
)
HandleTagDirective
(
pToken
);
}
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
void
Parser
::
HandleYamlDirective
(
Token
*
pToken
)
{
if
(
pToken
->
params
.
size
()
!=
1
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
YAML_DIRECTIVE_ARGS
);
std
::
stringstream
str
(
pToken
->
params
[
0
]);
str
>>
m_state
.
version
.
major
;
str
.
get
();
str
>>
m_state
.
version
.
minor
;
if
(
!
str
||
str
.
peek
()
!=
EOF
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
YAML_VERSION
+
pToken
->
params
[
0
]);
if
(
m_state
.
version
.
major
>
1
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
YAML_MAJOR_VERSION
);
// TODO: warning on major == 1, minor > 2?
}
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void
Parser
::
HandleTagDirective
(
Token
*
pToken
)
{
if
(
pToken
->
params
.
size
()
!=
2
)
throw
ParserException
(
pToken
->
line
,
pToken
->
column
,
ErrorMsg
::
TAG_DIRECTIVE_ARGS
);
std
::
string
handle
=
pToken
->
params
[
0
],
prefix
=
pToken
->
params
[
1
];
m_state
.
tags
[
handle
]
=
prefix
;
}
void
Parser
::
PrintTokens
(
std
::
ostream
&
out
)
{
while
(
1
)
{
if
(
m_pScanner
->
empty
())
break
;
out
<<
m_pScanner
->
peek
()
<<
"
\n
"
;
m_pScanner
->
pop
();
}
}
}
src/parserstate.cpp
View file @
45322566
#include "crt.h"
#include "parserstate.h"
namespace
YAML
{
void
ParserState
::
Reset
()
{
// version
version
.
major
=
1
;
version
.
minor
=
2
;
// and tags
tags
.
clear
();
tags
[
"!"
]
=
"!"
;
tags
[
"!!"
]
=
"tag:yaml.org,2002:"
;
}
std
::
string
ParserState
::
TranslateTag
(
const
std
::
string
&
handle
)
const
{
std
::
map
<
std
::
string
,
std
::
string
>::
const_iterator
it
=
tags
.
find
(
handle
);
if
(
it
==
tags
.
end
())
return
handle
;
return
it
->
second
;
}
}
#include "crt.h"
#include "parserstate.h"
namespace
YAML
{
void
ParserState
::
Reset
()
{
// version
version
.
major
=
1
;
version
.
minor
=
2
;
// and tags
tags
.
clear
();
tags
[
"!"
]
=
"!"
;
tags
[
"!!"
]
=
"tag:yaml.org,2002:"
;
}
std
::
string
ParserState
::
TranslateTag
(
const
std
::
string
&
handle
)
const
{
std
::
map
<
std
::
string
,
std
::
string
>::
const_iterator
it
=
tags
.
find
(
handle
);
if
(
it
==
tags
.
end
())
return
handle
;
return
it
->
second
;
}
}
src/regex.cpp
View file @
45322566
#include "crt.h"
#include "regex.h"
#include "stream.h"
#include <iostream>
namespace
YAML
{
RegEx
::
RegEx
(
REGEX_OP
op
)
:
m_op
(
op
),
m_pOp
(
0
)
{
SetOp
();
}
RegEx
::
RegEx
(
const
RegEx
&
rhs
)
:
m_pOp
(
0
)
{
m_op
=
rhs
.
m_op
;
m_a
=
rhs
.
m_a
;
m_z
=
rhs
.
m_z
;
m_params
=
rhs
.
m_params
;
SetOp
();
}
RegEx
::
RegEx
()
:
m_op
(
REGEX_EMPTY
),
m_pOp
(
0
)
{
SetOp
();
}
RegEx
::
RegEx
(
char
ch
)
:
m_op
(
REGEX_MATCH
),
m_pOp
(
0
),
m_a
(
ch
)
{
SetOp
();
}
RegEx
::
RegEx
(
char
a
,
char
z
)
:
m_op
(
REGEX_RANGE
),
m_pOp
(
0
),
m_a
(
a
),
m_z
(
z
)
{
SetOp
();
}
RegEx
::
RegEx
(
const
std
::
string
&
str
,
REGEX_OP
op
)
:
m_op
(
op
),
m_pOp
(
0
)
{
for
(
unsigned
i
=
0
;
i
<
str
.
size
();
i
++
)
m_params
.
push_back
(
RegEx
(
str
[
i
]));
SetOp
();
}
RegEx
::~
RegEx
()
{
delete
m_pOp
;
}
RegEx
&
RegEx
::
operator
=
(
const
RegEx
&
rhs
)
{
delete
m_pOp
;
m_pOp
=
0
;
m_op
=
rhs
.
m_op
;
m_a
=
rhs
.
m_a
;
m_z
=
rhs
.
m_z
;
m_params
=
rhs
.
m_params
;
SetOp
();
return
*
this
;
}
void
RegEx
::
SetOp
()
{
delete
m_pOp
;
m_pOp
=
0
;
switch
(
m_op
)
{
case
REGEX_MATCH
:
m_pOp
=
new
MatchOperator
;
break
;
case
REGEX_RANGE
:
m_pOp
=
new
RangeOperator
;
break
;
case
REGEX_OR
:
m_pOp
=
new
OrOperator
;
break
;
case
REGEX_AND
:
m_pOp
=
new
AndOperator
;
break
;
case
REGEX_NOT
:
m_pOp
=
new
NotOperator
;
break
;
case
REGEX_SEQ
:
m_pOp
=
new
SeqOperator
;
break
;
}
}
bool
RegEx
::
Matches
(
char
ch
)
const
{
std
::
string
str
;
str
+=
ch
;
return
Matches
(
str
);
}
bool
RegEx
::
Matches
(
const
std
::
string
&
str
)
const
{
return
Match
(
str
)
>=
0
;
}
bool
RegEx
::
Matches
(
std
::
istream
&
in
)
const
{
return
Match
(
in
)
>=
0
;
}
bool
RegEx
::
Matches
(
Stream
&
in
)
const
{
return
Match
(
in
)
>=
0
;
}
// Match
// . Matches the given string against this regular expression.
// . Returns the number of characters matched.
// . Returns -1 if no characters were matched (the reason for
// not returning zero is that we may have an empty regex
// which is ALWAYS successful at matching zero characters).
int
RegEx
::
Match
(
const
std
::
string
&
str
)
const
{
if
(
!
m_pOp
)
return
0
;
return
m_pOp
->
Match
(
str
,
*
this
);
}
// Match
int
RegEx
::
Match
(
Stream
&
in
)
const
{
return
Match
(
in
.
stream
());
}
// 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
(
std
::
istream
&
in
)
const
{
if
(
!
m_pOp
)
return
-
1
;
int
pos
=
in
.
tellg
();
int
ret
=
m_pOp
->
Match
(
in
,
*
this
);
// reset input stream!
in
.
clear
();
in
.
seekg
(
pos
);
return
ret
;
}
RegEx
operator
!
(
const
RegEx
&
ex
)
{
RegEx
ret
(
REGEX_NOT
);
ret
.
m_params
.
push_back
(
ex
);
return
ret
;
}
RegEx
operator
||
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_OR
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
RegEx
operator
&&
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_AND
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_SEQ
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
//////////////////////////////////////////////////////////////////////////////
// Operators
// MatchOperator
int
RegEx
::
MatchOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
if
(
str
.
empty
()
||
str
[
0
]
!=
regex
.
m_a
)
return
-
1
;
return
1
;
}
int
RegEx
::
MatchOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
if
(
!
in
||
in
.
peek
()
!=
regex
.
m_a
)
return
-
1
;
return
1
;
}
// RangeOperator
int
RegEx
::
RangeOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
if
(
str
.
empty
()
||
regex
.
m_a
>
str
[
0
]
||
regex
.
m_z
<
str
[
0
])
return
-
1
;
return
1
;
}
int
RegEx
::
RangeOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
if
(
!
in
||
regex
.
m_a
>
in
.
peek
()
||
regex
.
m_z
<
in
.
peek
())
return
-
1
;
return
1
;
}
// OrOperator
int
RegEx
::
OrOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
);
if
(
n
>=
0
)
return
n
;
}
return
-
1
;
}
int
RegEx
::
OrOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
>=
0
)
return
n
;
}
return
-
1
;
}
// AndOperator
// Note: 'AND' is a little funny, since we may be required to match things
// of different lengths. If we find a match, we return the length of
// the FIRST entry on the list.
int
RegEx
::
AndOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
int
first
=
-
1
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
);
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
int
RegEx
::
AndOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
int
first
=
-
1
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
// NotOperator
int
RegEx
::
NotOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
if
(
regex
.
m_params
.
empty
())
return
-
1
;
if
(
regex
.
m_params
[
0
].
Match
(
str
)
>=
0
)
return
-
1
;
return
1
;
}
int
RegEx
::
NotOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
if
(
regex
.
m_params
.
empty
())
return
-
1
;
if
(
regex
.
m_params
[
0
].
Match
(
in
)
>=
0
)
return
-
1
;
return
1
;
}
// SeqOperator
int
RegEx
::
SeqOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
int
offset
=
0
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
.
substr
(
offset
));
if
(
n
==
-
1
)
return
-
1
;
offset
+=
n
;
}
return
offset
;
}
int
RegEx
::
SeqOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
int
offset
=
0
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
==
-
1
)
return
-
1
;
offset
+=
n
;
in
.
ignore
(
n
);
}
return
offset
;
}
}
#include "crt.h"
#include "regex.h"
#include "stream.h"
#include <iostream>
namespace
YAML
{
RegEx
::
RegEx
(
REGEX_OP
op
)
:
m_op
(
op
),
m_pOp
(
0
)
{
SetOp
();
}
RegEx
::
RegEx
(
const
RegEx
&
rhs
)
:
m_pOp
(
0
)
{
m_op
=
rhs
.
m_op
;
m_a
=
rhs
.
m_a
;
m_z
=
rhs
.
m_z
;
m_params
=
rhs
.
m_params
;
SetOp
();
}
RegEx
::
RegEx
()
:
m_op
(
REGEX_EMPTY
),
m_pOp
(
0
)
{
SetOp
();
}
RegEx
::
RegEx
(
char
ch
)
:
m_op
(
REGEX_MATCH
),
m_pOp
(
0
),
m_a
(
ch
)
{
SetOp
();
}
RegEx
::
RegEx
(
char
a
,
char
z
)
:
m_op
(
REGEX_RANGE
),
m_pOp
(
0
),
m_a
(
a
),
m_z
(
z
)
{
SetOp
();
}
RegEx
::
RegEx
(
const
std
::
string
&
str
,
REGEX_OP
op
)
:
m_op
(
op
),
m_pOp
(
0
)
{
for
(
unsigned
i
=
0
;
i
<
str
.
size
();
i
++
)
m_params
.
push_back
(
RegEx
(
str
[
i
]));
SetOp
();
}
RegEx
::~
RegEx
()
{
delete
m_pOp
;
}
RegEx
&
RegEx
::
operator
=
(
const
RegEx
&
rhs
)
{
delete
m_pOp
;
m_pOp
=
0
;
m_op
=
rhs
.
m_op
;
m_a
=
rhs
.
m_a
;
m_z
=
rhs
.
m_z
;
m_params
=
rhs
.
m_params
;
SetOp
();
return
*
this
;
}
void
RegEx
::
SetOp
()
{
delete
m_pOp
;
m_pOp
=
0
;
switch
(
m_op
)
{
case
REGEX_MATCH
:
m_pOp
=
new
MatchOperator
;
break
;
case
REGEX_RANGE
:
m_pOp
=
new
RangeOperator
;
break
;
case
REGEX_OR
:
m_pOp
=
new
OrOperator
;
break
;
case
REGEX_AND
:
m_pOp
=
new
AndOperator
;
break
;
case
REGEX_NOT
:
m_pOp
=
new
NotOperator
;
break
;
case
REGEX_SEQ
:
m_pOp
=
new
SeqOperator
;
break
;
}
}
bool
RegEx
::
Matches
(
char
ch
)
const
{
std
::
string
str
;
str
+=
ch
;
return
Matches
(
str
);
}
bool
RegEx
::
Matches
(
const
std
::
string
&
str
)
const
{
return
Match
(
str
)
>=
0
;
}
bool
RegEx
::
Matches
(
std
::
istream
&
in
)
const
{
return
Match
(
in
)
>=
0
;
}
bool
RegEx
::
Matches
(
Stream
&
in
)
const
{
return
Match
(
in
)
>=
0
;
}
// Match
// . Matches the given string against this regular expression.
// . Returns the number of characters matched.
// . Returns -1 if no characters were matched (the reason for
// not returning zero is that we may have an empty regex
// which is ALWAYS successful at matching zero characters).
int
RegEx
::
Match
(
const
std
::
string
&
str
)
const
{
if
(
!
m_pOp
)
return
0
;
return
m_pOp
->
Match
(
str
,
*
this
);
}
// Match
int
RegEx
::
Match
(
Stream
&
in
)
const
{
return
Match
(
in
.
stream
());
}
// 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
(
std
::
istream
&
in
)
const
{
if
(
!
m_pOp
)
return
-
1
;
int
pos
=
in
.
tellg
();
int
ret
=
m_pOp
->
Match
(
in
,
*
this
);
// reset input stream!
in
.
clear
();
in
.
seekg
(
pos
);
return
ret
;
}
RegEx
operator
!
(
const
RegEx
&
ex
)
{
RegEx
ret
(
REGEX_NOT
);
ret
.
m_params
.
push_back
(
ex
);
return
ret
;
}
RegEx
operator
||
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_OR
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
RegEx
operator
&&
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_AND
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_SEQ
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
//////////////////////////////////////////////////////////////////////////////
// Operators
// MatchOperator
int
RegEx
::
MatchOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
if
(
str
.
empty
()
||
str
[
0
]
!=
regex
.
m_a
)
return
-
1
;
return
1
;
}
int
RegEx
::
MatchOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
if
(
!
in
||
in
.
peek
()
!=
regex
.
m_a
)
return
-
1
;
return
1
;
}
// RangeOperator
int
RegEx
::
RangeOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
if
(
str
.
empty
()
||
regex
.
m_a
>
str
[
0
]
||
regex
.
m_z
<
str
[
0
])
return
-
1
;
return
1
;
}
int
RegEx
::
RangeOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
if
(
!
in
||
regex
.
m_a
>
in
.
peek
()
||
regex
.
m_z
<
in
.
peek
())
return
-
1
;
return
1
;
}
// OrOperator
int
RegEx
::
OrOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
);
if
(
n
>=
0
)
return
n
;
}
return
-
1
;
}
int
RegEx
::
OrOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
>=
0
)
return
n
;
}
return
-
1
;
}
// AndOperator
// Note: 'AND' is a little funny, since we may be required to match things
// of different lengths. If we find a match, we return the length of
// the FIRST entry on the list.
int
RegEx
::
AndOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
int
first
=
-
1
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
);
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
int
RegEx
::
AndOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
int
first
=
-
1
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
// NotOperator
int
RegEx
::
NotOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
if
(
regex
.
m_params
.
empty
())
return
-
1
;
if
(
regex
.
m_params
[
0
].
Match
(
str
)
>=
0
)
return
-
1
;
return
1
;
}
int
RegEx
::
NotOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
if
(
regex
.
m_params
.
empty
())
return
-
1
;
if
(
regex
.
m_params
[
0
].
Match
(
in
)
>=
0
)
return
-
1
;
return
1
;
}
// SeqOperator
int
RegEx
::
SeqOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
int
offset
=
0
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
.
substr
(
offset
));
if
(
n
==
-
1
)
return
-
1
;
offset
+=
n
;
}
return
offset
;
}
int
RegEx
::
SeqOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
int
offset
=
0
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
==
-
1
)
return
-
1
;
offset
+=
n
;
in
.
ignore
(
n
);
}
return
offset
;
}
}
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment