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
bc86fd4a
Commit
bc86fd4a
authored
Jan 24, 2015
by
Jesse Beder
Browse files
Force null to be quoted if written as a string
parent
087e0673
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
80 additions
and
41 deletions
+80
-41
src/emitterutils.cpp
src/emitterutils.cpp
+74
-41
test/integration/emitter_test.cpp
test/integration/emitter_test.cpp
+6
-0
No files found.
src/emitterutils.cpp
View file @
bc86fd4a
...
@@ -32,22 +32,29 @@ bool IsAnchorChar(int ch) { // test for ns-anchor-char
...
@@ -32,22 +32,29 @@ bool IsAnchorChar(int ch) { // test for ns-anchor-char
return
true
;
return
true
;
}
}
if
(
ch
<
0x20
)
if
(
ch
<
0x20
)
{
return
false
;
return
false
;
}
if
(
ch
<
0x7E
)
if
(
ch
<
0x7E
)
{
return
true
;
return
true
;
}
if
(
ch
<
0xA0
)
if
(
ch
<
0xA0
)
{
return
false
;
return
false
;
if
(
ch
>=
0xD800
&&
ch
<=
0xDFFF
)
}
if
(
ch
>=
0xD800
&&
ch
<=
0xDFFF
)
{
return
false
;
return
false
;
if
((
ch
&
0xFFFE
)
==
0xFFFE
)
}
if
((
ch
&
0xFFFE
)
==
0xFFFE
)
{
return
false
;
return
false
;
if
((
ch
>=
0xFDD0
)
&&
(
ch
<=
0xFDEF
))
}
if
((
ch
>=
0xFDD0
)
&&
(
ch
<=
0xFDEF
))
{
return
false
;
return
false
;
if
(
ch
>
0x10FFFF
)
}
if
(
ch
>
0x10FFFF
)
{
return
false
;
return
false
;
}
return
true
;
return
true
;
}
}
...
@@ -145,19 +152,27 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
...
@@ -145,19 +152,27 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
bool
IsValidPlainScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
IsValidPlainScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
allowOnlyAscii
)
{
bool
allowOnlyAscii
)
{
if
(
str
.
empty
())
if
(
str
.
empty
())
{
return
false
;
}
// check against null
if
(
str
==
"null"
)
{
return
false
;
return
false
;
}
//
first
check the start
// check the start
const
RegEx
&
start
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
PlainScalarInFlow
()
const
RegEx
&
start
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
PlainScalarInFlow
()
:
Exp
::
PlainScalar
());
:
Exp
::
PlainScalar
());
if
(
!
start
.
Matches
(
str
))
if
(
!
start
.
Matches
(
str
))
{
return
false
;
return
false
;
}
// and check the end for plain whitespace (which can't be faithfully kept in a
// and check the end for plain whitespace (which can't be faithfully kept in a
// plain scalar)
// plain scalar)
if
(
!
str
.
empty
()
&&
*
str
.
rbegin
()
==
' '
)
if
(
!
str
.
empty
()
&&
*
str
.
rbegin
()
==
' '
)
{
return
false
;
return
false
;
}
// then check until something is disallowed
// then check until something is disallowed
const
RegEx
&
disallowed
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
EndScalarInFlow
()
const
RegEx
&
disallowed
=
(
flowType
==
FlowType
::
Flow
?
Exp
::
EndScalarInFlow
()
...
@@ -167,10 +182,12 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
...
@@ -167,10 +182,12 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
Exp
::
Break
()
||
Exp
::
Tab
();
Exp
::
Break
()
||
Exp
::
Tab
();
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
while
(
buffer
)
{
while
(
buffer
)
{
if
(
disallowed
.
Matches
(
buffer
))
if
(
disallowed
.
Matches
(
buffer
))
{
return
false
;
return
false
;
if
(
allowOnlyAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
buffer
[
0
])))
}
if
(
allowOnlyAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
buffer
[
0
])))
{
return
false
;
return
false
;
}
++
buffer
;
++
buffer
;
}
}
...
@@ -180,23 +197,27 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
...
@@ -180,23 +197,27 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool
IsValidSingleQuotedScalar
(
const
std
::
string
&
str
,
bool
escapeNonAscii
)
{
bool
IsValidSingleQuotedScalar
(
const
std
::
string
&
str
,
bool
escapeNonAscii
)
{
// TODO: check for non-printable characters?
// TODO: check for non-printable characters?
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
{
return
false
;
return
false
;
if
(
str
[
i
]
==
'\n'
)
}
if
(
str
[
i
]
==
'\n'
)
{
return
false
;
return
false
;
}
}
}
return
true
;
return
true
;
}
}
bool
IsValidLiteralScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
IsValidLiteralScalar
(
const
std
::
string
&
str
,
FlowType
::
value
flowType
,
bool
escapeNonAscii
)
{
bool
escapeNonAscii
)
{
if
(
flowType
==
FlowType
::
Flow
)
if
(
flowType
==
FlowType
::
Flow
)
{
return
false
;
return
false
;
}
// TODO: check for non-printable characters?
// TODO: check for non-printable characters?
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
for
(
std
::
size_t
i
=
0
;
i
<
str
.
size
();
i
++
)
{
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
if
(
escapeNonAscii
&&
(
0x80
<=
static_cast
<
unsigned
char
>
(
str
[
i
])))
{
return
false
;
return
false
;
}
}
}
return
true
;
return
true
;
}
}
...
@@ -226,8 +247,9 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
...
@@ -226,8 +247,9 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
int
codePoint
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
!
IsAnchorChar
(
codePoint
))
if
(
!
IsAnchorChar
(
codePoint
))
{
return
false
;
return
false
;
}
WriteCodePoint
(
out
,
codePoint
);
WriteCodePoint
(
out
,
codePoint
);
}
}
...
@@ -241,18 +263,21 @@ StringFormat::value ComputeStringFormat(const std::string& str,
...
@@ -241,18 +263,21 @@ StringFormat::value ComputeStringFormat(const std::string& str,
bool
escapeNonAscii
)
{
bool
escapeNonAscii
)
{
switch
(
strFormat
)
{
switch
(
strFormat
)
{
case
Auto
:
case
Auto
:
if
(
IsValidPlainScalar
(
str
,
flowType
,
escapeNonAscii
))
if
(
IsValidPlainScalar
(
str
,
flowType
,
escapeNonAscii
))
{
return
StringFormat
::
Plain
;
return
StringFormat
::
Plain
;
}
return
StringFormat
::
DoubleQuoted
;
return
StringFormat
::
DoubleQuoted
;
case
SingleQuoted
:
case
SingleQuoted
:
if
(
IsValidSingleQuotedScalar
(
str
,
escapeNonAscii
))
if
(
IsValidSingleQuotedScalar
(
str
,
escapeNonAscii
))
{
return
StringFormat
::
SingleQuoted
;
return
StringFormat
::
SingleQuoted
;
}
return
StringFormat
::
DoubleQuoted
;
return
StringFormat
::
DoubleQuoted
;
case
DoubleQuoted
:
case
DoubleQuoted
:
return
StringFormat
::
DoubleQuoted
;
return
StringFormat
::
DoubleQuoted
;
case
Literal
:
case
Literal
:
if
(
IsValidLiteralScalar
(
str
,
flowType
,
escapeNonAscii
))
if
(
IsValidLiteralScalar
(
str
,
flowType
,
escapeNonAscii
))
{
return
StringFormat
::
Literal
;
return
StringFormat
::
Literal
;
}
return
StringFormat
::
DoubleQuoted
;
return
StringFormat
::
DoubleQuoted
;
default:
default:
break
;
break
;
...
@@ -266,14 +291,16 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
...
@@ -266,14 +291,16 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
int
codePoint
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
codePoint
==
'\n'
)
if
(
codePoint
==
'\n'
)
{
return
false
;
// We can't handle a new line and the attendant indentation
return
false
;
// We can't handle a new line and the attendant indentation
// yet
// yet
}
if
(
codePoint
==
'\''
)
if
(
codePoint
==
'\''
)
{
out
<<
"''"
;
out
<<
"''"
;
else
}
else
{
WriteCodePoint
(
out
,
codePoint
);
WriteCodePoint
(
out
,
codePoint
);
}
}
}
out
<<
"'"
;
out
<<
"'"
;
return
true
;
return
true
;
...
@@ -307,15 +334,16 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
...
@@ -307,15 +334,16 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
default:
default:
if
(
codePoint
<
0x20
||
if
(
codePoint
<
0x20
||
(
codePoint
>=
0x80
&&
(
codePoint
>=
0x80
&&
codePoint
<=
0xA0
))
// Control characters and non-breaking space
codePoint
<=
0xA0
))
{
// Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
if
(
codePoint
==
0xFEFF
)
// Byte order marks (ZWNS) should be
}
else
if
(
codePoint
==
0xFEFF
)
{
// Byte order marks (ZWNS) should be
// escaped (YAML 1.2, sec. 5.2)
// escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
if
(
escapeNonAscii
&&
codePoint
>
0x7E
)
}
else
if
(
escapeNonAscii
&&
codePoint
>
0x7E
)
{
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
WriteDoubleQuoteEscapeSequence
(
out
,
codePoint
);
else
}
else
{
WriteCodePoint
(
out
,
codePoint
);
WriteCodePoint
(
out
,
codePoint
);
}
}
}
}
}
out
<<
"
\"
"
;
out
<<
"
\"
"
;
...
@@ -329,26 +357,27 @@ bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
...
@@ -329,26 +357,27 @@ bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
int
codePoint
;
int
codePoint
;
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
for
(
std
::
string
::
const_iterator
i
=
str
.
begin
();
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
GetNextCodePointAndAdvance
(
codePoint
,
i
,
str
.
end
());)
{
if
(
codePoint
==
'\n'
)
if
(
codePoint
==
'\n'
)
{
out
<<
"
\n
"
<<
IndentTo
(
indent
);
out
<<
"
\n
"
<<
IndentTo
(
indent
);
else
}
else
{
WriteCodePoint
(
out
,
codePoint
);
WriteCodePoint
(
out
,
codePoint
);
}
}
}
return
true
;
return
true
;
}
}
bool
WriteChar
(
ostream_wrapper
&
out
,
char
ch
)
{
bool
WriteChar
(
ostream_wrapper
&
out
,
char
ch
)
{
if
((
'a'
<=
ch
&&
ch
<=
'z'
)
||
(
'A'
<=
ch
&&
ch
<=
'Z'
))
if
((
'a'
<=
ch
&&
ch
<=
'z'
)
||
(
'A'
<=
ch
&&
ch
<=
'Z'
))
{
out
<<
ch
;
out
<<
ch
;
else
if
((
0x20
<=
ch
&&
ch
<=
0x7e
)
||
ch
==
' '
)
}
else
if
((
0x20
<=
ch
&&
ch
<=
0x7e
)
||
ch
==
' '
)
{
out
<<
"
\"
"
<<
ch
<<
"
\"
"
;
out
<<
"
\"
"
<<
ch
<<
"
\"
"
;
else
if
(
ch
==
'\t'
)
}
else
if
(
ch
==
'\t'
)
{
out
<<
"
\"\\
t
\"
"
;
out
<<
"
\"\\
t
\"
"
;
else
if
(
ch
==
'\n'
)
}
else
if
(
ch
==
'\n'
)
{
out
<<
"
\"\\
n
\"
"
;
out
<<
"
\"\\
n
\"
"
;
else
if
(
ch
==
'\b'
)
}
else
if
(
ch
==
'\b'
)
{
out
<<
"
\"\\
b
\"
"
;
out
<<
"
\"\\
b
\"
"
;
else
{
}
else
{
out
<<
"
\"
"
;
out
<<
"
\"
"
;
WriteDoubleQuoteEscapeSequence
(
out
,
ch
);
WriteDoubleQuoteEscapeSequence
(
out
,
ch
);
out
<<
"
\"
"
;
out
<<
"
\"
"
;
...
@@ -391,16 +420,18 @@ bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
...
@@ -391,16 +420,18 @@ bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
const
RegEx
&
reValid
=
verbatim
?
Exp
::
URI
()
:
Exp
::
Tag
();
const
RegEx
&
reValid
=
verbatim
?
Exp
::
URI
()
:
Exp
::
Tag
();
while
(
buffer
)
{
while
(
buffer
)
{
int
n
=
reValid
.
Match
(
buffer
);
int
n
=
reValid
.
Match
(
buffer
);
if
(
n
<=
0
)
if
(
n
<=
0
)
{
return
false
;
return
false
;
}
while
(
--
n
>=
0
)
{
while
(
--
n
>=
0
)
{
out
<<
buffer
[
0
];
out
<<
buffer
[
0
];
++
buffer
;
++
buffer
;
}
}
}
}
if
(
verbatim
)
if
(
verbatim
)
{
out
<<
">"
;
out
<<
">"
;
}
return
true
;
return
true
;
}
}
...
@@ -410,8 +441,9 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
...
@@ -410,8 +441,9 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
StringCharSource
prefixBuffer
(
prefix
.
c_str
(),
prefix
.
size
());
StringCharSource
prefixBuffer
(
prefix
.
c_str
(),
prefix
.
size
());
while
(
prefixBuffer
)
{
while
(
prefixBuffer
)
{
int
n
=
Exp
::
URI
().
Match
(
prefixBuffer
);
int
n
=
Exp
::
URI
().
Match
(
prefixBuffer
);
if
(
n
<=
0
)
if
(
n
<=
0
)
{
return
false
;
return
false
;
}
while
(
--
n
>=
0
)
{
while
(
--
n
>=
0
)
{
out
<<
prefixBuffer
[
0
];
out
<<
prefixBuffer
[
0
];
...
@@ -423,8 +455,9 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
...
@@ -423,8 +455,9 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
StringCharSource
tagBuffer
(
tag
.
c_str
(),
tag
.
size
());
StringCharSource
tagBuffer
(
tag
.
c_str
(),
tag
.
size
());
while
(
tagBuffer
)
{
while
(
tagBuffer
)
{
int
n
=
Exp
::
Tag
().
Match
(
tagBuffer
);
int
n
=
Exp
::
Tag
().
Match
(
tagBuffer
);
if
(
n
<=
0
)
if
(
n
<=
0
)
{
return
false
;
return
false
;
}
while
(
--
n
>=
0
)
{
while
(
--
n
>=
0
)
{
out
<<
tagBuffer
[
0
];
out
<<
tagBuffer
[
0
];
...
...
test/integration/emitter_test.cpp
View file @
bc86fd4a
...
@@ -956,6 +956,12 @@ TEST_F(EmitterTest, ForceSingleQuotedToDouble) {
...
@@ -956,6 +956,12 @@ TEST_F(EmitterTest, ForceSingleQuotedToDouble) {
ExpectEmit
(
"
\"
Hello
\\
nWorld
\"
"
);
ExpectEmit
(
"
\"
Hello
\\
nWorld
\"
"
);
}
}
TEST_F
(
EmitterTest
,
QuoteNull
)
{
out
<<
"null"
;
ExpectEmit
(
"
\"
null
\"
"
);
}
class
EmitterErrorTest
:
public
::
testing
::
Test
{
class
EmitterErrorTest
:
public
::
testing
::
Test
{
protected:
protected:
void
ExpectEmitError
(
const
std
::
string
&
expectedError
)
{
void
ExpectEmitError
(
const
std
::
string
&
expectedError
)
{
...
...
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