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
9b4db068
Commit
9b4db068
authored
Mar 22, 2014
by
Jesse Beder
Browse files
Run clang-format
parent
e40ed4f9
Changes
78
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
2818 additions
and
2804 deletions
+2818
-2804
src/regex.cpp
src/regex.cpp
+41
-56
src/regex.h
src/regex.h
+65
-47
src/regeximpl.h
src/regeximpl.h
+176
-176
src/scanner.cpp
src/scanner.cpp
+364
-374
src/scanner.h
src/scanner.h
+125
-115
src/scanscalar.cpp
src/scanscalar.cpp
+211
-207
src/scanscalar.h
src/scanscalar.h
+60
-33
src/scantag.cpp
src/scantag.cpp
+72
-77
src/scantag.h
src/scantag.h
+8
-9
src/scantoken.cpp
src/scantoken.cpp
+422
-429
src/setting.h
src/setting.h
+87
-93
src/simplekey.cpp
src/simplekey.cpp
+121
-132
src/singledocparser.cpp
src/singledocparser.cpp
+390
-381
src/singledocparser.h
src/singledocparser.h
+48
-49
src/stream.cpp
src/stream.cpp
+432
-435
src/stream.h
src/stream.h
+59
-56
src/streamcharsource.h
src/streamcharsource.h
+37
-37
src/stringsource.h
src/stringsource.h
+38
-37
src/tag.cpp
src/tag.cpp
+40
-44
src/tag.h
src/tag.h
+22
-17
No files found.
src/regex.cpp
View file @
9b4db068
#include "regex.h"
namespace
YAML
{
// constructors
RegEx
::
RegEx
()
:
m_op
(
REGEX_EMPTY
)
{
}
RegEx
::
RegEx
(
REGEX_OP
op
)
:
m_op
(
op
)
{
}
RegEx
::
RegEx
(
char
ch
)
:
m_op
(
REGEX_MATCH
),
m_a
(
ch
)
{
}
RegEx
::
RegEx
(
char
a
,
char
z
)
:
m_op
(
REGEX_RANGE
),
m_a
(
a
),
m_z
(
z
)
{
}
RegEx
::
RegEx
(
const
std
::
string
&
str
,
REGEX_OP
op
)
:
m_op
(
op
)
{
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
namespace
YAML
{
// constructors
RegEx
::
RegEx
()
:
m_op
(
REGEX_EMPTY
)
{}
RegEx
::
RegEx
(
REGEX_OP
op
)
:
m_op
(
op
)
{}
RegEx
::
RegEx
(
char
ch
)
:
m_op
(
REGEX_MATCH
),
m_a
(
ch
)
{}
RegEx
::
RegEx
(
char
a
,
char
z
)
:
m_op
(
REGEX_RANGE
),
m_a
(
a
),
m_z
(
z
)
{}
RegEx
::
RegEx
(
const
std
::
string
&
str
,
REGEX_OP
op
)
:
m_op
(
op
)
{
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
m_params
.
push_back
(
RegEx
(
str
[
i
]));
}
}
// combination constructors
RegEx
operator
!
(
const
RegEx
&
ex
)
{
// combination constructors
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
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
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
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
;
}
}
}
src/regex.h
View file @
9b4db068
#ifndef REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEX_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <vector>
#include <string>
namespace
YAML
{
class
Stream
;
namespace
YAML
{
class
Stream
;
enum
REGEX_OP
{
REGEX_EMPTY
,
REGEX_MATCH
,
REGEX_RANGE
,
REGEX_OR
,
REGEX_AND
,
REGEX_NOT
,
REGEX_SEQ
};
enum
REGEX_OP
{
REGEX_EMPTY
,
REGEX_MATCH
,
REGEX_RANGE
,
REGEX_OR
,
REGEX_AND
,
REGEX_NOT
,
REGEX_SEQ
};
// simplified regular expressions
// . Only straightforward matches (no repeated characters)
// . Only matches from start of string
class
RegEx
{
// simplified regular expressions
// . Only straightforward matches (no repeated characters)
// . Only matches from start of string
class
RegEx
{
public:
RegEx
();
RegEx
(
char
ch
);
...
...
@@ -27,39 +34,50 @@ namespace YAML
RegEx
(
const
std
::
string
&
str
,
REGEX_OP
op
=
REGEX_SEQ
);
~
RegEx
()
{}
friend
RegEx
operator
!
(
const
RegEx
&
ex
);
friend
RegEx
operator
||
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
&&
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
!
(
const
RegEx
&
ex
);
friend
RegEx
operator
||
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
&&
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
bool
Matches
(
char
ch
)
const
;
bool
Matches
(
const
std
::
string
&
str
)
const
;
bool
Matches
(
const
Stream
&
in
)
const
;
template
<
typename
Source
>
bool
Matches
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
bool
Matches
(
const
Source
&
source
)
const
;
int
Match
(
const
std
::
string
&
str
)
const
;
int
Match
(
const
Stream
&
in
)
const
;
template
<
typename
Source
>
int
Match
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
Match
(
const
Source
&
source
)
const
;
private:
RegEx
(
REGEX_OP
op
);
template
<
typename
Source
>
bool
IsValidSource
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchUnchecked
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
bool
IsValidSource
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchUnchecked
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpEmpty
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpMatch
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpRange
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpOr
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpAnd
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpNot
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpSeq
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpEmpty
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpMatch
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpRange
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpOr
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpAnd
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpNot
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpSeq
(
const
Source
&
source
)
const
;
private:
REGEX_OP
m_op
;
char
m_a
,
m_z
;
std
::
vector
<
RegEx
>
m_params
;
};
std
::
vector
<
RegEx
>
m_params
;
};
}
#include "regeximpl.h"
...
...
src/regeximpl.h
View file @
9b4db068
#ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "stream.h"
#include "stringsource.h"
#include "streamcharsource.h"
namespace
YAML
{
// query matches
inline
bool
RegEx
::
Matches
(
char
ch
)
const
{
namespace
YAML
{
// query matches
inline
bool
RegEx
::
Matches
(
char
ch
)
const
{
std
::
string
str
;
str
+=
ch
;
return
Matches
(
str
);
}
}
inline
bool
RegEx
::
Matches
(
const
std
::
string
&
str
)
const
{
inline
bool
RegEx
::
Matches
(
const
std
::
string
&
str
)
const
{
return
Match
(
str
)
>=
0
;
}
}
inline
bool
RegEx
::
Matches
(
const
Stream
&
in
)
const
{
return
Match
(
in
)
>=
0
;
}
inline
bool
RegEx
::
Matches
(
const
Stream
&
in
)
const
{
return
Match
(
in
)
>=
0
;
}
template
<
typename
Source
>
inline
bool
RegEx
::
Matches
(
const
Source
&
source
)
const
{
template
<
typename
Source
>
inline
bool
RegEx
::
Matches
(
const
Source
&
source
)
const
{
return
Match
(
source
)
>=
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).
// . REMEMBER that we only match from the start of the buffer!
inline
int
RegEx
::
Match
(
const
std
::
string
&
str
)
const
{
// 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).
// . REMEMBER that we only match from the start of the buffer!
inline
int
RegEx
::
Match
(
const
std
::
string
&
str
)
const
{
StringCharSource
source
(
str
.
c_str
(),
str
.
size
());
return
Match
(
source
);
}
}
inline
int
RegEx
::
Match
(
const
Stream
&
in
)
const
{
inline
int
RegEx
::
Match
(
const
Stream
&
in
)
const
{
StreamCharSource
source
(
in
);
return
Match
(
source
);
}
}
template
<
typename
Source
>
inline
bool
RegEx
::
IsValidSource
(
const
Source
&
source
)
const
{
template
<
typename
Source
>
inline
bool
RegEx
::
IsValidSource
(
const
Source
&
source
)
const
{
return
source
;
}
}
template
<
>
inline
bool
RegEx
::
IsValidSource
<
StringCharSource
>
(
const
StringCharSource
&
source
)
const
{
switch
(
m_op
)
{
template
<
>
inline
bool
RegEx
::
IsValidSource
<
StringCharSource
>
(
const
StringCharSource
&
source
)
const
{
switch
(
m_op
)
{
case
REGEX_MATCH
:
case
REGEX_RANGE
:
return
source
;
default:
return
true
;
}
}
}
template
<
typename
Source
>
inline
int
RegEx
::
Match
(
const
Source
&
source
)
const
{
template
<
typename
Source
>
inline
int
RegEx
::
Match
(
const
Source
&
source
)
const
{
return
IsValidSource
(
source
)
?
MatchUnchecked
(
source
)
:
-
1
;
}
}
template
<
typename
Source
>
inline
int
RegEx
::
MatchUnchecked
(
const
Source
&
source
)
const
{
switch
(
m_op
)
{
template
<
typename
Source
>
inline
int
RegEx
::
MatchUnchecked
(
const
Source
&
source
)
const
{
switch
(
m_op
)
{
case
REGEX_EMPTY
:
return
MatchOpEmpty
(
source
);
case
REGEX_MATCH
:
...
...
@@ -96,91 +89,98 @@ namespace YAML
}
return
-
1
;
}
}
//////////////////////////////////////////////////////////////////////////////
// Operators
// Note: the convention MatchOp*<Source> is that we can assume IsSourceValid(source).
// So we do all our checks *before* we call these functions
//////////////////////////////////////////////////////////////////////////////
// Operators
// Note: the convention MatchOp*<Source> is that we can assume
// IsSourceValid(source).
// So we do all our checks *before* we call these functions
// EmptyOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpEmpty
(
const
Source
&
source
)
const
{
// EmptyOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpEmpty
(
const
Source
&
source
)
const
{
return
source
[
0
]
==
Stream
::
eof
()
?
0
:
-
1
;
}
}
template
<
>
inline
int
RegEx
::
MatchOpEmpty
<
StringCharSource
>
(
const
StringCharSource
&
source
)
const
{
return
!
source
?
0
:
-
1
;
// the empty regex only is successful on the empty string
}
template
<
>
inline
int
RegEx
::
MatchOpEmpty
<
StringCharSource
>
(
const
StringCharSource
&
source
)
const
{
return
!
source
?
0
:
-
1
;
// the empty regex only is successful on the empty string
}
// MatchOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpMatch
(
const
Source
&
source
)
const
{
if
(
source
[
0
]
!=
m_a
)
// MatchOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpMatch
(
const
Source
&
source
)
const
{
if
(
source
[
0
]
!=
m_a
)
return
-
1
;
return
1
;
}
}
// RangeOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpRange
(
const
Source
&
source
)
const
{
if
(
m_a
>
source
[
0
]
||
m_z
<
source
[
0
])
// RangeOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpRange
(
const
Source
&
source
)
const
{
if
(
m_a
>
source
[
0
]
||
m_z
<
source
[
0
])
return
-
1
;
return
1
;
}
}
// OrOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpOr
(
const
Source
&
source
)
const
{
for
(
std
::
size_t
i
=
0
;
i
<
m_params
.
size
();
i
++
)
{
// OrOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpOr
(
const
Source
&
source
)
const
{
for
(
std
::
size_t
i
=
0
;
i
<
m_params
.
size
();
i
++
)
{
int
n
=
m_params
[
i
].
MatchUnchecked
(
source
);
if
(
n
>=
0
)
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.
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpAnd
(
const
Source
&
source
)
const
{
// 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.
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpAnd
(
const
Source
&
source
)
const
{
int
first
=
-
1
;
for
(
std
::
size_t
i
=
0
;
i
<
m_params
.
size
();
i
++
)
{
for
(
std
::
size_t
i
=
0
;
i
<
m_params
.
size
();
i
++
)
{
int
n
=
m_params
[
i
].
MatchUnchecked
(
source
);
if
(
n
==
-
1
)
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
}
// NotOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpNot
(
const
Source
&
source
)
const
{
if
(
m_params
.
empty
())
// NotOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpNot
(
const
Source
&
source
)
const
{
if
(
m_params
.
empty
())
return
-
1
;
if
(
m_params
[
0
].
MatchUnchecked
(
source
)
>=
0
)
if
(
m_params
[
0
].
MatchUnchecked
(
source
)
>=
0
)
return
-
1
;
return
1
;
}
}
// SeqOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpSeq
(
const
Source
&
source
)
const
{
// SeqOperator
template
<
typename
Source
>
inline
int
RegEx
::
MatchOpSeq
(
const
Source
&
source
)
const
{
int
offset
=
0
;
for
(
std
::
size_t
i
=
0
;
i
<
m_params
.
size
();
i
++
)
{
int
n
=
m_params
[
i
].
Match
(
source
+
offset
);
// note Match, not MatchUnchecked because we need to check validity after the offset
if
(
n
==
-
1
)
for
(
std
::
size_t
i
=
0
;
i
<
m_params
.
size
();
i
++
)
{
int
n
=
m_params
[
i
].
Match
(
source
+
offset
);
// note Match, not
// MatchUnchecked because we
// need to check validity after
// the offset
if
(
n
==
-
1
)
return
-
1
;
offset
+=
n
;
}
return
offset
;
}
}
}
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scanner.cpp
View file @
9b4db068
...
...
@@ -5,40 +5,37 @@
#include <cassert>
#include <memory>
namespace
YAML
{
Scanner
::
Scanner
(
std
::
istream
&
in
)
:
INPUT
(
in
),
m_startedStream
(
false
),
m_endedStream
(
false
),
m_simpleKeyAllowed
(
false
),
m_canBeJSONFlow
(
false
)
{
}
Scanner
::~
Scanner
()
{
}
// empty
// . Returns true if there are no more tokens to be read
bool
Scanner
::
empty
()
{
namespace
YAML
{
Scanner
::
Scanner
(
std
::
istream
&
in
)
:
INPUT
(
in
),
m_startedStream
(
false
),
m_endedStream
(
false
),
m_simpleKeyAllowed
(
false
),
m_canBeJSONFlow
(
false
)
{}
Scanner
::~
Scanner
()
{}
// empty
// . Returns true if there are no more tokens to be read
bool
Scanner
::
empty
()
{
EnsureTokensInQueue
();
return
m_tokens
.
empty
();
}
}
// pop
// . Simply removes the next token on the queue.
void
Scanner
::
pop
()
{
// pop
// . Simply removes the next token on the queue.
void
Scanner
::
pop
()
{
EnsureTokensInQueue
();
if
(
!
m_tokens
.
empty
())
if
(
!
m_tokens
.
empty
())
m_tokens
.
pop
();
}
}
// peek
// . Returns (but does not remove) the next token on the queue.
Token
&
Scanner
::
peek
()
{
// peek
// . Returns (but does not remove) the next token on the queue.
Token
&
Scanner
::
peek
()
{
EnsureTokensInQueue
();
assert
(
!
m_tokens
.
empty
());
// should we be asserting here? I mean, we really just be checking
assert
(
!
m_tokens
.
empty
());
// should we be asserting here? I mean, we really
// just be checking
// if it's empty before peeking.
#if 0
...
...
@@ -49,30 +46,26 @@ namespace YAML
#endif
return
m_tokens
.
front
();
}
}
// mark
// . Returns the current mark in the stream
Mark
Scanner
::
mark
()
const
{
return
INPUT
.
mark
();
}
// mark
// . Returns the current mark in the stream
Mark
Scanner
::
mark
()
const
{
return
INPUT
.
mark
();
}
// 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
)
{
if
(
!
m_tokens
.
empty
())
{
// 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
)
{
if
(
!
m_tokens
.
empty
())
{
Token
&
token
=
m_tokens
.
front
();
// if this guy's valid, then we're done
if
(
token
.
status
==
Token
::
VALID
)
if
(
token
.
status
==
Token
::
VALID
)
return
;
// here's where we clean up the impossible tokens
if
(
token
.
status
==
Token
::
INVALID
)
{
if
(
token
.
status
==
Token
::
INVALID
)
{
m_tokens
.
pop
();
continue
;
}
...
...
@@ -81,23 +74,22 @@ namespace YAML
}
// no token? maybe we've actually finished
if
(
m_endedStream
)
if
(
m_endedStream
)
return
;
// no? then scan...
ScanNextToken
();
}
}
}
// ScanNextToken
// . The main scanning function; here we branch out and
// scan whatever the next token should be.
void
Scanner
::
ScanNextToken
()
{
if
(
m_endedStream
)
// ScanNextToken
// . The main scanning function; here we branch out and
// scan whatever the next token should be.
void
Scanner
::
ScanNextToken
()
{
if
(
m_endedStream
)
return
;
if
(
!
m_startedStream
)
if
(
!
m_startedStream
)
return
StartStream
();
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
...
...
@@ -111,83 +103,84 @@ namespace YAML
// *****
// end of stream
if
(
!
INPUT
)
if
(
!
INPUT
)
return
EndStream
();
if
(
INPUT
.
column
()
==
0
&&
INPUT
.
peek
()
==
Keys
::
Directive
)
if
(
INPUT
.
column
()
==
0
&&
INPUT
.
peek
()
==
Keys
::
Directive
)
return
ScanDirective
();
// document token
if
(
INPUT
.
column
()
==
0
&&
Exp
::
DocStart
().
Matches
(
INPUT
))
if
(
INPUT
.
column
()
==
0
&&
Exp
::
DocStart
().
Matches
(
INPUT
))
return
ScanDocStart
();
if
(
INPUT
.
column
()
==
0
&&
Exp
::
DocEnd
().
Matches
(
INPUT
))
if
(
INPUT
.
column
()
==
0
&&
Exp
::
DocEnd
().
Matches
(
INPUT
))
return
ScanDocEnd
();
// flow start/end/entry
if
(
INPUT
.
peek
()
==
Keys
::
FlowSeqStart
||
INPUT
.
peek
()
==
Keys
::
FlowMapStart
)
if
(
INPUT
.
peek
()
==
Keys
::
FlowSeqStart
||
INPUT
.
peek
()
==
Keys
::
FlowMapStart
)
return
ScanFlowStart
();
if
(
INPUT
.
peek
()
==
Keys
::
FlowSeqEnd
||
INPUT
.
peek
()
==
Keys
::
FlowMapEnd
)
if
(
INPUT
.
peek
()
==
Keys
::
FlowSeqEnd
||
INPUT
.
peek
()
==
Keys
::
FlowMapEnd
)
return
ScanFlowEnd
();
if
(
INPUT
.
peek
()
==
Keys
::
FlowEntry
)
if
(
INPUT
.
peek
()
==
Keys
::
FlowEntry
)
return
ScanFlowEntry
();
// block/map stuff
if
(
Exp
::
BlockEntry
().
Matches
(
INPUT
))
if
(
Exp
::
BlockEntry
().
Matches
(
INPUT
))
return
ScanBlockEntry
();
if
((
InBlockContext
()
?
Exp
::
Key
()
:
Exp
::
KeyInFlow
()).
Matches
(
INPUT
))
if
((
InBlockContext
()
?
Exp
::
Key
()
:
Exp
::
KeyInFlow
()).
Matches
(
INPUT
))
return
ScanKey
();
if
(
GetValueRegex
().
Matches
(
INPUT
))
if
(
GetValueRegex
().
Matches
(
INPUT
))
return
ScanValue
();
// alias/anchor
if
(
INPUT
.
peek
()
==
Keys
::
Alias
||
INPUT
.
peek
()
==
Keys
::
Anchor
)
if
(
INPUT
.
peek
()
==
Keys
::
Alias
||
INPUT
.
peek
()
==
Keys
::
Anchor
)
return
ScanAnchorOrAlias
();
// tag
if
(
INPUT
.
peek
()
==
Keys
::
Tag
)
if
(
INPUT
.
peek
()
==
Keys
::
Tag
)
return
ScanTag
();
// special scalars
if
(
InBlockContext
()
&&
(
INPUT
.
peek
()
==
Keys
::
LiteralScalar
||
INPUT
.
peek
()
==
Keys
::
FoldedScalar
))
if
(
InBlockContext
()
&&
(
INPUT
.
peek
()
==
Keys
::
LiteralScalar
||
INPUT
.
peek
()
==
Keys
::
FoldedScalar
))
return
ScanBlockScalar
();
if
(
INPUT
.
peek
()
==
'\''
||
INPUT
.
peek
()
==
'\"'
)
if
(
INPUT
.
peek
()
==
'\''
||
INPUT
.
peek
()
==
'\"'
)
return
ScanQuotedScalar
();
// plain scalars
if
((
InBlockContext
()
?
Exp
::
PlainScalar
()
:
Exp
::
PlainScalarInFlow
()).
Matches
(
INPUT
))
if
((
InBlockContext
()
?
Exp
::
PlainScalar
()
:
Exp
::
PlainScalarInFlow
())
.
Matches
(
INPUT
))
return
ScanPlainScalar
();
// don't know what it is!
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
UNKNOWN_TOKEN
);
}
}
// ScanToNextToken
// . Eats input until we reach the next token-like thing.
void
Scanner
::
ScanToNextToken
()
{
while
(
1
)
{
// ScanToNextToken
// . Eats input until we reach the next token-like thing.
void
Scanner
::
ScanToNextToken
()
{
while
(
1
)
{
// first eat whitespace
while
(
INPUT
&&
IsWhitespaceToBeEaten
(
INPUT
.
peek
()))
{
if
(
InBlockContext
()
&&
Exp
::
Tab
().
Matches
(
INPUT
))
while
(
INPUT
&&
IsWhitespaceToBeEaten
(
INPUT
.
peek
()))
{
if
(
InBlockContext
()
&&
Exp
::
Tab
().
Matches
(
INPUT
))
m_simpleKeyAllowed
=
false
;
INPUT
.
eat
(
1
);
}
// then eat a comment
if
(
Exp
::
Comment
().
Matches
(
INPUT
))
{
if
(
Exp
::
Comment
().
Matches
(
INPUT
))
{
// eat until line break
while
(
INPUT
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
INPUT
.
eat
(
1
);
}
// if it's NOT a line break, then we're done!
if
(
!
Exp
::
Break
().
Matches
(
INPUT
))
if
(
!
Exp
::
Break
().
Matches
(
INPUT
))
break
;
// otherwise, let's eat the line break and keep going
...
...
@@ -198,60 +191,57 @@ namespace YAML
InvalidateSimpleKey
();
// new line - we may be able to accept a simple key now
if
(
InBlockContext
())
if
(
InBlockContext
())
m_simpleKeyAllowed
=
true
;
}
}
}
///////////////////////////////////////////////////////////////////////
// Misc. helpers
// IsWhitespaceToBeEaten
// . We can eat whitespace if it's a space or tab
// . Note: originally tabs in block context couldn't be eaten
// "where a simple key could be allowed
// (i.e., not at the beginning of a line, or following '-', '?', or
':')"
//
I think this is wrong, since tabs can be non-content whitespace; it's just
//
that they can't contribute to indentation, so once you've seen a tab in a
//
line, you can't start a simple key
bool
Scanner
::
IsWhitespaceToBeEaten
(
char
ch
)
{
if
(
ch
==
' '
)
///////////////////////////////////////////////////////////////////////
// Misc. helpers
// IsWhitespaceToBeEaten
// . We can eat whitespace if it's a space or tab
// . Note: originally tabs in block context couldn't be eaten
// "where a simple key could be allowed
// (i.e., not at the beginning of a line, or following '-', '?', or
//
':')"
//
I think this is wrong, since tabs can be non-content whitespace; it's just
//
that they can't contribute to indentation, so once you've seen a tab in a
// line, you can't start a simple key
bool
Scanner
::
IsWhitespaceToBeEaten
(
char
ch
)
{
if
(
ch
==
' '
)
return
true
;
if
(
ch
==
'\t'
)
if
(
ch
==
'\t'
)
return
true
;
return
false
;
}
}
// GetValueRegex
// . Get the appropriate regex to check if it's a value token
const
RegEx
&
Scanner
::
GetValueRegex
()
const
{
if
(
InBlockContext
())
// GetValueRegex
// . Get the appropriate regex to check if it's a value token
const
RegEx
&
Scanner
::
GetValueRegex
()
const
{
if
(
InBlockContext
())
return
Exp
::
Value
();
return
m_canBeJSONFlow
?
Exp
::
ValueInJSONFlow
()
:
Exp
::
ValueInFlow
();
}
}
// StartStream
// . Set the initial conditions for starting a stream.
void
Scanner
::
StartStream
()
{
// StartStream
// . Set the initial conditions for starting a stream.
void
Scanner
::
StartStream
()
{
m_startedStream
=
true
;
m_simpleKeyAllowed
=
true
;
std
::
auto_ptr
<
IndentMarker
>
pIndent
(
new
IndentMarker
(
-
1
,
IndentMarker
::
NONE
));
m_indentRefs
.
push_back
(
pIndent
);
m_indents
.
push
(
&
m_indentRefs
.
back
());
}
}
// EndStream
// . Close out the stream, finish up, etc.
void
Scanner
::
EndStream
()
{
// EndStream
// . Close out the stream, finish up, etc.
void
Scanner
::
EndStream
()
{
// force newline
if
(
INPUT
.
column
()
>
0
)
if
(
INPUT
.
column
()
>
0
)
INPUT
.
ResetColumn
();
PopAllIndents
();
...
...
@@ -259,33 +249,35 @@ namespace YAML
m_simpleKeyAllowed
=
false
;
m_endedStream
=
true
;
}
}
Token
*
Scanner
::
PushToken
(
Token
::
TYPE
type
)
{
Token
*
Scanner
::
PushToken
(
Token
::
TYPE
type
)
{
m_tokens
.
push
(
Token
(
type
,
INPUT
.
mark
()));
return
&
m_tokens
.
back
();
}
}
Token
::
TYPE
Scanner
::
GetStartTokenFor
(
IndentMarker
::
INDENT_TYPE
type
)
const
{
switch
(
type
)
{
case
IndentMarker
::
SEQ
:
return
Token
::
BLOCK_SEQ_START
;
case
IndentMarker
::
MAP
:
return
Token
::
BLOCK_MAP_START
;
case
IndentMarker
::
NONE
:
assert
(
false
);
break
;
Token
::
TYPE
Scanner
::
GetStartTokenFor
(
IndentMarker
::
INDENT_TYPE
type
)
const
{
switch
(
type
)
{
case
IndentMarker
::
SEQ
:
return
Token
::
BLOCK_SEQ_START
;
case
IndentMarker
::
MAP
:
return
Token
::
BLOCK_MAP_START
;
case
IndentMarker
::
NONE
:
assert
(
false
);
break
;
}
assert
(
false
);
throw
std
::
runtime_error
(
"yaml-cpp: internal error, invalid indent type"
);
}
}
// PushIndentTo
// . Pushes an indentation onto the stack, and enqueues the
// proper token (sequence start or mapping start).
// . Returns the indent marker it generates (if any).
Scanner
::
IndentMarker
*
Scanner
::
PushIndentTo
(
int
column
,
IndentMarker
::
INDENT_TYPE
type
)
{
// PushIndentTo
// . Pushes an indentation onto the stack, and enqueues the
// proper token (sequence start or mapping start).
// . Returns the indent marker it generates (if any).
Scanner
::
IndentMarker
*
Scanner
::
PushIndentTo
(
int
column
,
IndentMarker
::
INDENT_TYPE
type
)
{
// are we in flow?
if
(
InFlowContext
())
if
(
InFlowContext
())
return
0
;
std
::
auto_ptr
<
IndentMarker
>
pIndent
(
new
IndentMarker
(
column
,
type
));
...
...
@@ -293,9 +285,11 @@ namespace YAML
const
IndentMarker
&
lastIndent
=
*
m_indents
.
top
();
// is this actually an indentation?
if
(
indent
.
column
<
lastIndent
.
column
)
if
(
indent
.
column
<
lastIndent
.
column
)
return
0
;
if
(
indent
.
column
==
lastIndent
.
column
&&
!
(
indent
.
type
==
IndentMarker
::
SEQ
&&
lastIndent
.
type
==
IndentMarker
::
MAP
))
if
(
indent
.
column
==
lastIndent
.
column
&&
!
(
indent
.
type
==
IndentMarker
::
SEQ
&&
lastIndent
.
type
==
IndentMarker
::
MAP
))
return
0
;
// push a start token
...
...
@@ -305,90 +299,86 @@ namespace YAML
m_indents
.
push
(
&
indent
);
m_indentRefs
.
push_back
(
pIndent
);
return
&
m_indentRefs
.
back
();
}
}
// PopIndentToHere
// . Pops indentations off the stack until we reach the current indentation
level,
//
and enqueues the proper token each time.
//
. T
he
n
pop
s all invalid indentations off
.
void
Scanner
::
PopIndentToHere
()
{
// PopIndentToHere
// . Pops indentations off the stack until we reach the current indentation
//
level,
//
and enqueues t
he p
r
op
er token each time
.
// . Then pops all invalid indentations off.
void
Scanner
::
PopIndentToHere
()
{
// are we in flow?
if
(
InFlowContext
())
if
(
InFlowContext
())
return
;
// now pop away
while
(
!
m_indents
.
empty
())
{
while
(
!
m_indents
.
empty
())
{
const
IndentMarker
&
indent
=
*
m_indents
.
top
();
if
(
indent
.
column
<
INPUT
.
column
())
if
(
indent
.
column
<
INPUT
.
column
())
break
;
if
(
indent
.
column
==
INPUT
.
column
()
&&
!
(
indent
.
type
==
IndentMarker
::
SEQ
&&
!
Exp
::
BlockEntry
().
Matches
(
INPUT
)))
if
(
indent
.
column
==
INPUT
.
column
()
&&
!
(
indent
.
type
==
IndentMarker
::
SEQ
&&
!
Exp
::
BlockEntry
().
Matches
(
INPUT
)))
break
;
PopIndent
();
}
while
(
!
m_indents
.
empty
()
&&
m_indents
.
top
()
->
status
==
IndentMarker
::
INVALID
)
while
(
!
m_indents
.
empty
()
&&
m_indents
.
top
()
->
status
==
IndentMarker
::
INVALID
)
PopIndent
();
}
}
// PopAllIndents
// . Pops all indentations (except for the base empty one) off the stack,
// and enqueues the proper token each time.
void
Scanner
::
PopAllIndents
()
{
// PopAllIndents
// . Pops all indentations (except for the base empty one) off the stack,
// and enqueues the proper token each time.
void
Scanner
::
PopAllIndents
()
{
// are we in flow?
if
(
InFlowContext
())
if
(
InFlowContext
())
return
;
// now pop away
while
(
!
m_indents
.
empty
())
{
while
(
!
m_indents
.
empty
())
{
const
IndentMarker
&
indent
=
*
m_indents
.
top
();
if
(
indent
.
type
==
IndentMarker
::
NONE
)
if
(
indent
.
type
==
IndentMarker
::
NONE
)
break
;
PopIndent
();
}
}
}
// PopIndent
// . Pops a single indent, pushing the proper token
void
Scanner
::
PopIndent
()
{
// PopIndent
// . Pops a single indent, pushing the proper token
void
Scanner
::
PopIndent
()
{
const
IndentMarker
&
indent
=
*
m_indents
.
top
();
m_indents
.
pop
();
if
(
indent
.
status
!=
IndentMarker
::
VALID
)
{
if
(
indent
.
status
!=
IndentMarker
::
VALID
)
{
InvalidateSimpleKey
();
return
;
}
if
(
indent
.
type
==
IndentMarker
::
SEQ
)
if
(
indent
.
type
==
IndentMarker
::
SEQ
)
m_tokens
.
push
(
Token
(
Token
::
BLOCK_SEQ_END
,
INPUT
.
mark
()));
else
if
(
indent
.
type
==
IndentMarker
::
MAP
)
else
if
(
indent
.
type
==
IndentMarker
::
MAP
)
m_tokens
.
push
(
Token
(
Token
::
BLOCK_MAP_END
,
INPUT
.
mark
()));
}
}
// GetTopIndent
int
Scanner
::
GetTopIndent
()
const
{
if
(
m_indents
.
empty
())
// GetTopIndent
int
Scanner
::
GetTopIndent
()
const
{
if
(
m_indents
.
empty
())
return
0
;
return
m_indents
.
top
()
->
column
;
}
}
// ThrowParserException
// . Throws a ParserException with the current token location
// (if available).
// . Does not parse any more tokens.
void
Scanner
::
ThrowParserException
(
const
std
::
string
&
msg
)
const
{
// ThrowParserException
// . Throws a ParserException with the current token location
// (if available).
// . Does not parse any more tokens.
void
Scanner
::
ThrowParserException
(
const
std
::
string
&
msg
)
const
{
Mark
mark
=
Mark
::
null_mark
();
if
(
!
m_tokens
.
empty
())
{
if
(
!
m_tokens
.
empty
())
{
const
Token
&
token
=
m_tokens
.
front
();
mark
=
token
.
mark
;
}
throw
ParserException
(
mark
,
msg
);
}
}
}
src/scanner.h
View file @
9b4db068
#ifndef SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <ios>
#include <string>
#include <queue>
...
...
@@ -16,28 +17,35 @@
#include "stream.h"
#include "token.h"
namespace
YAML
{
class
Node
;
class
RegEx
;
namespace
YAML
{
class
Node
;
class
RegEx
;
class
Scanner
{
class
Scanner
{
public:
Scanner
(
std
::
istream
&
in
);
Scanner
(
std
::
istream
&
in
);
~
Scanner
();
// token queue management (hopefully this looks kinda stl-ish)
bool
empty
();
void
pop
();
Token
&
peek
();
Token
&
peek
();
Mark
mark
()
const
;
private:
struct
IndentMarker
{
enum
INDENT_TYPE
{
MAP
,
SEQ
,
NONE
};
enum
STATUS
{
VALID
,
INVALID
,
UNKNOWN
};
IndentMarker
(
int
column_
,
INDENT_TYPE
type_
)
:
column
(
column_
),
type
(
type_
),
status
(
VALID
),
pStartToken
(
0
)
{}
enum
INDENT_TYPE
{
MAP
,
SEQ
,
NONE
};
enum
STATUS
{
VALID
,
INVALID
,
UNKNOWN
};
IndentMarker
(
int
column_
,
INDENT_TYPE
type_
)
:
column
(
column_
),
type
(
type_
),
status
(
VALID
),
pStartToken
(
0
)
{}
int
column
;
INDENT_TYPE
type
;
...
...
@@ -45,7 +53,10 @@ namespace YAML
Token
*
pStartToken
;
};
enum
FLOW_MARKER
{
FLOW_MAP
,
FLOW_SEQ
};
enum
FLOW_MARKER
{
FLOW_MAP
,
FLOW_SEQ
};
private:
// scanning
...
...
@@ -75,13 +86,13 @@ namespace YAML
bool
VerifySimpleKey
();
void
PopAllSimpleKeys
();
void
ThrowParserException
(
const
std
::
string
&
msg
)
const
;
void
ThrowParserException
(
const
std
::
string
&
msg
)
const
;
bool
IsWhitespaceToBeEaten
(
char
ch
);
const
RegEx
&
GetValueRegex
()
const
;
const
RegEx
&
GetValueRegex
()
const
;
struct
SimpleKey
{
SimpleKey
(
const
Mark
&
mark_
,
int
flowLevel_
);
SimpleKey
(
const
Mark
&
mark_
,
int
flowLevel_
);
void
Validate
();
void
Invalidate
();
...
...
@@ -126,8 +137,7 @@ namespace YAML
std
::
stack
<
IndentMarker
*>
m_indents
;
ptr_vector
<
IndentMarker
>
m_indentRefs
;
// for "garbage collection"
std
::
stack
<
FLOW_MARKER
>
m_flows
;
};
};
}
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scanscalar.cpp
View file @
9b4db068
...
...
@@ -4,20 +4,18 @@
#include "yaml-cpp/exceptions.h"
#include "token.h"
namespace
YAML
{
// ScanScalar
// . This is where the scalar magic happens.
//
// . We do the scanning in three phases:
// 1. Scan until newline
// 2. Eat newline
// 3. Scan leading blanks.
//
// . Depending on the parameters given, we store or stop
// and different places in the above flow.
std
::
string
ScanScalar
(
Stream
&
INPUT
,
ScanScalarParams
&
params
)
{
namespace
YAML
{
// ScanScalar
// . This is where the scalar magic happens.
//
// . We do the scanning in three phases:
// 1. Scan until newline
// 2. Eat newline
// 3. Scan leading blanks.
//
// . Depending on the parameters given, we store or stop
// and different places in the above flow.
std
::
string
ScanScalar
(
Stream
&
INPUT
,
ScanScalarParams
&
params
)
{
bool
foundNonEmptyLine
=
false
;
bool
pastOpeningBreak
=
(
params
.
fold
==
FOLD_FLOW
);
bool
emptyLine
=
false
,
moreIndented
=
false
;
...
...
@@ -27,21 +25,21 @@ namespace YAML
std
::
string
scalar
;
params
.
leadingSpaces
=
false
;
while
(
INPUT
)
{
while
(
INPUT
)
{
// ********************************
// Phase #1: scan until line ending
std
::
size_t
lastNonWhitespaceChar
=
scalar
.
size
();
bool
escapedNewline
=
false
;
while
(
!
params
.
end
.
Matches
(
INPUT
)
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
{
if
(
!
INPUT
)
while
(
!
params
.
end
.
Matches
(
INPUT
)
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
{
if
(
!
INPUT
)
break
;
// document indicator?
if
(
INPUT
.
column
()
==
0
&&
Exp
::
DocIndicator
().
Matches
(
INPUT
))
{
if
(
params
.
onDocIndicator
==
BREAK
)
if
(
INPUT
.
column
()
==
0
&&
Exp
::
DocIndicator
().
Matches
(
INPUT
))
{
if
(
params
.
onDocIndicator
==
BREAK
)
break
;
else
if
(
params
.
onDocIndicator
==
THROW
)
else
if
(
params
.
onDocIndicator
==
THROW
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
DOC_IN_SCALAR
);
}
...
...
@@ -49,7 +47,7 @@ namespace YAML
pastOpeningBreak
=
true
;
// escaped newline? (only if we're escaping on slash)
if
(
params
.
escape
==
'\\'
&&
Exp
::
EscBreak
().
Matches
(
INPUT
))
{
if
(
params
.
escape
==
'\\'
&&
Exp
::
EscBreak
().
Matches
(
INPUT
))
{
// eat escape character and get out (but preserve trailing whitespace!)
INPUT
.
get
();
lastNonWhitespaceChar
=
scalar
.
size
();
...
...
@@ -59,7 +57,7 @@ namespace YAML
}
// escape this?
if
(
INPUT
.
peek
()
==
params
.
escape
)
{
if
(
INPUT
.
peek
()
==
params
.
escape
)
{
scalar
+=
Exp
::
Escape
(
INPUT
);
lastNonWhitespaceChar
=
scalar
.
size
();
lastEscapedChar
=
scalar
.
size
();
...
...
@@ -69,31 +67,32 @@ namespace YAML
// otherwise, just add the damn character
char
ch
=
INPUT
.
get
();
scalar
+=
ch
;
if
(
ch
!=
' '
&&
ch
!=
'\t'
)
if
(
ch
!=
' '
&&
ch
!=
'\t'
)
lastNonWhitespaceChar
=
scalar
.
size
();
}
// eof? if we're looking to eat something, then we throw
if
(
!
INPUT
)
{
if
(
params
.
eatEnd
)
if
(
!
INPUT
)
{
if
(
params
.
eatEnd
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
EOF_IN_SCALAR
);
break
;
}
// doc indicator?
if
(
params
.
onDocIndicator
==
BREAK
&&
INPUT
.
column
()
==
0
&&
Exp
::
DocIndicator
().
Matches
(
INPUT
))
if
(
params
.
onDocIndicator
==
BREAK
&&
INPUT
.
column
()
==
0
&&
Exp
::
DocIndicator
().
Matches
(
INPUT
))
break
;
// are we done via character match?
int
n
=
params
.
end
.
Match
(
INPUT
);
if
(
n
>=
0
)
{
if
(
params
.
eatEnd
)
if
(
n
>=
0
)
{
if
(
params
.
eatEnd
)
INPUT
.
eat
(
n
);
break
;
}
// do we remove trailing whitespace?
if
(
params
.
fold
==
FOLD_FLOW
)
if
(
params
.
fold
==
FOLD_FLOW
)
scalar
.
erase
(
lastNonWhitespaceChar
);
// ********************************
...
...
@@ -105,20 +104,22 @@ namespace YAML
// Phase #3: scan initial spaces
// first the required indentation
while
(
INPUT
.
peek
()
==
' '
&&
(
INPUT
.
column
()
<
params
.
indent
||
(
params
.
detectIndent
&&
!
foundNonEmptyLine
)))
while
(
INPUT
.
peek
()
==
' '
&&
(
INPUT
.
column
()
<
params
.
indent
||
(
params
.
detectIndent
&&
!
foundNonEmptyLine
)))
INPUT
.
eat
(
1
);
// update indent if we're auto-detecting
if
(
params
.
detectIndent
&&
!
foundNonEmptyLine
)
if
(
params
.
detectIndent
&&
!
foundNonEmptyLine
)
params
.
indent
=
std
::
max
(
params
.
indent
,
INPUT
.
column
());
// and then the rest of the whitespace
while
(
Exp
::
Blank
().
Matches
(
INPUT
))
{
while
(
Exp
::
Blank
().
Matches
(
INPUT
))
{
// we check for tabs that masquerade as indentation
if
(
INPUT
.
peek
()
==
'\t'
&&
INPUT
.
column
()
<
params
.
indent
&&
params
.
onTabInIndentation
==
THROW
)
if
(
INPUT
.
peek
()
==
'\t'
&&
INPUT
.
column
()
<
params
.
indent
&&
params
.
onTabInIndentation
==
THROW
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
TAB_IN_INDENTATION
);
if
(
!
params
.
eatLeadingWhitespace
)
if
(
!
params
.
eatLeadingWhitespace
)
break
;
INPUT
.
eat
(
1
);
...
...
@@ -127,34 +128,37 @@ namespace YAML
// was this an empty line?
bool
nextEmptyLine
=
Exp
::
Break
().
Matches
(
INPUT
);
bool
nextMoreIndented
=
Exp
::
Blank
().
Matches
(
INPUT
);
if
(
params
.
fold
==
FOLD_BLOCK
&&
foldedNewlineCount
==
0
&&
nextEmptyLine
)
if
(
params
.
fold
==
FOLD_BLOCK
&&
foldedNewlineCount
==
0
&&
nextEmptyLine
)
foldedNewlineStartedMoreIndented
=
moreIndented
;
// for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
if
(
pastOpeningBreak
)
{
switch
(
params
.
fold
)
{
// for block scalars, we always start with a newline, so we should ignore it
// (not fold or keep)
if
(
pastOpeningBreak
)
{
switch
(
params
.
fold
)
{
case
DONT_FOLD
:
scalar
+=
"
\n
"
;
break
;
case
FOLD_BLOCK
:
if
(
!
emptyLine
&&
!
nextEmptyLine
&&
!
moreIndented
&&
!
nextMoreIndented
&&
INPUT
.
column
()
>=
params
.
indent
)
if
(
!
emptyLine
&&
!
nextEmptyLine
&&
!
moreIndented
&&
!
nextMoreIndented
&&
INPUT
.
column
()
>=
params
.
indent
)
scalar
+=
" "
;
else
if
(
nextEmptyLine
)
else
if
(
nextEmptyLine
)
foldedNewlineCount
++
;
else
scalar
+=
"
\n
"
;
if
(
!
nextEmptyLine
&&
foldedNewlineCount
>
0
)
{
if
(
!
nextEmptyLine
&&
foldedNewlineCount
>
0
)
{
scalar
+=
std
::
string
(
foldedNewlineCount
-
1
,
'\n'
);
if
(
foldedNewlineStartedMoreIndented
||
nextMoreIndented
|
!
foundNonEmptyLine
)
if
(
foldedNewlineStartedMoreIndented
||
nextMoreIndented
|
!
foundNonEmptyLine
)
scalar
+=
"
\n
"
;
foldedNewlineCount
=
0
;
}
break
;
case
FOLD_FLOW
:
if
(
nextEmptyLine
)
if
(
nextEmptyLine
)
scalar
+=
"
\n
"
;
else
if
(
!
emptyLine
&&
!
nextEmptyLine
&&
!
escapedNewline
)
else
if
(
!
emptyLine
&&
!
nextEmptyLine
&&
!
escapedNewline
)
scalar
+=
" "
;
break
;
}
...
...
@@ -165,44 +169,44 @@ namespace YAML
pastOpeningBreak
=
true
;
// are we done via indentation?
if
(
!
emptyLine
&&
INPUT
.
column
()
<
params
.
indent
)
{
if
(
!
emptyLine
&&
INPUT
.
column
()
<
params
.
indent
)
{
params
.
leadingSpaces
=
true
;
break
;
}
}
// post-processing
if
(
params
.
trimTrailingSpaces
)
{
if
(
params
.
trimTrailingSpaces
)
{
std
::
size_t
pos
=
scalar
.
find_last_not_of
(
' '
);
if
(
lastEscapedChar
!=
std
::
string
::
npos
)
{
if
(
pos
<
lastEscapedChar
||
pos
==
std
::
string
::
npos
)
if
(
lastEscapedChar
!=
std
::
string
::
npos
)
{
if
(
pos
<
lastEscapedChar
||
pos
==
std
::
string
::
npos
)
pos
=
lastEscapedChar
;
}
if
(
pos
<
scalar
.
size
())
if
(
pos
<
scalar
.
size
())
scalar
.
erase
(
pos
+
1
);
}
switch
(
params
.
chomp
)
{
switch
(
params
.
chomp
)
{
case
CLIP
:
{
std
::
size_t
pos
=
scalar
.
find_last_not_of
(
'\n'
);
if
(
lastEscapedChar
!=
std
::
string
::
npos
)
{
if
(
pos
<
lastEscapedChar
||
pos
==
std
::
string
::
npos
)
if
(
lastEscapedChar
!=
std
::
string
::
npos
)
{
if
(
pos
<
lastEscapedChar
||
pos
==
std
::
string
::
npos
)
pos
=
lastEscapedChar
;
}
if
(
pos
==
std
::
string
::
npos
)
if
(
pos
==
std
::
string
::
npos
)
scalar
.
erase
();
else
if
(
pos
+
1
<
scalar
.
size
())
else
if
(
pos
+
1
<
scalar
.
size
())
scalar
.
erase
(
pos
+
2
);
}
break
;
case
STRIP
:
{
std
::
size_t
pos
=
scalar
.
find_last_not_of
(
'\n'
);
if
(
lastEscapedChar
!=
std
::
string
::
npos
)
{
if
(
pos
<
lastEscapedChar
||
pos
==
std
::
string
::
npos
)
if
(
lastEscapedChar
!=
std
::
string
::
npos
)
{
if
(
pos
<
lastEscapedChar
||
pos
==
std
::
string
::
npos
)
pos
=
lastEscapedChar
;
}
if
(
pos
==
std
::
string
::
npos
)
if
(
pos
==
std
::
string
::
npos
)
scalar
.
erase
();
else
if
(
pos
<
scalar
.
size
())
else
if
(
pos
<
scalar
.
size
())
scalar
.
erase
(
pos
+
1
);
}
break
;
default:
...
...
@@ -210,5 +214,5 @@ namespace YAML
}
return
scalar
;
}
}
}
src/scanscalar.h
View file @
9b4db068
#ifndef SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
#include "regex.h"
#include "stream.h"
namespace
YAML
{
enum
CHOMP
{
STRIP
=
-
1
,
CLIP
,
KEEP
};
enum
ACTION
{
NONE
,
BREAK
,
THROW
};
enum
FOLD
{
DONT_FOLD
,
FOLD_BLOCK
,
FOLD_FLOW
};
namespace
YAML
{
enum
CHOMP
{
STRIP
=
-
1
,
CLIP
,
KEEP
};
enum
ACTION
{
NONE
,
BREAK
,
THROW
};
enum
FOLD
{
DONT_FOLD
,
FOLD_BLOCK
,
FOLD_FLOW
};
struct
ScanScalarParams
{
ScanScalarParams
()
:
eatEnd
(
false
),
indent
(
0
),
detectIndent
(
false
),
eatLeadingWhitespace
(
0
),
escape
(
0
),
fold
(
DONT_FOLD
),
trimTrailingSpaces
(
0
),
chomp
(
CLIP
),
onDocIndicator
(
NONE
),
onTabInIndentation
(
NONE
),
leadingSpaces
(
false
)
{}
struct
ScanScalarParams
{
ScanScalarParams
()
:
eatEnd
(
false
),
indent
(
0
),
detectIndent
(
false
),
eatLeadingWhitespace
(
0
),
escape
(
0
),
fold
(
DONT_FOLD
),
trimTrailingSpaces
(
0
),
chomp
(
CLIP
),
onDocIndicator
(
NONE
),
onTabInIndentation
(
NONE
),
leadingSpaces
(
false
)
{}
// input:
RegEx
end
;
// what condition ends this scalar?
bool
eatEnd
;
// should we eat that condition when we see it?
int
indent
;
// what level of indentation should be eaten and ignored?
bool
detectIndent
;
// should we try to autodetect the indent?
bool
eatLeadingWhitespace
;
// should we continue eating this delicious indentation after 'indent' spaces?
char
escape
;
// what character do we escape on (i.e., slash or single quote) (0 for none)
bool
eatLeadingWhitespace
;
// should we continue eating this delicious
// indentation after 'indent' spaces?
char
escape
;
// what character do we escape on (i.e., slash or single quote)
// (0 for none)
FOLD
fold
;
// how do we fold line ends?
bool
trimTrailingSpaces
;
// do we remove all trailing spaces (at the very end)
CHOMP
chomp
;
// do we strip, clip, or keep trailing newlines (at the very end)
// Note: strip means kill all, clip means keep at most one, keep means keep all
bool
trimTrailingSpaces
;
// do we remove all trailing spaces (at the very
// end)
CHOMP
chomp
;
// do we strip, clip, or keep trailing newlines (at the very
// end)
// Note: strip means kill all, clip means keep at most one, keep means keep
// all
ACTION
onDocIndicator
;
// what do we do if we see a document indicator?
ACTION
onTabInIndentation
;
// what do we do if we see a tab where we should be seeing indentation spaces
ACTION
onTabInIndentation
;
// what do we do if we see a tab where we should
// be seeing indentation spaces
// output:
bool
leadingSpaces
;
};
};
std
::
string
ScanScalar
(
Stream
&
INPUT
,
ScanScalarParams
&
info
);
std
::
string
ScanScalar
(
Stream
&
INPUT
,
ScanScalarParams
&
info
);
}
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scantag.cpp
View file @
9b4db068
...
...
@@ -3,82 +3,77 @@
#include "exp.h"
#include "yaml-cpp/exceptions.h"
namespace
YAML
{
const
std
::
string
ScanVerbatimTag
(
Stream
&
INPUT
)
{
namespace
YAML
{
const
std
::
string
ScanVerbatimTag
(
Stream
&
INPUT
)
{
std
::
string
tag
;
// eat the start character
INPUT
.
get
();
while
(
INPUT
)
{
if
(
INPUT
.
peek
()
==
Keys
::
VerbatimTagEnd
)
{
while
(
INPUT
)
{
if
(
INPUT
.
peek
()
==
Keys
::
VerbatimTagEnd
)
{
// eat the end character
INPUT
.
get
();
return
tag
;
}
int
n
=
Exp
::
URI
().
Match
(
INPUT
);
if
(
n
<=
0
)
if
(
n
<=
0
)
break
;
tag
+=
INPUT
.
get
(
n
);
}
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
END_OF_VERBATIM_TAG
);
}
}
const
std
::
string
ScanTagHandle
(
Stream
&
INPUT
,
bool
&
canBeHandle
)
{
const
std
::
string
ScanTagHandle
(
Stream
&
INPUT
,
bool
&
canBeHandle
)
{
std
::
string
tag
;
canBeHandle
=
true
;
Mark
firstNonWordChar
;
while
(
INPUT
)
{
if
(
INPUT
.
peek
()
==
Keys
::
Tag
)
{
if
(
!
canBeHandle
)
while
(
INPUT
)
{
if
(
INPUT
.
peek
()
==
Keys
::
Tag
)
{
if
(
!
canBeHandle
)
throw
ParserException
(
firstNonWordChar
,
ErrorMsg
::
CHAR_IN_TAG_HANDLE
);
break
;
}
int
n
=
0
;
if
(
canBeHandle
)
{
if
(
canBeHandle
)
{
n
=
Exp
::
Word
().
Match
(
INPUT
);
if
(
n
<=
0
)
{
if
(
n
<=
0
)
{
canBeHandle
=
false
;
firstNonWordChar
=
INPUT
.
mark
();
}
}
if
(
!
canBeHandle
)
if
(
!
canBeHandle
)
n
=
Exp
::
Tag
().
Match
(
INPUT
);
if
(
n
<=
0
)
if
(
n
<=
0
)
break
;
tag
+=
INPUT
.
get
(
n
);
}
return
tag
;
}
}
const
std
::
string
ScanTagSuffix
(
Stream
&
INPUT
)
{
const
std
::
string
ScanTagSuffix
(
Stream
&
INPUT
)
{
std
::
string
tag
;
while
(
INPUT
)
{
while
(
INPUT
)
{
int
n
=
Exp
::
Tag
().
Match
(
INPUT
);
if
(
n
<=
0
)
if
(
n
<=
0
)
break
;
tag
+=
INPUT
.
get
(
n
);
}
if
(
tag
.
empty
())
if
(
tag
.
empty
())
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
TAG_WITH_NO_SUFFIX
);
return
tag
;
}
}
}
src/scantag.h
View file @
9b4db068
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
#include "stream.h"
namespace
YAML
{
const
std
::
string
ScanVerbatimTag
(
Stream
&
INPUT
);
const
std
::
string
ScanTagHandle
(
Stream
&
INPUT
,
bool
&
canBeHandle
);
const
std
::
string
ScanTagSuffix
(
Stream
&
INPUT
);
namespace
YAML
{
const
std
::
string
ScanVerbatimTag
(
Stream
&
INPUT
);
const
std
::
string
ScanTagHandle
(
Stream
&
INPUT
,
bool
&
canBeHandle
);
const
std
::
string
ScanTagSuffix
(
Stream
&
INPUT
);
}
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scantoken.cpp
View file @
9b4db068
...
...
@@ -7,17 +7,15 @@
#include "tag.h"
#include <sstream>
namespace
YAML
{
///////////////////////////////////////////////////////////////////////
// Specialization for scanning specific tokens
// Directive
// . Note: no semantic checking is done here (that's for the parser to do)
void
Scanner
::
ScanDirective
()
{
namespace
YAML
{
///////////////////////////////////////////////////////////////////////
// Specialization for scanning specific tokens
// Directive
// . Note: no semantic checking is done here (that's for the parser to do)
void
Scanner
::
ScanDirective
()
{
std
::
string
name
;
std
::
vector
<
std
::
string
>
params
;
std
::
vector
<
std
::
string
>
params
;
// pop indents and simple keys
PopAllIndents
();
...
...
@@ -31,33 +29,32 @@ namespace YAML
INPUT
.
eat
(
1
);
// read name
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
().
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
().
Matches
(
INPUT
))
token
.
value
+=
INPUT
.
get
();
// read parameters
while
(
1
)
{
while
(
1
)
{
// first get rid of whitespace
while
(
Exp
::
Blank
().
Matches
(
INPUT
))
while
(
Exp
::
Blank
().
Matches
(
INPUT
))
INPUT
.
eat
(
1
);
// break on newline or comment
if
(
!
INPUT
||
Exp
::
Break
().
Matches
(
INPUT
)
||
Exp
::
Comment
().
Matches
(
INPUT
))
if
(
!
INPUT
||
Exp
::
Break
().
Matches
(
INPUT
)
||
Exp
::
Comment
().
Matches
(
INPUT
))
break
;
// now read parameter
std
::
string
param
;
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
().
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
().
Matches
(
INPUT
))
param
+=
INPUT
.
get
();
token
.
params
.
push_back
(
param
);
}
m_tokens
.
push
(
token
);
}
}
// DocStart
void
Scanner
::
ScanDocStart
()
{
// DocStart
void
Scanner
::
ScanDocStart
()
{
PopAllIndents
();
PopAllSimpleKeys
();
m_simpleKeyAllowed
=
false
;
...
...
@@ -67,11 +64,10 @@ namespace YAML
Mark
mark
=
INPUT
.
mark
();
INPUT
.
eat
(
3
);
m_tokens
.
push
(
Token
(
Token
::
DOC_START
,
mark
));
}
}
// DocEnd
void
Scanner
::
ScanDocEnd
()
{
// DocEnd
void
Scanner
::
ScanDocEnd
()
{
PopAllIndents
();
PopAllSimpleKeys
();
m_simpleKeyAllowed
=
false
;
...
...
@@ -81,11 +77,10 @@ namespace YAML
Mark
mark
=
INPUT
.
mark
();
INPUT
.
eat
(
3
);
m_tokens
.
push
(
Token
(
Token
::
DOC_END
,
mark
));
}
}
// FlowStart
void
Scanner
::
ScanFlowStart
()
{
// FlowStart
void
Scanner
::
ScanFlowStart
()
{
// flows can be simple keys
InsertPotentialSimpleKey
();
m_simpleKeyAllowed
=
true
;
...
...
@@ -96,21 +91,21 @@ namespace YAML
char
ch
=
INPUT
.
get
();
FLOW_MARKER
flowType
=
(
ch
==
Keys
::
FlowSeqStart
?
FLOW_SEQ
:
FLOW_MAP
);
m_flows
.
push
(
flowType
);
Token
::
TYPE
type
=
(
flowType
==
FLOW_SEQ
?
Token
::
FLOW_SEQ_START
:
Token
::
FLOW_MAP_START
);
Token
::
TYPE
type
=
(
flowType
==
FLOW_SEQ
?
Token
::
FLOW_SEQ_START
:
Token
::
FLOW_MAP_START
);
m_tokens
.
push
(
Token
(
type
,
mark
));
}
}
// FlowEnd
void
Scanner
::
ScanFlowEnd
()
{
if
(
InBlockContext
())
// FlowEnd
void
Scanner
::
ScanFlowEnd
()
{
if
(
InBlockContext
())
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
FLOW_END
);
// we might have a solo entry in the flow context
if
(
InFlowContext
())
{
if
(
m_flows
.
top
()
==
FLOW_MAP
&&
VerifySimpleKey
())
if
(
InFlowContext
())
{
if
(
m_flows
.
top
()
==
FLOW_MAP
&&
VerifySimpleKey
())
m_tokens
.
push
(
Token
(
Token
::
VALUE
,
INPUT
.
mark
()));
else
if
(
m_flows
.
top
()
==
FLOW_SEQ
)
else
if
(
m_flows
.
top
()
==
FLOW_SEQ
)
InvalidateSimpleKey
();
}
...
...
@@ -123,22 +118,21 @@ namespace YAML
// check that it matches the start
FLOW_MARKER
flowType
=
(
ch
==
Keys
::
FlowSeqEnd
?
FLOW_SEQ
:
FLOW_MAP
);
if
(
m_flows
.
top
()
!=
flowType
)
if
(
m_flows
.
top
()
!=
flowType
)
throw
ParserException
(
mark
,
ErrorMsg
::
FLOW_END
);
m_flows
.
pop
();
Token
::
TYPE
type
=
(
flowType
?
Token
::
FLOW_SEQ_END
:
Token
::
FLOW_MAP_END
);
m_tokens
.
push
(
Token
(
type
,
mark
));
}
}
// FlowEntry
void
Scanner
::
ScanFlowEntry
()
{
// FlowEntry
void
Scanner
::
ScanFlowEntry
()
{
// we might have a solo entry in the flow context
if
(
InFlowContext
())
{
if
(
m_flows
.
top
()
==
FLOW_MAP
&&
VerifySimpleKey
())
if
(
InFlowContext
())
{
if
(
m_flows
.
top
()
==
FLOW_MAP
&&
VerifySimpleKey
())
m_tokens
.
push
(
Token
(
Token
::
VALUE
,
INPUT
.
mark
()));
else
if
(
m_flows
.
top
()
==
FLOW_SEQ
)
else
if
(
m_flows
.
top
()
==
FLOW_SEQ
)
InvalidateSimpleKey
();
}
...
...
@@ -149,17 +143,16 @@ namespace YAML
Mark
mark
=
INPUT
.
mark
();
INPUT
.
eat
(
1
);
m_tokens
.
push
(
Token
(
Token
::
FLOW_ENTRY
,
mark
));
}
}
// BlockEntry
void
Scanner
::
ScanBlockEntry
()
{
// BlockEntry
void
Scanner
::
ScanBlockEntry
()
{
// we better be in the block context!
if
(
InFlowContext
())
if
(
InFlowContext
())
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
BLOCK_ENTRY
);
// can we put it here?
if
(
!
m_simpleKeyAllowed
)
if
(
!
m_simpleKeyAllowed
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
BLOCK_ENTRY
);
PushIndentTo
(
INPUT
.
column
(),
IndentMarker
::
SEQ
);
...
...
@@ -170,14 +163,13 @@ namespace YAML
Mark
mark
=
INPUT
.
mark
();
INPUT
.
eat
(
1
);
m_tokens
.
push
(
Token
(
Token
::
BLOCK_ENTRY
,
mark
));
}
}
// Key
void
Scanner
::
ScanKey
()
{
// Key
void
Scanner
::
ScanKey
()
{
// handle keys diffently in the block context (and manage indents)
if
(
InBlockContext
())
{
if
(
!
m_simpleKeyAllowed
)
if
(
InBlockContext
())
{
if
(
!
m_simpleKeyAllowed
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
MAP_KEY
);
PushIndentTo
(
INPUT
.
column
(),
IndentMarker
::
MAP
);
...
...
@@ -190,22 +182,22 @@ namespace YAML
Mark
mark
=
INPUT
.
mark
();
INPUT
.
eat
(
1
);
m_tokens
.
push
(
Token
(
Token
::
KEY
,
mark
));
}
}
// Value
void
Scanner
::
ScanValue
()
{
// Value
void
Scanner
::
ScanValue
()
{
// and check that simple key
bool
isSimpleKey
=
VerifySimpleKey
();
m_canBeJSONFlow
=
false
;
if
(
isSimpleKey
)
{
// can't follow a simple key with another simple key (dunno why, though - it seems fine)
if
(
isSimpleKey
)
{
// can't follow a simple key with another simple key (dunno why, though - it
// seems fine)
m_simpleKeyAllowed
=
false
;
}
else
{
// handle values diffently in the block context (and manage indents)
if
(
InBlockContext
())
{
if
(
!
m_simpleKeyAllowed
)
if
(
InBlockContext
())
{
if
(
!
m_simpleKeyAllowed
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
MAP_VALUE
);
PushIndentTo
(
INPUT
.
column
(),
IndentMarker
::
MAP
);
...
...
@@ -219,11 +211,10 @@ namespace YAML
Mark
mark
=
INPUT
.
mark
();
INPUT
.
eat
(
1
);
m_tokens
.
push
(
Token
(
Token
::
VALUE
,
mark
));
}
}
// AnchorOrAlias
void
Scanner
::
ScanAnchorOrAlias
()
{
// AnchorOrAlias
void
Scanner
::
ScanAnchorOrAlias
()
{
bool
alias
;
std
::
string
name
;
...
...
@@ -238,26 +229,27 @@ namespace YAML
alias
=
(
indicator
==
Keys
::
Alias
);
// now eat the content
while
(
INPUT
&&
Exp
::
Anchor
().
Matches
(
INPUT
))
while
(
INPUT
&&
Exp
::
Anchor
().
Matches
(
INPUT
))
name
+=
INPUT
.
get
();
// we need to have read SOMETHING!
if
(
name
.
empty
())
throw
ParserException
(
INPUT
.
mark
(),
alias
?
ErrorMsg
::
ALIAS_NOT_FOUND
:
ErrorMsg
::
ANCHOR_NOT_FOUND
);
if
(
name
.
empty
())
throw
ParserException
(
INPUT
.
mark
(),
alias
?
ErrorMsg
::
ALIAS_NOT_FOUND
:
ErrorMsg
::
ANCHOR_NOT_FOUND
);
// and needs to end correctly
if
(
INPUT
&&
!
Exp
::
AnchorEnd
().
Matches
(
INPUT
))
throw
ParserException
(
INPUT
.
mark
(),
alias
?
ErrorMsg
::
CHAR_IN_ALIAS
:
ErrorMsg
::
CHAR_IN_ANCHOR
);
if
(
INPUT
&&
!
Exp
::
AnchorEnd
().
Matches
(
INPUT
))
throw
ParserException
(
INPUT
.
mark
(),
alias
?
ErrorMsg
::
CHAR_IN_ALIAS
:
ErrorMsg
::
CHAR_IN_ANCHOR
);
// and we're done
Token
token
(
alias
?
Token
::
ALIAS
:
Token
::
ANCHOR
,
mark
);
token
.
value
=
name
;
m_tokens
.
push
(
token
);
}
}
// Tag
void
Scanner
::
ScanTag
()
{
// Tag
void
Scanner
::
ScanTag
()
{
// insert a potential simple key
InsertPotentialSimpleKey
();
m_simpleKeyAllowed
=
false
;
...
...
@@ -268,7 +260,7 @@ namespace YAML
// eat the indicator
INPUT
.
get
();
if
(
INPUT
&&
INPUT
.
peek
()
==
Keys
::
VerbatimTagStart
){
if
(
INPUT
&&
INPUT
.
peek
()
==
Keys
::
VerbatimTagStart
)
{
std
::
string
tag
=
ScanVerbatimTag
(
INPUT
);
token
.
value
=
tag
;
...
...
@@ -276,15 +268,15 @@ namespace YAML
}
else
{
bool
canBeHandle
;
token
.
value
=
ScanTagHandle
(
INPUT
,
canBeHandle
);
if
(
!
canBeHandle
&&
token
.
value
.
empty
())
if
(
!
canBeHandle
&&
token
.
value
.
empty
())
token
.
data
=
Tag
::
NON_SPECIFIC
;
else
if
(
token
.
value
.
empty
())
else
if
(
token
.
value
.
empty
())
token
.
data
=
Tag
::
SECONDARY_HANDLE
;
else
token
.
data
=
Tag
::
PRIMARY_HANDLE
;
// is there a suffix?
if
(
canBeHandle
&&
INPUT
.
peek
()
==
Keys
::
Tag
)
{
if
(
canBeHandle
&&
INPUT
.
peek
()
==
Keys
::
Tag
)
{
// eat the indicator
INPUT
.
get
();
token
.
params
.
push_back
(
ScanTagSuffix
(
INPUT
));
...
...
@@ -293,16 +285,16 @@ namespace YAML
}
m_tokens
.
push
(
token
);
}
}
// PlainScalar
void
Scanner
::
ScanPlainScalar
()
{
// PlainScalar
void
Scanner
::
ScanPlainScalar
()
{
std
::
string
scalar
;
// set up the scanning parameters
ScanScalarParams
params
;
params
.
end
=
(
InFlowContext
()
?
Exp
::
EndScalarInFlow
()
:
Exp
::
EndScalar
())
||
(
Exp
::
BlankOrBreak
()
+
Exp
::
Comment
());
params
.
end
=
(
InFlowContext
()
?
Exp
::
EndScalarInFlow
()
:
Exp
::
EndScalar
())
||
(
Exp
::
BlankOrBreak
()
+
Exp
::
Comment
());
params
.
eatEnd
=
false
;
params
.
indent
=
(
InFlowContext
()
?
0
:
GetTopIndent
()
+
1
);
params
.
fold
=
FOLD_FLOW
;
...
...
@@ -323,20 +315,20 @@ namespace YAML
m_canBeJSONFlow
=
false
;
// finally, check and see if we ended on an illegal character
//if(Exp::IllegalCharInScalar.Matches(INPUT))
//
if(Exp::IllegalCharInScalar.Matches(INPUT))
// throw ParserException(INPUT.mark(), ErrorMsg::CHAR_IN_SCALAR);
Token
token
(
Token
::
PLAIN_SCALAR
,
mark
);
token
.
value
=
scalar
;
m_tokens
.
push
(
token
);
}
}
// QuotedScalar
void
Scanner
::
ScanQuotedScalar
()
{
// QuotedScalar
void
Scanner
::
ScanQuotedScalar
()
{
std
::
string
scalar
;
// peek at single or double quote (don't eat because we need to preserve (for the time being) the input position)
// peek at single or double quote (don't eat because we need to preserve (for
// the time being) the input position)
char
quote
=
INPUT
.
peek
();
bool
single
=
(
quote
==
'\''
);
...
...
@@ -368,14 +360,14 @@ namespace YAML
Token
token
(
Token
::
NON_PLAIN_SCALAR
,
mark
);
token
.
value
=
scalar
;
m_tokens
.
push
(
token
);
}
}
// BlockScalarToken
// . These need a little extra processing beforehand.
// . We need to scan the line where the indicator is (this doesn't count as part
of the scalar),
//
and then we need to figure out what level of indentation we'll be using.
void
Scanner
::
ScanBlockScalar
()
{
// BlockScalarToken
// . These need a little extra processing beforehand.
// . We need to scan the line where the indicator is (this doesn't count as part
//
of the scalar),
// and then we need to figure out what level of indentation we'll be using.
void
Scanner
::
ScanBlockScalar
()
{
std
::
string
scalar
;
ScanScalarParams
params
;
...
...
@@ -390,14 +382,14 @@ namespace YAML
// eat chomping/indentation indicators
params
.
chomp
=
CLIP
;
int
n
=
Exp
::
Chomp
().
Match
(
INPUT
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
char
ch
=
INPUT
.
get
();
if
(
ch
==
'+'
)
if
(
ch
==
'+'
)
params
.
chomp
=
KEEP
;
else
if
(
ch
==
'-'
)
else
if
(
ch
==
'-'
)
params
.
chomp
=
STRIP
;
else
if
(
Exp
::
Digit
().
Matches
(
ch
))
{
if
(
ch
==
'0'
)
else
if
(
Exp
::
Digit
().
Matches
(
ch
))
{
if
(
ch
==
'0'
)
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
ZERO_INDENT_IN_BLOCK
);
params
.
indent
=
ch
-
'0'
;
...
...
@@ -406,20 +398,20 @@ namespace YAML
}
// now eat whitespace
while
(
Exp
::
Blank
().
Matches
(
INPUT
))
while
(
Exp
::
Blank
().
Matches
(
INPUT
))
INPUT
.
eat
(
1
);
// and comments to the end of the line
if
(
Exp
::
Comment
().
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
if
(
Exp
::
Comment
().
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
INPUT
.
eat
(
1
);
// if it's not a line break, then we ran into a bad character inline
if
(
INPUT
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
if
(
INPUT
&&
!
Exp
::
Break
().
Matches
(
INPUT
))
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
CHAR_IN_BLOCK
);
// set the initial indentation
if
(
GetTopIndent
()
>=
0
)
if
(
GetTopIndent
()
>=
0
)
params
.
indent
+=
GetTopIndent
();
params
.
eatLeadingWhitespace
=
false
;
...
...
@@ -428,12 +420,13 @@ namespace YAML
scalar
=
ScanScalar
(
INPUT
,
params
);
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
// simple keys always ok after block scalars (since we're gonna start a new
// line anyways)
m_simpleKeyAllowed
=
true
;
m_canBeJSONFlow
=
false
;
Token
token
(
Token
::
NON_PLAIN_SCALAR
,
mark
);
token
.
value
=
scalar
;
m_tokens
.
push
(
token
);
}
}
}
src/setting.h
View file @
9b4db068
#ifndef SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <memory>
#include <vector>
#include "yaml-cpp/noncopyable.h"
namespace
YAML
{
class
SettingChangeBase
;
namespace
YAML
{
class
SettingChangeBase
;
template
<
typename
T
>
class
Setting
{
template
<
typename
T
>
class
Setting
{
public:
Setting
()
:
m_value
()
{}
Setting
()
:
m_value
()
{}
const
T
get
()
const
{
return
m_value
;
}
std
::
auto_ptr
<
SettingChangeBase
>
set
(
const
T
&
value
);
void
restore
(
const
Setting
<
T
>&
oldSetting
)
{
m_value
=
oldSetting
.
get
();
}
std
::
auto_ptr
<
SettingChangeBase
>
set
(
const
T
&
value
);
void
restore
(
const
Setting
<
T
>&
oldSetting
)
{
m_value
=
oldSetting
.
get
();
}
private:
T
m_value
;
};
};
class
SettingChangeBase
{
class
SettingChangeBase
{
public:
virtual
~
SettingChangeBase
()
{}
virtual
void
pop
()
=
0
;
};
};
template
<
typename
T
>
class
SettingChange
:
public
SettingChangeBase
{
template
<
typename
T
>
class
SettingChange
:
public
SettingChangeBase
{
public:
SettingChange
(
Setting
<
T
>
*
pSetting
)
:
m_pCurSetting
(
pSetting
)
{
SettingChange
(
Setting
<
T
>*
pSetting
)
:
m_pCurSetting
(
pSetting
)
{
// copy old setting to save its state
m_oldSetting
=
*
pSetting
;
}
virtual
void
pop
()
{
m_pCurSetting
->
restore
(
m_oldSetting
);
}
virtual
void
pop
()
{
m_pCurSetting
->
restore
(
m_oldSetting
);
}
private:
Setting
<
T
>
*
m_pCurSetting
;
Setting
<
T
>*
m_pCurSetting
;
Setting
<
T
>
m_oldSetting
;
};
};
template
<
typename
T
>
inline
std
::
auto_ptr
<
SettingChangeBase
>
Setting
<
T
>::
set
(
const
T
&
value
)
{
std
::
auto_ptr
<
SettingChangeBase
>
pChange
(
new
SettingChange
<
T
>
(
this
));
template
<
typename
T
>
inline
std
::
auto_ptr
<
SettingChangeBase
>
Setting
<
T
>::
set
(
const
T
&
value
)
{
std
::
auto_ptr
<
SettingChangeBase
>
pChange
(
new
SettingChange
<
T
>
(
this
));
m_value
=
value
;
return
pChange
;
}
}
class
SettingChanges
:
private
noncopyable
{
class
SettingChanges
:
private
noncopyable
{
public:
SettingChanges
()
{}
~
SettingChanges
()
{
clear
();
}
...
...
@@ -71,23 +63,25 @@ namespace YAML
void
clear
()
{
restore
();
for
(
setting_changes
::
const_iterator
it
=
m_settingChanges
.
begin
();
it
!=
m_settingChanges
.
end
();
++
it
)
for
(
setting_changes
::
const_iterator
it
=
m_settingChanges
.
begin
();
it
!=
m_settingChanges
.
end
();
++
it
)
delete
*
it
;
m_settingChanges
.
clear
();
}
void
restore
()
{
for
(
setting_changes
::
const_iterator
it
=
m_settingChanges
.
begin
();
it
!=
m_settingChanges
.
end
();
++
it
)
for
(
setting_changes
::
const_iterator
it
=
m_settingChanges
.
begin
();
it
!=
m_settingChanges
.
end
();
++
it
)
(
*
it
)
->
pop
();
}
void
push
(
std
::
auto_ptr
<
SettingChangeBase
>
pSettingChange
)
{
void
push
(
std
::
auto_ptr
<
SettingChangeBase
>
pSettingChange
)
{
m_settingChanges
.
push_back
(
pSettingChange
.
release
());
}
// like std::auto_ptr - assignment is transfer of ownership
SettingChanges
&
operator
=
(
SettingChanges
&
rhs
)
{
if
(
this
==
&
rhs
)
SettingChanges
&
operator
=
(
SettingChanges
&
rhs
)
{
if
(
this
==
&
rhs
)
return
*
this
;
clear
();
...
...
@@ -97,9 +91,9 @@ namespace YAML
}
private:
typedef
std
::
vector
<
SettingChangeBase
*>
setting_changes
;
typedef
std
::
vector
<
SettingChangeBase
*>
setting_changes
;
setting_changes
m_settingChanges
;
};
};
}
#endif // SETTING_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/simplekey.cpp
View file @
9b4db068
...
...
@@ -3,71 +3,64 @@
#include "yaml-cpp/exceptions.h"
#include "exp.h"
namespace
YAML
{
Scanner
::
SimpleKey
::
SimpleKey
(
const
Mark
&
mark_
,
int
flowLevel_
)
:
mark
(
mark_
),
flowLevel
(
flowLevel_
),
pIndent
(
0
),
pMapStart
(
0
),
pKey
(
0
)
{
}
namespace
YAML
{
Scanner
::
SimpleKey
::
SimpleKey
(
const
Mark
&
mark_
,
int
flowLevel_
)
:
mark
(
mark_
),
flowLevel
(
flowLevel_
),
pIndent
(
0
),
pMapStart
(
0
),
pKey
(
0
)
{}
void
Scanner
::
SimpleKey
::
Validate
()
{
void
Scanner
::
SimpleKey
::
Validate
()
{
// Note: pIndent will *not* be garbage here;
// we "garbage collect" them so we can
// always refer to them
if
(
pIndent
)
if
(
pIndent
)
pIndent
->
status
=
IndentMarker
::
VALID
;
if
(
pMapStart
)
if
(
pMapStart
)
pMapStart
->
status
=
Token
::
VALID
;
if
(
pKey
)
if
(
pKey
)
pKey
->
status
=
Token
::
VALID
;
}
}
void
Scanner
::
SimpleKey
::
Invalidate
()
{
if
(
pIndent
)
void
Scanner
::
SimpleKey
::
Invalidate
()
{
if
(
pIndent
)
pIndent
->
status
=
IndentMarker
::
INVALID
;
if
(
pMapStart
)
if
(
pMapStart
)
pMapStart
->
status
=
Token
::
INVALID
;
if
(
pKey
)
if
(
pKey
)
pKey
->
status
=
Token
::
INVALID
;
}
}
// CanInsertPotentialSimpleKey
bool
Scanner
::
CanInsertPotentialSimpleKey
()
const
{
if
(
!
m_simpleKeyAllowed
)
// CanInsertPotentialSimpleKey
bool
Scanner
::
CanInsertPotentialSimpleKey
()
const
{
if
(
!
m_simpleKeyAllowed
)
return
false
;
return
!
ExistsActiveSimpleKey
();
}
}
// ExistsActiveSimpleKey
// . Returns true if there's a potential simple key at our flow level
// (there's allowed at most one per flow level, i.e., at the start of the flow
start token)
bool
Scanner
::
ExistsActiveSimpleKey
()
const
{
if
(
m_simpleKeys
.
empty
())
// ExistsActiveSimpleKey
// . Returns true if there's a potential simple key at our flow level
// (there's allowed at most one per flow level, i.e., at the start of the flow
// start token)
bool
Scanner
::
ExistsActiveSimpleKey
()
const
{
if
(
m_simpleKeys
.
empty
())
return
false
;
const
SimpleKey
&
key
=
m_simpleKeys
.
top
();
return
key
.
flowLevel
==
GetFlowLevel
();
}
}
// InsertPotentialSimpleKey
// . If we can, add a potential simple key to the queue,
// and save it on a stack.
void
Scanner
::
InsertPotentialSimpleKey
()
{
if
(
!
CanInsertPotentialSimpleKey
())
// InsertPotentialSimpleKey
// . If we can, add a potential simple key to the queue,
// and save it on a stack.
void
Scanner
::
InsertPotentialSimpleKey
()
{
if
(
!
CanInsertPotentialSimpleKey
())
return
;
SimpleKey
key
(
INPUT
.
mark
(),
GetFlowLevel
());
// first add a map start, if necessary
if
(
InBlockContext
())
{
if
(
InBlockContext
())
{
key
.
pIndent
=
PushIndentTo
(
INPUT
.
column
(),
IndentMarker
::
MAP
);
if
(
key
.
pIndent
)
{
if
(
key
.
pIndent
)
{
key
.
pIndent
->
status
=
IndentMarker
::
UNKNOWN
;
key
.
pMapStart
=
key
.
pIndent
->
pStartToken
;
key
.
pMapStart
->
status
=
Token
::
UNVERIFIED
;
...
...
@@ -80,37 +73,35 @@ namespace YAML
key
.
pKey
->
status
=
Token
::
UNVERIFIED
;
m_simpleKeys
.
push
(
key
);
}
}
// InvalidateSimpleKey
// . Automatically invalidate the simple key in our flow level
void
Scanner
::
InvalidateSimpleKey
()
{
if
(
m_simpleKeys
.
empty
())
// InvalidateSimpleKey
// . Automatically invalidate the simple key in our flow level
void
Scanner
::
InvalidateSimpleKey
()
{
if
(
m_simpleKeys
.
empty
())
return
;
// grab top key
SimpleKey
&
key
=
m_simpleKeys
.
top
();
if
(
key
.
flowLevel
!=
GetFlowLevel
())
if
(
key
.
flowLevel
!=
GetFlowLevel
())
return
;
key
.
Invalidate
();
m_simpleKeys
.
pop
();
}
}
// VerifySimpleKey
// . Determines whether the latest simple key to be added is valid,
// and if so, makes it valid.
bool
Scanner
::
VerifySimpleKey
()
{
if
(
m_simpleKeys
.
empty
())
// VerifySimpleKey
// . Determines whether the latest simple key to be added is valid,
// and if so, makes it valid.
bool
Scanner
::
VerifySimpleKey
()
{
if
(
m_simpleKeys
.
empty
())
return
false
;
// grab top key
SimpleKey
key
=
m_simpleKeys
.
top
();
// only validate if we're in the correct flow level
if
(
key
.
flowLevel
!=
GetFlowLevel
())
if
(
key
.
flowLevel
!=
GetFlowLevel
())
return
false
;
m_simpleKeys
.
pop
();
...
...
@@ -118,22 +109,20 @@ namespace YAML
bool
isValid
=
true
;
// needs to be less than 1024 characters and inline
if
(
INPUT
.
line
()
!=
key
.
mark
.
line
||
INPUT
.
pos
()
-
key
.
mark
.
pos
>
1024
)
if
(
INPUT
.
line
()
!=
key
.
mark
.
line
||
INPUT
.
pos
()
-
key
.
mark
.
pos
>
1024
)
isValid
=
false
;
// invalidate key
if
(
isValid
)
if
(
isValid
)
key
.
Validate
();
else
key
.
Invalidate
();
return
isValid
;
}
}
void
Scanner
::
PopAllSimpleKeys
()
{
while
(
!
m_simpleKeys
.
empty
())
void
Scanner
::
PopAllSimpleKeys
()
{
while
(
!
m_simpleKeys
.
empty
())
m_simpleKeys
.
pop
();
}
}
}
src/singledocparser.cpp
View file @
9b4db068
...
...
@@ -10,28 +10,26 @@
#include <cstdio>
#include <algorithm>
namespace
YAML
{
SingleDocParser
::
SingleDocParser
(
Scanner
&
scanner
,
const
Directives
&
directives
)
:
m_scanner
(
scanner
),
m_directives
(
directives
),
m_pCollectionStack
(
new
CollectionStack
),
m_curAnchor
(
0
)
{
}
SingleDocParser
::~
SingleDocParser
()
{
}
// HandleDocument
// . Handles the next document
// . Throws a ParserException on error.
void
SingleDocParser
::
HandleDocument
(
EventHandler
&
eventHandler
)
{
namespace
YAML
{
SingleDocParser
::
SingleDocParser
(
Scanner
&
scanner
,
const
Directives
&
directives
)
:
m_scanner
(
scanner
),
m_directives
(
directives
),
m_pCollectionStack
(
new
CollectionStack
),
m_curAnchor
(
0
)
{}
SingleDocParser
::~
SingleDocParser
()
{}
// HandleDocument
// . Handles the next document
// . Throws a ParserException on error.
void
SingleDocParser
::
HandleDocument
(
EventHandler
&
eventHandler
)
{
assert
(
!
m_scanner
.
empty
());
// guaranteed that there are tokens
assert
(
!
m_curAnchor
);
eventHandler
.
OnDocumentStart
(
m_scanner
.
peek
().
mark
);
// eat doc start
if
(
m_scanner
.
peek
().
type
==
Token
::
DOC_START
)
if
(
m_scanner
.
peek
().
type
==
Token
::
DOC_START
)
m_scanner
.
pop
();
// recurse!
...
...
@@ -40,14 +38,13 @@ namespace YAML
eventHandler
.
OnDocumentEnd
();
// and finally eat any doc ends we see
while
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
DOC_END
)
while
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
DOC_END
)
m_scanner
.
pop
();
}
}
void
SingleDocParser
::
HandleNode
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleNode
(
EventHandler
&
eventHandler
)
{
// an empty node *is* a possibility
if
(
m_scanner
.
empty
())
{
if
(
m_scanner
.
empty
())
{
eventHandler
.
OnNull
(
m_scanner
.
mark
(),
NullAnchor
);
return
;
}
...
...
@@ -56,7 +53,7 @@ namespace YAML
Mark
mark
=
m_scanner
.
peek
().
mark
;
// special case: a value node by itself must be a map, with no header
if
(
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
if
(
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
eventHandler
.
OnMapStart
(
mark
,
"?"
,
NullAnchor
);
HandleMap
(
eventHandler
);
eventHandler
.
OnMapEnd
();
...
...
@@ -64,7 +61,7 @@ namespace YAML
}
// special case: an alias node
if
(
m_scanner
.
peek
().
type
==
Token
::
ALIAS
)
{
if
(
m_scanner
.
peek
().
type
==
Token
::
ALIAS
)
{
eventHandler
.
OnAlias
(
mark
,
LookupAnchor
(
mark
,
m_scanner
.
peek
().
value
));
m_scanner
.
pop
();
return
;
...
...
@@ -76,18 +73,18 @@ namespace YAML
const
Token
&
token
=
m_scanner
.
peek
();
if
(
token
.
type
==
Token
::
PLAIN_SCALAR
&&
token
.
value
==
"null"
)
{
if
(
token
.
type
==
Token
::
PLAIN_SCALAR
&&
token
.
value
==
"null"
)
{
eventHandler
.
OnNull
(
mark
,
anchor
);
m_scanner
.
pop
();
return
;
}
// add non-specific tags
if
(
tag
.
empty
())
if
(
tag
.
empty
())
tag
=
(
token
.
type
==
Token
::
NON_PLAIN_SCALAR
?
"!"
:
"?"
);
// now split based on what kind of node we should be
switch
(
token
.
type
)
{
switch
(
token
.
type
)
{
case
Token
::
PLAIN_SCALAR
:
case
Token
::
NON_PLAIN_SCALAR
:
eventHandler
.
OnScalar
(
mark
,
tag
,
anchor
,
token
.
value
);
...
...
@@ -107,7 +104,8 @@ namespace YAML
return
;
case
Token
::
KEY
:
// compact maps can only go in a flow sequence
if
(
m_pCollectionStack
->
GetCurCollectionType
()
==
CollectionType
::
FlowSeq
)
{
if
(
m_pCollectionStack
->
GetCurCollectionType
()
==
CollectionType
::
FlowSeq
)
{
eventHandler
.
OnMapStart
(
mark
,
tag
,
anchor
);
HandleMap
(
eventHandler
);
eventHandler
.
OnMapEnd
();
...
...
@@ -118,44 +116,48 @@ namespace YAML
break
;
}
if
(
tag
==
"?"
)
if
(
tag
==
"?"
)
eventHandler
.
OnNull
(
mark
,
anchor
);
else
eventHandler
.
OnScalar
(
mark
,
tag
,
anchor
,
""
);
}
}
void
SingleDocParser
::
HandleSequence
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleSequence
(
EventHandler
&
eventHandler
)
{
// split based on start token
switch
(
m_scanner
.
peek
().
type
)
{
case
Token
::
BLOCK_SEQ_START
:
HandleBlockSequence
(
eventHandler
);
break
;
case
Token
::
FLOW_SEQ_START
:
HandleFlowSequence
(
eventHandler
);
break
;
default:
break
;
}
switch
(
m_scanner
.
peek
().
type
)
{
case
Token
::
BLOCK_SEQ_START
:
HandleBlockSequence
(
eventHandler
);
break
;
case
Token
::
FLOW_SEQ_START
:
HandleFlowSequence
(
eventHandler
);
break
;
default:
break
;
}
}
void
SingleDocParser
::
HandleBlockSequence
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleBlockSequence
(
EventHandler
&
eventHandler
)
{
// eat start token
m_scanner
.
pop
();
m_pCollectionStack
->
PushCollectionType
(
CollectionType
::
BlockSeq
);
while
(
1
)
{
if
(
m_scanner
.
empty
())
while
(
1
)
{
if
(
m_scanner
.
empty
())
throw
ParserException
(
m_scanner
.
mark
(),
ErrorMsg
::
END_OF_SEQ
);
Token
token
=
m_scanner
.
peek
();
if
(
token
.
type
!=
Token
::
BLOCK_ENTRY
&&
token
.
type
!=
Token
::
BLOCK_SEQ_END
)
if
(
token
.
type
!=
Token
::
BLOCK_ENTRY
&&
token
.
type
!=
Token
::
BLOCK_SEQ_END
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
END_OF_SEQ
);
m_scanner
.
pop
();
if
(
token
.
type
==
Token
::
BLOCK_SEQ_END
)
if
(
token
.
type
==
Token
::
BLOCK_SEQ_END
)
break
;
// check for null
if
(
!
m_scanner
.
empty
())
{
if
(
!
m_scanner
.
empty
())
{
const
Token
&
token
=
m_scanner
.
peek
();
if
(
token
.
type
==
Token
::
BLOCK_ENTRY
||
token
.
type
==
Token
::
BLOCK_SEQ_END
)
{
if
(
token
.
type
==
Token
::
BLOCK_ENTRY
||
token
.
type
==
Token
::
BLOCK_SEQ_END
)
{
eventHandler
.
OnNull
(
token
.
mark
,
NullAnchor
);
continue
;
}
...
...
@@ -165,20 +167,19 @@ namespace YAML
}
m_pCollectionStack
->
PopCollectionType
(
CollectionType
::
BlockSeq
);
}
}
void
SingleDocParser
::
HandleFlowSequence
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleFlowSequence
(
EventHandler
&
eventHandler
)
{
// eat start token
m_scanner
.
pop
();
m_pCollectionStack
->
PushCollectionType
(
CollectionType
::
FlowSeq
);
while
(
1
)
{
if
(
m_scanner
.
empty
())
while
(
1
)
{
if
(
m_scanner
.
empty
())
throw
ParserException
(
m_scanner
.
mark
(),
ErrorMsg
::
END_OF_SEQ_FLOW
);
// first check for end
if
(
m_scanner
.
peek
().
type
==
Token
::
FLOW_SEQ_END
)
{
if
(
m_scanner
.
peek
().
type
==
Token
::
FLOW_SEQ_END
)
{
m_scanner
.
pop
();
break
;
}
...
...
@@ -186,53 +187,62 @@ namespace YAML
// then read the node
HandleNode
(
eventHandler
);
if
(
m_scanner
.
empty
())
if
(
m_scanner
.
empty
())
throw
ParserException
(
m_scanner
.
mark
(),
ErrorMsg
::
END_OF_SEQ_FLOW
);
// 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
=
m_scanner
.
peek
();
if
(
token
.
type
==
Token
::
FLOW_ENTRY
)
if
(
token
.
type
==
Token
::
FLOW_ENTRY
)
m_scanner
.
pop
();
else
if
(
token
.
type
!=
Token
::
FLOW_SEQ_END
)
else
if
(
token
.
type
!=
Token
::
FLOW_SEQ_END
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
END_OF_SEQ_FLOW
);
}
m_pCollectionStack
->
PopCollectionType
(
CollectionType
::
FlowSeq
);
}
}
void
SingleDocParser
::
HandleMap
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleMap
(
EventHandler
&
eventHandler
)
{
// split based on start token
switch
(
m_scanner
.
peek
().
type
)
{
case
Token
::
BLOCK_MAP_START
:
HandleBlockMap
(
eventHandler
);
break
;
case
Token
::
FLOW_MAP_START
:
HandleFlowMap
(
eventHandler
);
break
;
case
Token
::
KEY
:
HandleCompactMap
(
eventHandler
);
break
;
case
Token
::
VALUE
:
HandleCompactMapWithNoKey
(
eventHandler
);
break
;
default:
break
;
}
switch
(
m_scanner
.
peek
().
type
)
{
case
Token
::
BLOCK_MAP_START
:
HandleBlockMap
(
eventHandler
);
break
;
case
Token
::
FLOW_MAP_START
:
HandleFlowMap
(
eventHandler
);
break
;
case
Token
::
KEY
:
HandleCompactMap
(
eventHandler
);
break
;
case
Token
::
VALUE
:
HandleCompactMapWithNoKey
(
eventHandler
);
break
;
default:
break
;
}
}
void
SingleDocParser
::
HandleBlockMap
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleBlockMap
(
EventHandler
&
eventHandler
)
{
// eat start token
m_scanner
.
pop
();
m_pCollectionStack
->
PushCollectionType
(
CollectionType
::
BlockMap
);
while
(
1
)
{
if
(
m_scanner
.
empty
())
while
(
1
)
{
if
(
m_scanner
.
empty
())
throw
ParserException
(
m_scanner
.
mark
(),
ErrorMsg
::
END_OF_MAP
);
Token
token
=
m_scanner
.
peek
();
if
(
token
.
type
!=
Token
::
KEY
&&
token
.
type
!=
Token
::
VALUE
&&
token
.
type
!=
Token
::
BLOCK_MAP_END
)
if
(
token
.
type
!=
Token
::
KEY
&&
token
.
type
!=
Token
::
VALUE
&&
token
.
type
!=
Token
::
BLOCK_MAP_END
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
END_OF_MAP
);
if
(
token
.
type
==
Token
::
BLOCK_MAP_END
)
{
if
(
token
.
type
==
Token
::
BLOCK_MAP_END
)
{
m_scanner
.
pop
();
break
;
}
// grab key (if non-null)
if
(
token
.
type
==
Token
::
KEY
)
{
if
(
token
.
type
==
Token
::
KEY
)
{
m_scanner
.
pop
();
HandleNode
(
eventHandler
);
}
else
{
...
...
@@ -240,7 +250,7 @@ namespace YAML
}
// now grab value (optional)
if
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
if
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
m_scanner
.
pop
();
HandleNode
(
eventHandler
);
}
else
{
...
...
@@ -249,28 +259,27 @@ namespace YAML
}
m_pCollectionStack
->
PopCollectionType
(
CollectionType
::
BlockMap
);
}
}
void
SingleDocParser
::
HandleFlowMap
(
EventHandler
&
eventHandler
)
{
void
SingleDocParser
::
HandleFlowMap
(
EventHandler
&
eventHandler
)
{
// eat start token
m_scanner
.
pop
();
m_pCollectionStack
->
PushCollectionType
(
CollectionType
::
FlowMap
);
while
(
1
)
{
if
(
m_scanner
.
empty
())
while
(
1
)
{
if
(
m_scanner
.
empty
())
throw
ParserException
(
m_scanner
.
mark
(),
ErrorMsg
::
END_OF_MAP_FLOW
);
Token
&
token
=
m_scanner
.
peek
();
const
Mark
mark
=
token
.
mark
;
// first check for end
if
(
token
.
type
==
Token
::
FLOW_MAP_END
)
{
if
(
token
.
type
==
Token
::
FLOW_MAP_END
)
{
m_scanner
.
pop
();
break
;
}
// grab key (if non-null)
if
(
token
.
type
==
Token
::
KEY
)
{
if
(
token
.
type
==
Token
::
KEY
)
{
m_scanner
.
pop
();
HandleNode
(
eventHandler
);
}
else
{
...
...
@@ -278,30 +287,30 @@ namespace YAML
}
// now grab value (optional)
if
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
if
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
m_scanner
.
pop
();
HandleNode
(
eventHandler
);
}
else
{
eventHandler
.
OnNull
(
mark
,
NullAnchor
);
}
if
(
m_scanner
.
empty
())
if
(
m_scanner
.
empty
())
throw
ParserException
(
m_scanner
.
mark
(),
ErrorMsg
::
END_OF_MAP_FLOW
);
// 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
=
m_scanner
.
peek
();
if
(
nextToken
.
type
==
Token
::
FLOW_ENTRY
)
if
(
nextToken
.
type
==
Token
::
FLOW_ENTRY
)
m_scanner
.
pop
();
else
if
(
nextToken
.
type
!=
Token
::
FLOW_MAP_END
)
else
if
(
nextToken
.
type
!=
Token
::
FLOW_MAP_END
)
throw
ParserException
(
nextToken
.
mark
,
ErrorMsg
::
END_OF_MAP_FLOW
);
}
m_pCollectionStack
->
PopCollectionType
(
CollectionType
::
FlowMap
);
}
}
// . Single "key: value" pair in a flow sequence
void
SingleDocParser
::
HandleCompactMap
(
EventHandler
&
eventHandler
)
{
// . Single "key: value" pair in a flow sequence
void
SingleDocParser
::
HandleCompactMap
(
EventHandler
&
eventHandler
)
{
m_pCollectionStack
->
PushCollectionType
(
CollectionType
::
CompactMap
);
// grab key
...
...
@@ -310,7 +319,7 @@ namespace YAML
HandleNode
(
eventHandler
);
// now grab value (optional)
if
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
if
(
!
m_scanner
.
empty
()
&&
m_scanner
.
peek
().
type
==
Token
::
VALUE
)
{
m_scanner
.
pop
();
HandleNode
(
eventHandler
);
}
else
{
...
...
@@ -318,11 +327,10 @@ namespace YAML
}
m_pCollectionStack
->
PopCollectionType
(
CollectionType
::
CompactMap
);
}
}
// . Single ": value" pair in a flow sequence
void
SingleDocParser
::
HandleCompactMapWithNoKey
(
EventHandler
&
eventHandler
)
{
// . Single ": value" pair in a flow sequence
void
SingleDocParser
::
HandleCompactMapWithNoKey
(
EventHandler
&
eventHandler
)
{
m_pCollectionStack
->
PushCollectionType
(
CollectionType
::
CompactMap
);
// null key
...
...
@@ -333,62 +341,63 @@ namespace YAML
HandleNode
(
eventHandler
);
m_pCollectionStack
->
PopCollectionType
(
CollectionType
::
CompactMap
);
}
}
// ParseProperties
// . Grabs any tag or anchor tokens and deals with them.
void
SingleDocParser
::
ParseProperties
(
std
::
string
&
tag
,
anchor_t
&
anchor
)
{
// ParseProperties
// . Grabs any tag or anchor tokens and deals with them.
void
SingleDocParser
::
ParseProperties
(
std
::
string
&
tag
,
anchor_t
&
anchor
)
{
tag
.
clear
();
anchor
=
NullAnchor
;
while
(
1
)
{
if
(
m_scanner
.
empty
())
while
(
1
)
{
if
(
m_scanner
.
empty
())
return
;
switch
(
m_scanner
.
peek
().
type
)
{
case
Token
::
TAG
:
ParseTag
(
tag
);
break
;
case
Token
::
ANCHOR
:
ParseAnchor
(
anchor
);
break
;
default:
return
;
}
switch
(
m_scanner
.
peek
().
type
)
{
case
Token
::
TAG
:
ParseTag
(
tag
);
break
;
case
Token
::
ANCHOR
:
ParseAnchor
(
anchor
);
break
;
default:
return
;
}
}
}
void
SingleDocParser
::
ParseTag
(
std
::
string
&
tag
)
{
void
SingleDocParser
::
ParseTag
(
std
::
string
&
tag
)
{
Token
&
token
=
m_scanner
.
peek
();
if
(
!
tag
.
empty
())
if
(
!
tag
.
empty
())
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
MULTIPLE_TAGS
);
Tag
tagInfo
(
token
);
tag
=
tagInfo
.
Translate
(
m_directives
);
m_scanner
.
pop
();
}
}
void
SingleDocParser
::
ParseAnchor
(
anchor_t
&
anchor
)
{
void
SingleDocParser
::
ParseAnchor
(
anchor_t
&
anchor
)
{
Token
&
token
=
m_scanner
.
peek
();
if
(
anchor
)
if
(
anchor
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
MULTIPLE_ANCHORS
);
anchor
=
RegisterAnchor
(
token
.
value
);
m_scanner
.
pop
();
}
}
anchor_t
SingleDocParser
::
RegisterAnchor
(
const
std
::
string
&
name
)
{
if
(
name
.
empty
())
anchor_t
SingleDocParser
::
RegisterAnchor
(
const
std
::
string
&
name
)
{
if
(
name
.
empty
())
return
NullAnchor
;
return
m_anchors
[
name
]
=
++
m_curAnchor
;
}
}
anchor_t
SingleDocParser
::
LookupAnchor
(
const
Mark
&
mark
,
const
std
::
string
&
name
)
const
{
anchor_t
SingleDocParser
::
LookupAnchor
(
const
Mark
&
mark
,
const
std
::
string
&
name
)
const
{
Anchors
::
const_iterator
it
=
m_anchors
.
find
(
name
);
if
(
it
==
m_anchors
.
end
())
if
(
it
==
m_anchors
.
end
())
throw
ParserException
(
mark
,
ErrorMsg
::
UNKNOWN_ANCHOR
);
return
it
->
second
;
}
}
}
src/singledocparser.h
View file @
9b4db068
#ifndef SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/noncopyable.h"
#include <string>
#include <map>
#include <memory>
namespace
YAML
{
struct
Directives
;
struct
Mark
;
struct
Token
;
class
CollectionStack
;
class
EventHandler
;
class
Node
;
class
Scanner
;
namespace
YAML
{
struct
Directives
;
struct
Mark
;
struct
Token
;
class
CollectionStack
;
class
EventHandler
;
class
Node
;
class
Scanner
;
class
SingleDocParser
:
private
noncopyable
{
class
SingleDocParser
:
private
noncopyable
{
public:
SingleDocParser
(
Scanner
&
scanner
,
const
Directives
&
directives
);
~
SingleDocParser
();
...
...
@@ -59,7 +58,7 @@ namespace YAML
Anchors
m_anchors
;
anchor_t
m_curAnchor
;
};
};
}
#endif // SINGLEDOCPARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/stream.cpp
View file @
9b4db068
...
...
@@ -6,14 +6,13 @@
#define YAML_PREFETCH_SIZE 2048
#endif
#define S_ARRAY_SIZE(
A
) (sizeof(A)
/
sizeof(*(A)))
#define S_ARRAY_END(
A
) ((A) + S_ARRAY_SIZE(A))
#define S_ARRAY_SIZE(
A
) (sizeof(A)
/
sizeof(*(A)))
#define S_ARRAY_END(
A
) ((A) + S_ARRAY_SIZE(A))
#define CP_REPLACEMENT_CHARACTER (0xFFFD)
namespace
YAML
{
enum
UtfIntroState
{
namespace
YAML
{
enum
UtfIntroState
{
uis_start
,
uis_utfbe_b1
,
uis_utf32be_b2
,
...
...
@@ -33,9 +32,9 @@ namespace YAML
uis_utf8_bom2
,
uis_utf8
,
uis_error
};
};
enum
UtfIntroCharType
{
enum
UtfIntroCharType
{
uict00
,
uictBB
,
uictBF
,
...
...
@@ -45,53 +44,70 @@ namespace YAML
uictAscii
,
uictOther
,
uictMax
};
static
bool
s_introFinalState
[]
=
{
false
,
//uis_start
false
,
//uis_utfbe_b1
false
,
//uis_utf32be_b2
false
,
//uis_utf32be_bom3
true
,
//uis_utf32be
true
,
//uis_utf16be
false
,
//uis_utf16be_bom1
false
,
//uis_utfle_bom1
false
,
//uis_utf16le_bom2
false
,
//uis_utf32le_bom3
true
,
//uis_utf16le
true
,
//uis_utf32le
false
,
//uis_utf8_imp
false
,
//uis_utf16le_imp
false
,
//uis_utf32le_imp3
false
,
//uis_utf8_bom1
false
,
//uis_utf8_bom2
true
,
//uis_utf8
true
,
//uis_error
};
static
UtfIntroState
s_introTransitions
[][
uictMax
]
=
{
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
{
uis_utfbe_b1
,
uis_utf8
,
uis_utf8
,
uis_utf8_bom1
,
uis_utf16be_bom1
,
uis_utfle_bom1
,
uis_utf8_imp
,
uis_utf8
},
{
uis_utf32be_b2
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf16be
,
uis_utf8
},
{
uis_utf32be
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf32be_bom3
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf32be
,
uis_utf8
,
uis_utf8
},
{
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
},
{
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf16be
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf16le_bom2
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf32le_bom3
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf32le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
},
{
uis_utf16le_imp
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf32le_imp3
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf32le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf8
,
uis_utf8_bom2
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
};
static
char
s_introUngetCount
[][
uictMax
]
=
{
};
static
bool
s_introFinalState
[]
=
{
false
,
// uis_start
false
,
// uis_utfbe_b1
false
,
// uis_utf32be_b2
false
,
// uis_utf32be_bom3
true
,
// uis_utf32be
true
,
// uis_utf16be
false
,
// uis_utf16be_bom1
false
,
// uis_utfle_bom1
false
,
// uis_utf16le_bom2
false
,
// uis_utf32le_bom3
true
,
// uis_utf16le
true
,
// uis_utf32le
false
,
// uis_utf8_imp
false
,
// uis_utf16le_imp
false
,
// uis_utf32le_imp3
false
,
// uis_utf8_bom1
false
,
// uis_utf8_bom2
true
,
// uis_utf8
true
,
// uis_error
};
static
UtfIntroState
s_introTransitions
[][
uictMax
]
=
{
// uict00, uictBB, uictBF, uictEF,
// uictFE, uictFF, uictAscii, uictOther
{
uis_utfbe_b1
,
uis_utf8
,
uis_utf8
,
uis_utf8_bom1
,
uis_utf16be_bom1
,
uis_utfle_bom1
,
uis_utf8_imp
,
uis_utf8
},
{
uis_utf32be_b2
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf16be
,
uis_utf8
},
{
uis_utf32be
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf32be_bom3
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf32be
,
uis_utf8
,
uis_utf8
},
{
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
,
uis_utf32be
},
{
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
,
uis_utf16be
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf16be
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf16le_bom2
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf32le_bom3
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf32le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
,
uis_utf32le
},
{
uis_utf16le_imp
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf32le_imp3
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf32le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
,
uis_utf16le
},
{
uis_utf8
,
uis_utf8_bom2
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
{
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
,
uis_utf8
},
};
static
char
s_introUngetCount
[][
uictMax
]
=
{
// uict00, uictBB, uictBF, uictEF, uictFE, uictFF, uictAscii, uictOther
{
0
,
1
,
1
,
0
,
0
,
0
,
0
,
1
},
{
0
,
2
,
2
,
2
,
2
,
2
,
2
,
2
},
...
...
@@ -110,22 +126,26 @@ namespace YAML
{
4
,
4
,
4
,
4
,
4
,
4
,
4
,
4
},
{
2
,
0
,
2
,
2
,
2
,
2
,
2
,
2
},
{
3
,
3
,
0
,
3
,
3
,
3
,
3
,
3
},
{
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
},
};
{
1
,
1
,
1
,
1
,
1
,
1
,
1
,
1
},
};
inline
UtfIntroCharType
IntroCharTypeOf
(
std
::
istream
::
int_type
ch
)
{
inline
UtfIntroCharType
IntroCharTypeOf
(
std
::
istream
::
int_type
ch
)
{
if
(
std
::
istream
::
traits_type
::
eof
()
==
ch
)
{
return
uictOther
;
}
switch
(
ch
)
{
case
0
:
return
uict00
;
case
0xBB
:
return
uictBB
;
case
0xBF
:
return
uictBF
;
case
0xEF
:
return
uictEF
;
case
0xFE
:
return
uictFE
;
case
0xFF
:
return
uictFF
;
case
0
:
return
uict00
;
case
0xBB
:
return
uictBB
;
case
0xBF
:
return
uictBF
;
case
0xEF
:
return
uictEF
;
case
0xFE
:
return
uictFE
;
case
0xFF
:
return
uictFF
;
}
if
((
ch
>
0
)
&&
(
ch
<
0xFF
))
{
...
...
@@ -133,58 +153,48 @@ namespace YAML
}
return
uictOther
;
}
}
inline
char
Utf8Adjust
(
unsigned
long
ch
,
unsigned
char
lead_bits
,
unsigned
char
rshift
)
{
inline
char
Utf8Adjust
(
unsigned
long
ch
,
unsigned
char
lead_bits
,
unsigned
char
rshift
)
{
const
unsigned
char
header
=
((
1
<<
lead_bits
)
-
1
)
<<
(
8
-
lead_bits
);
const
unsigned
char
mask
=
(
0xFF
>>
(
lead_bits
+
1
));
return
static_cast
<
char
>
(
static_cast
<
unsigned
char
>
(
header
|
((
ch
>>
rshift
)
&
mask
)
));
}
return
static_cast
<
char
>
(
static_cast
<
unsigned
char
>
(
header
|
((
ch
>>
rshift
)
&
mask
)));
}
inline
void
QueueUnicodeCodepoint
(
std
::
deque
<
char
>&
q
,
unsigned
long
ch
)
{
inline
void
QueueUnicodeCodepoint
(
std
::
deque
<
char
>&
q
,
unsigned
long
ch
)
{
// We are not allowed to queue the Stream::eof() codepoint, so
// replace it with CP_REPLACEMENT_CHARACTER
if
(
static_cast
<
unsigned
long
>
(
Stream
::
eof
())
==
ch
)
{
if
(
static_cast
<
unsigned
long
>
(
Stream
::
eof
())
==
ch
)
{
ch
=
CP_REPLACEMENT_CHARACTER
;
}
if
(
ch
<
0x80
)
{
if
(
ch
<
0x80
)
{
q
.
push_back
(
Utf8Adjust
(
ch
,
0
,
0
));
}
else
if
(
ch
<
0x800
)
{
}
else
if
(
ch
<
0x800
)
{
q
.
push_back
(
Utf8Adjust
(
ch
,
2
,
6
));
q
.
push_back
(
Utf8Adjust
(
ch
,
1
,
0
));
}
else
if
(
ch
<
0x10000
)
{
}
else
if
(
ch
<
0x10000
)
{
q
.
push_back
(
Utf8Adjust
(
ch
,
3
,
12
));
q
.
push_back
(
Utf8Adjust
(
ch
,
1
,
6
));
q
.
push_back
(
Utf8Adjust
(
ch
,
1
,
0
));
}
else
{
}
else
{
q
.
push_back
(
Utf8Adjust
(
ch
,
4
,
18
));
q
.
push_back
(
Utf8Adjust
(
ch
,
1
,
12
));
q
.
push_back
(
Utf8Adjust
(
ch
,
1
,
6
));
q
.
push_back
(
Utf8Adjust
(
ch
,
1
,
0
));
}
}
}
Stream
::
Stream
(
std
::
istream
&
input
)
Stream
::
Stream
(
std
::
istream
&
input
)
:
m_input
(
input
),
m_pPrefetched
(
new
unsigned
char
[
YAML_PREFETCH_SIZE
]),
m_nPrefetchedAvailable
(
0
),
m_nPrefetchedUsed
(
0
)
{
m_nPrefetchedAvailable
(
0
),
m_nPrefetchedUsed
(
0
)
{
typedef
std
::
istream
::
traits_type
char_traits
;
if
(
!
input
)
if
(
!
input
)
return
;
// Determine (or guess) the character-set by reading the BOM, if any. See
...
...
@@ -192,16 +202,16 @@ namespace YAML
char_traits
::
int_type
intro
[
4
];
int
nIntroUsed
=
0
;
UtfIntroState
state
=
uis_start
;
for
(;
!
s_introFinalState
[
state
];
)
{
for
(;
!
s_introFinalState
[
state
];)
{
std
::
istream
::
int_type
ch
=
input
.
get
();
intro
[
nIntroUsed
++
]
=
ch
;
UtfIntroCharType
charType
=
IntroCharTypeOf
(
ch
);
UtfIntroState
newState
=
s_introTransitions
[
state
][
charType
];
int
nUngets
=
s_introUngetCount
[
state
][
charType
];
if
(
nUngets
>
0
)
{
if
(
nUngets
>
0
)
{
input
.
clear
();
for
(;
nUngets
>
0
;
--
nUngets
)
{
if
(
char_traits
::
eof
()
!=
intro
[
--
nIntroUsed
])
for
(;
nUngets
>
0
;
--
nUngets
)
{
if
(
char_traits
::
eof
()
!=
intro
[
--
nIntroUsed
])
input
.
putback
(
char_traits
::
to_char_type
(
intro
[
nIntroUsed
]));
}
}
...
...
@@ -209,166 +219,163 @@ namespace YAML
}
switch
(
state
)
{
case
uis_utf8
:
m_charSet
=
utf8
;
break
;
case
uis_utf16le
:
m_charSet
=
utf16le
;
break
;
case
uis_utf16be
:
m_charSet
=
utf16be
;
break
;
case
uis_utf32le
:
m_charSet
=
utf32le
;
break
;
case
uis_utf32be
:
m_charSet
=
utf32be
;
break
;
default:
m_charSet
=
utf8
;
break
;
case
uis_utf8
:
m_charSet
=
utf8
;
break
;
case
uis_utf16le
:
m_charSet
=
utf16le
;
break
;
case
uis_utf16be
:
m_charSet
=
utf16be
;
break
;
case
uis_utf32le
:
m_charSet
=
utf32le
;
break
;
case
uis_utf32be
:
m_charSet
=
utf32be
;
break
;
default:
m_charSet
=
utf8
;
break
;
}
ReadAheadTo
(
0
);
}
}
Stream
::~
Stream
()
{
delete
[]
m_pPrefetched
;
}
Stream
::~
Stream
()
{
delete
[]
m_pPrefetched
;
}
char
Stream
::
peek
()
const
{
if
(
m_readahead
.
empty
())
{
char
Stream
::
peek
()
const
{
if
(
m_readahead
.
empty
())
{
return
Stream
::
eof
();
}
return
m_readahead
[
0
];
}
}
Stream
::
operator
bool
()
const
{
return
m_input
.
good
()
||
(
!
m_readahead
.
empty
()
&&
m_readahead
[
0
]
!=
Stream
::
eof
());
}
Stream
::
operator
bool
()
const
{
return
m_input
.
good
()
||
(
!
m_readahead
.
empty
()
&&
m_readahead
[
0
]
!=
Stream
::
eof
());
}
// get
// . Extracts a character from the stream and updates our position
char
Stream
::
get
()
{
// get
// . Extracts a character from the stream and updates our position
char
Stream
::
get
()
{
char
ch
=
peek
();
AdvanceCurrent
();
m_mark
.
column
++
;
if
(
ch
==
'\n'
)
{
if
(
ch
==
'\n'
)
{
m_mark
.
column
=
0
;
m_mark
.
line
++
;
}
return
ch
;
}
}
// get
// . Extracts 'n' characters from the stream and updates our position
std
::
string
Stream
::
get
(
int
n
)
{
// get
// . Extracts 'n' characters from the stream and updates our position
std
::
string
Stream
::
get
(
int
n
)
{
std
::
string
ret
;
ret
.
reserve
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
i
=
0
;
i
<
n
;
i
++
)
ret
+=
get
();
return
ret
;
}
}
// eat
// . Eats 'n' characters and updates our position.
void
Stream
::
eat
(
int
n
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
// eat
// . Eats 'n' characters and updates our position.
void
Stream
::
eat
(
int
n
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++
)
get
();
}
}
void
Stream
::
AdvanceCurrent
()
{
if
(
!
m_readahead
.
empty
())
{
void
Stream
::
AdvanceCurrent
()
{
if
(
!
m_readahead
.
empty
())
{
m_readahead
.
pop_front
();
m_mark
.
pos
++
;
}
ReadAheadTo
(
0
);
}
}
bool
Stream
::
_ReadAheadTo
(
size_t
i
)
const
{
while
(
m_input
.
good
()
&&
(
m_readahead
.
size
()
<=
i
))
{
switch
(
m_charSet
)
{
case
utf8
:
StreamInUtf8
();
break
;
case
utf16le
:
StreamInUtf16
();
break
;
case
utf16be
:
StreamInUtf16
();
break
;
case
utf32le
:
StreamInUtf32
();
break
;
case
utf32be
:
StreamInUtf32
();
break
;
bool
Stream
::
_ReadAheadTo
(
size_t
i
)
const
{
while
(
m_input
.
good
()
&&
(
m_readahead
.
size
()
<=
i
))
{
switch
(
m_charSet
)
{
case
utf8
:
StreamInUtf8
();
break
;
case
utf16le
:
StreamInUtf16
();
break
;
case
utf16be
:
StreamInUtf16
();
break
;
case
utf32le
:
StreamInUtf32
();
break
;
case
utf32be
:
StreamInUtf32
();
break
;
}
}
// signal end of stream
if
(
!
m_input
.
good
())
if
(
!
m_input
.
good
())
m_readahead
.
push_back
(
Stream
::
eof
());
return
m_readahead
.
size
()
>
i
;
}
}
void
Stream
::
StreamInUtf8
()
const
{
void
Stream
::
StreamInUtf8
()
const
{
unsigned
char
b
=
GetNextByte
();
if
(
m_input
.
good
())
{
if
(
m_input
.
good
())
{
m_readahead
.
push_back
(
b
);
}
}
}
void
Stream
::
StreamInUtf16
()
const
{
void
Stream
::
StreamInUtf16
()
const
{
unsigned
long
ch
=
0
;
unsigned
char
bytes
[
2
];
int
nBigEnd
=
(
m_charSet
==
utf16be
)
?
0
:
1
;
bytes
[
0
]
=
GetNextByte
();
bytes
[
1
]
=
GetNextByte
();
if
(
!
m_input
.
good
())
{
if
(
!
m_input
.
good
())
{
return
;
}
ch
=
(
static_cast
<
unsigned
long
>
(
bytes
[
nBigEnd
])
<<
8
)
|
static_cast
<
unsigned
long
>
(
bytes
[
1
^
nBigEnd
]);
if
(
ch
>=
0xDC00
&&
ch
<
0xE000
)
{
if
(
ch
>=
0xDC00
&&
ch
<
0xE000
)
{
// Trailing (low) surrogate...ugh, wrong order
QueueUnicodeCodepoint
(
m_readahead
,
CP_REPLACEMENT_CHARACTER
);
return
;
}
else
if
(
ch
>=
0xD800
&&
ch
<
0xDC00
)
{
}
else
if
(
ch
>=
0xD800
&&
ch
<
0xDC00
)
{
// ch is a leading (high) surrogate
// Four byte UTF-8 code point
// Read the trailing (low) surrogate
for
(;;)
{
for
(;;)
{
bytes
[
0
]
=
GetNextByte
();
bytes
[
1
]
=
GetNextByte
();
if
(
!
m_input
.
good
())
{
if
(
!
m_input
.
good
())
{
QueueUnicodeCodepoint
(
m_readahead
,
CP_REPLACEMENT_CHARACTER
);
return
;
}
unsigned
long
chLow
=
(
static_cast
<
unsigned
long
>
(
bytes
[
nBigEnd
])
<<
8
)
|
static_cast
<
unsigned
long
>
(
bytes
[
1
^
nBigEnd
]);
if
(
chLow
<
0xDC00
||
ch
>=
0xE000
)
{
// Trouble...not a low surrogate. Dump a REPLACEMENT CHARACTER into the
stream.
if
(
chLow
<
0xDC00
||
ch
>=
0xE000
)
{
// Trouble...not a low surrogate. Dump a REPLACEMENT CHARACTER into the
//
stream.
QueueUnicodeCodepoint
(
m_readahead
,
CP_REPLACEMENT_CHARACTER
);
// Deal with the next UTF-16 unit
if
(
chLow
<
0xD800
||
ch
>=
0xE000
)
{
if
(
chLow
<
0xD800
||
ch
>=
0xE000
)
{
// Easiest case: queue the codepoint and return
QueueUnicodeCodepoint
(
m_readahead
,
ch
);
return
;
}
else
{
}
else
{
// Start the loop over with the new high surrogate
ch
=
chLow
;
continue
;
...
...
@@ -388,40 +395,32 @@ namespace YAML
}
QueueUnicodeCodepoint
(
m_readahead
,
ch
);
}
}
inline
char
*
ReadBuffer
(
unsigned
char
*
pBuffer
)
{
inline
char
*
ReadBuffer
(
unsigned
char
*
pBuffer
)
{
return
reinterpret_cast
<
char
*>
(
pBuffer
);
}
}
unsigned
char
Stream
::
GetNextByte
()
const
{
if
(
m_nPrefetchedUsed
>=
m_nPrefetchedAvailable
)
{
std
::
streambuf
*
pBuf
=
m_input
.
rdbuf
();
m_nPrefetchedAvailable
=
static_cast
<
std
::
size_t
>
(
pBuf
->
sgetn
(
ReadBuffer
(
m_pPrefetched
),
YAML_PREFETCH_SIZE
));
unsigned
char
Stream
::
GetNextByte
()
const
{
if
(
m_nPrefetchedUsed
>=
m_nPrefetchedAvailable
)
{
std
::
streambuf
*
pBuf
=
m_input
.
rdbuf
();
m_nPrefetchedAvailable
=
static_cast
<
std
::
size_t
>
(
pBuf
->
sgetn
(
ReadBuffer
(
m_pPrefetched
),
YAML_PREFETCH_SIZE
));
m_nPrefetchedUsed
=
0
;
if
(
!
m_nPrefetchedAvailable
)
{
if
(
!
m_nPrefetchedAvailable
)
{
m_input
.
setstate
(
std
::
ios_base
::
eofbit
);
}
if
(
0
==
m_nPrefetchedAvailable
)
{
if
(
0
==
m_nPrefetchedAvailable
)
{
return
0
;
}
}
return
m_pPrefetched
[
m_nPrefetchedUsed
++
];
}
}
void
Stream
::
StreamInUtf32
()
const
{
static
int
indexes
[
2
][
4
]
=
{
{
3
,
2
,
1
,
0
},
{
0
,
1
,
2
,
3
}
};
void
Stream
::
StreamInUtf32
()
const
{
static
int
indexes
[
2
][
4
]
=
{{
3
,
2
,
1
,
0
},
{
0
,
1
,
2
,
3
}};
unsigned
long
ch
=
0
;
unsigned
char
bytes
[
4
];
...
...
@@ -431,17 +430,15 @@ namespace YAML
bytes
[
1
]
=
GetNextByte
();
bytes
[
2
]
=
GetNextByte
();
bytes
[
3
]
=
GetNextByte
();
if
(
!
m_input
.
good
())
{
if
(
!
m_input
.
good
())
{
return
;
}
for
(
int
i
=
0
;
i
<
4
;
++
i
)
{
for
(
int
i
=
0
;
i
<
4
;
++
i
)
{
ch
<<=
8
;
ch
|=
bytes
[
pIndexes
[
i
]];
}
QueueUnicodeCodepoint
(
m_readahead
,
ch
);
}
}
}
src/stream.h
View file @
9b4db068
#ifndef STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include "yaml-cpp/mark.h"
#include <cstddef>
...
...
@@ -15,10 +16,8 @@
#include <set>
#include <string>
namespace
YAML
{
class
Stream
:
private
noncopyable
{
namespace
YAML
{
class
Stream
:
private
noncopyable
{
public:
friend
class
StreamCharSource
;
...
...
@@ -26,7 +25,7 @@ namespace YAML
~
Stream
();
operator
bool
()
const
;
bool
operator
!
()
const
{
return
!
static_cast
<
bool
>
(
*
this
);
}
bool
operator
!
()
const
{
return
!
static_cast
<
bool
>
(
*
this
);
}
char
peek
()
const
;
char
get
();
...
...
@@ -42,7 +41,13 @@ namespace YAML
void
ResetColumn
()
{
m_mark
.
column
=
0
;
}
private:
enum
CharacterSet
{
utf8
,
utf16le
,
utf16be
,
utf32le
,
utf32be
};
enum
CharacterSet
{
utf8
,
utf16le
,
utf16be
,
utf32le
,
utf32be
};
std
::
istream
&
m_input
;
Mark
m_mark
;
...
...
@@ -61,19 +66,17 @@ namespace YAML
void
StreamInUtf16
()
const
;
void
StreamInUtf32
()
const
;
unsigned
char
GetNextByte
()
const
;
};
};
// CharAt
// . Unchecked access
inline
char
Stream
::
CharAt
(
size_t
i
)
const
{
return
m_readahead
[
i
];
}
// CharAt
// . Unchecked access
inline
char
Stream
::
CharAt
(
size_t
i
)
const
{
return
m_readahead
[
i
];
}
inline
bool
Stream
::
ReadAheadTo
(
size_t
i
)
const
{
if
(
m_readahead
.
size
()
>
i
)
inline
bool
Stream
::
ReadAheadTo
(
size_t
i
)
const
{
if
(
m_readahead
.
size
()
>
i
)
return
true
;
return
_ReadAheadTo
(
i
);
}
}
}
#endif // STREAM_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/streamcharsource.h
View file @
9b4db068
#ifndef STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "yaml-cpp/noncopyable.h"
#include <cstddef>
namespace
YAML
{
class
StreamCharSource
{
namespace
YAML
{
class
StreamCharSource
{
public:
StreamCharSource
(
const
Stream
&
stream
)
:
m_offset
(
0
),
m_stream
(
stream
)
{}
StreamCharSource
(
const
StreamCharSource
&
source
)
:
m_offset
(
source
.
m_offset
),
m_stream
(
source
.
m_stream
)
{}
StreamCharSource
(
const
Stream
&
stream
)
:
m_offset
(
0
),
m_stream
(
stream
)
{}
StreamCharSource
(
const
StreamCharSource
&
source
)
:
m_offset
(
source
.
m_offset
),
m_stream
(
source
.
m_stream
)
{}
~
StreamCharSource
()
{}
operator
bool
()
const
;
char
operator
[]
(
std
::
size_t
i
)
const
{
return
m_stream
.
CharAt
(
m_offset
+
i
);
}
bool
operator
!
()
const
{
return
!
static_cast
<
bool
>
(
*
this
);
}
char
operator
[](
std
::
size_t
i
)
const
{
return
m_stream
.
CharAt
(
m_offset
+
i
);
}
bool
operator
!
()
const
{
return
!
static_cast
<
bool
>
(
*
this
);
}
const
StreamCharSource
operator
+
(
int
i
)
const
;
const
StreamCharSource
operator
+
(
int
i
)
const
;
private:
std
::
size_t
m_offset
;
const
Stream
&
m_stream
;
StreamCharSource
&
operator
=
(
const
StreamCharSource
&
);
// non-assignable
};
StreamCharSource
&
operator
=
(
const
StreamCharSource
&
);
// non-assignable
};
inline
StreamCharSource
::
operator
bool
()
const
{
inline
StreamCharSource
::
operator
bool
()
const
{
return
m_stream
.
ReadAheadTo
(
m_offset
);
}
}
inline
const
StreamCharSource
StreamCharSource
::
operator
+
(
int
i
)
const
{
inline
const
StreamCharSource
StreamCharSource
::
operator
+
(
int
i
)
const
{
StreamCharSource
source
(
*
this
);
if
(
static_cast
<
int
>
(
source
.
m_offset
)
+
i
>=
0
)
if
(
static_cast
<
int
>
(
source
.
m_offset
)
+
i
>=
0
)
source
.
m_offset
+=
i
;
else
source
.
m_offset
=
0
;
return
source
;
}
}
}
#endif // STREAMCHARSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/stringsource.h
View file @
9b4db068
#ifndef STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <cstddef>
namespace
YAML
{
class
StringCharSource
{
namespace
YAML
{
class
StringCharSource
{
public:
StringCharSource
(
const
char
*
str
,
std
::
size_t
size
)
:
m_str
(
str
),
m_size
(
size
),
m_offset
(
0
)
{}
StringCharSource
(
const
char
*
str
,
std
::
size_t
size
)
:
m_str
(
str
),
m_size
(
size
),
m_offset
(
0
)
{}
operator
bool
()
const
{
return
m_offset
<
m_size
;
}
char
operator
[]
(
std
::
size_t
i
)
const
{
return
m_str
[
m_offset
+
i
];
}
bool
operator
!
()
const
{
return
!
static_cast
<
bool
>
(
*
this
);
}
char
operator
[](
std
::
size_t
i
)
const
{
return
m_str
[
m_offset
+
i
];
}
bool
operator
!
()
const
{
return
!
static_cast
<
bool
>
(
*
this
);
}
const
StringCharSource
operator
+
(
int
i
)
const
{
const
StringCharSource
operator
+
(
int
i
)
const
{
StringCharSource
source
(
*
this
);
if
(
static_cast
<
int
>
(
source
.
m_offset
)
+
i
>=
0
)
if
(
static_cast
<
int
>
(
source
.
m_offset
)
+
i
>=
0
)
source
.
m_offset
+=
i
;
else
source
.
m_offset
=
0
;
return
source
;
}
StringCharSource
&
operator
++
()
{
StringCharSource
&
operator
++
()
{
++
m_offset
;
return
*
this
;
}
StringCharSource
&
operator
+=
(
std
::
size_t
offset
)
{
StringCharSource
&
operator
+=
(
std
::
size_t
offset
)
{
m_offset
+=
offset
;
return
*
this
;
}
private:
const
char
*
m_str
;
const
char
*
m_str
;
std
::
size_t
m_size
;
std
::
size_t
m_offset
;
};
};
}
#endif // STRINGSOURCE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/tag.cpp
View file @
9b4db068
...
...
@@ -4,11 +4,9 @@
#include <cassert>
#include <stdexcept>
namespace
YAML
{
Tag
::
Tag
(
const
Token
&
token
)
:
type
(
static_cast
<
TYPE
>
(
token
.
data
))
{
switch
(
type
)
{
namespace
YAML
{
Tag
::
Tag
(
const
Token
&
token
)
:
type
(
static_cast
<
TYPE
>
(
token
.
data
))
{
switch
(
type
)
{
case
VERBATIM
:
value
=
token
.
value
;
break
;
...
...
@@ -27,11 +25,10 @@ namespace YAML
default:
assert
(
false
);
}
}
}
const
std
::
string
Tag
::
Translate
(
const
Directives
&
directives
)
{
switch
(
type
)
{
const
std
::
string
Tag
::
Translate
(
const
Directives
&
directives
)
{
switch
(
type
)
{
case
VERBATIM
:
return
value
;
case
PRIMARY_HANDLE
:
...
...
@@ -47,6 +44,5 @@ namespace YAML
assert
(
false
);
}
throw
std
::
runtime_error
(
"yaml-cpp: internal error, bad tag type"
);
}
}
}
src/tag.h
View file @
9b4db068
#ifndef TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include <string>
namespace
YAML
{
struct
Token
;
struct
Directives
;
namespace
YAML
{
struct
Token
;
struct
Directives
;
struct
Tag
{
struct
Tag
{
enum
TYPE
{
VERBATIM
,
PRIMARY_HANDLE
,
SECONDARY_HANDLE
,
NAMED_HANDLE
,
NON_SPECIFIC
VERBATIM
,
PRIMARY_HANDLE
,
SECONDARY_HANDLE
,
NAMED_HANDLE
,
NON_SPECIFIC
};
Tag
(
const
Token
&
token
);
...
...
@@ -22,7 +27,7 @@ namespace YAML
TYPE
type
;
std
::
string
handle
,
value
;
};
};
}
#endif // TAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
Prev
1
2
3
4
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