Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
R
rapidjson
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
rapidjson
Commits
ba50fe7d
Commit
ba50fe7d
authored
Jun 30, 2014
by
Milo Yip
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #27 from miloyip/issue23errorcode
Issue23errorcode
parents
d8ed6095
389fe87c
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
272 additions
and
137 deletions
+272
-137
condense.cpp
example/condense/condense.cpp
+2
-1
pretty.cpp
example/pretty/pretty.cpp
+2
-1
prettyauto.cpp
example/prettyauto/prettyauto.cpp
+2
-1
document.h
include/rapidjson/document.h
+6
-6
en.h
include/rapidjson/error/en.h
+48
-0
error.h
include/rapidjson/error/error.h
+46
-0
reader.h
include/rapidjson/reader.h
+62
-34
readertest.cpp
test/unittest/readertest.cpp
+104
-94
No files found.
example/condense/condense.cpp
View file @
ba50fe7d
...
...
@@ -7,6 +7,7 @@
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
using
namespace
rapidjson
;
...
...
@@ -23,7 +24,7 @@ int main(int, char*[]) {
// JSON reader parse from the input stream and let writer generate the output.
if
(
!
reader
.
Parse
(
is
,
writer
))
{
fprintf
(
stderr
,
"
\n
Error(%u): %s
\n
"
,
(
unsigned
)
reader
.
GetErrorOffset
(),
reader
.
GetParseError
(
));
fprintf
(
stderr
,
"
\n
Error(%u): %s
\n
"
,
(
unsigned
)
reader
.
GetErrorOffset
(),
GetParseError_En
(
reader
.
GetParseErrorCode
()
));
return
1
;
}
...
...
example/pretty/pretty.cpp
View file @
ba50fe7d
...
...
@@ -5,6 +5,7 @@
#include "rapidjson/prettywriter.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
using
namespace
rapidjson
;
...
...
@@ -21,7 +22,7 @@ int main(int, char*[]) {
// JSON reader parse from the input stream and let writer generate the output.
if
(
!
reader
.
Parse
<
kParseValidateEncodingFlag
>
(
is
,
writer
))
{
fprintf
(
stderr
,
"
\n
Error(%u): %s
\n
"
,
(
unsigned
)
reader
.
GetErrorOffset
(),
reader
.
GetParseError
(
));
fprintf
(
stderr
,
"
\n
Error(%u): %s
\n
"
,
(
unsigned
)
reader
.
GetErrorOffset
(),
GetParseError_En
(
reader
.
GetParseErrorCode
()
));
return
1
;
}
...
...
example/prettyauto/prettyauto.cpp
View file @
ba50fe7d
...
...
@@ -7,6 +7,7 @@
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/encodedstream.h" // NEW
#include "rapidjson/error/en.h"
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
...
...
@@ -47,7 +48,7 @@ int main(int, char*[]) {
// JSON reader parse from the input stream and let writer generate the output.
//if (!reader.Parse<kParseValidateEncodingFlag>(is, writer)) {
if
(
!
reader
.
Parse
<
kParseValidateEncodingFlag
>
(
eis
,
writer
))
{
// CHANGED
fprintf
(
stderr
,
"
\n
Error(%u): %s
\n
"
,
(
unsigned
)
reader
.
GetErrorOffset
(),
reader
.
GetParseError
(
));
fprintf
(
stderr
,
"
\n
Error(%u): %s
\n
"
,
(
unsigned
)
reader
.
GetErrorOffset
(),
GetParseError_En
(
reader
.
GetParseErrorCode
()
));
return
1
;
}
...
...
include/rapidjson/document.h
View file @
ba50fe7d
...
...
@@ -788,7 +788,7 @@ public:
/*! \param allocator Optional allocator for allocating stack memory.
\param stackCapacity Initial capacity of stack in bytes.
*/
GenericDocument
(
Allocator
*
allocator
=
0
,
size_t
stackCapacity
=
kDefaultStackCapacity
)
:
stack_
(
allocator
,
stackCapacity
),
parseError
_
(
0
),
errorOffset_
(
0
)
{}
GenericDocument
(
Allocator
*
allocator
=
0
,
size_t
stackCapacity
=
kDefaultStackCapacity
)
:
stack_
(
allocator
,
stackCapacity
),
parseError
Code_
(
kParseErrorNone
),
errorOffset_
(
0
)
{}
//! Parse JSON text from an input stream.
/*! \tparam parseFlags Combination of ParseFlag.
...
...
@@ -802,11 +802,11 @@ public:
if
(
reader
.
template
Parse
<
parseFlags
>
(
is
,
*
this
))
{
RAPIDJSON_ASSERT
(
stack_
.
GetSize
()
==
sizeof
(
ValueType
));
// Got one and only one root object
this
->
RawAssign
(
*
stack_
.
template
Pop
<
ValueType
>
(
1
));
// Add this-> to prevent issue 13.
parseError
_
=
0
;
parseError
Code_
=
kParseErrorNone
;
errorOffset_
=
0
;
}
else
{
parseError
_
=
reader
.
GetParseError
();
parseError
Code_
=
reader
.
GetParseErrorCode
();
errorOffset_
=
reader
.
GetErrorOffset
();
ClearStack
();
}
...
...
@@ -864,10 +864,10 @@ public:
}
//! Whether a parse error was occured in the last parsing.
bool
HasParseError
()
const
{
return
parseError
_
!=
0
;
}
bool
HasParseError
()
const
{
return
parseError
Code_
!=
kParseErrorNone
;
}
//! Get the message of parsing error.
const
char
*
GetParseError
()
const
{
return
parseError
_
;
}
ParseErrorCode
GetParseError
()
const
{
return
parseErrorCode
_
;
}
//! Get the offset in character of the parsing error.
size_t
GetErrorOffset
()
const
{
return
errorOffset_
;
}
...
...
@@ -927,7 +927,7 @@ private:
static
const
size_t
kDefaultStackCapacity
=
1024
;
internal
::
Stack
<
Allocator
>
stack_
;
const
char
*
parseError
_
;
ParseErrorCode
parseErrorCode
_
;
size_t
errorOffset_
;
};
...
...
include/rapidjson/error/en.h
0 → 100644
View file @
ba50fe7d
#ifndef RAPIDJSON_ERROR_EN_H__
#define RAPIDJSON_ERROR_EN_H__
#include "error.h"
namespace
rapidjson
{
//! Maps error code of parsing into error message.
/*!
\param parseErrorCode Error code obtained in parsing.
\return the error message.
\note User can make a copy of this function for localization.
Using switch-case is safer for future modification of error codes.
*/
inline
const
RAPIDJSON_ERROR_CHARTYPE
*
GetParseError_En
(
ParseErrorCode
parseErrorCode
)
{
switch
(
parseErrorCode
)
{
case
kParseErrorNone
:
return
RAPIDJSON_ERROR_STRING
(
"No error."
);
case
kParseErrorDocumentEmpty
:
return
RAPIDJSON_ERROR_STRING
(
"The document is empty."
);
case
kParseErrorDocumentRootNotObjectOrArray
:
return
RAPIDJSON_ERROR_STRING
(
"The document root must be either object or array."
);
case
kParseErrorDocumentRootNotSingular
:
return
RAPIDJSON_ERROR_STRING
(
"The document root must not follow by other values."
);
case
kParseErrorValueInvalid
:
return
RAPIDJSON_ERROR_STRING
(
"Invalid value."
);
case
kParseErrorObjectMissName
:
return
RAPIDJSON_ERROR_STRING
(
"Missing a name for object member."
);
case
kParseErrorObjectMissColon
:
return
RAPIDJSON_ERROR_STRING
(
"Missing a colon after a name of object member."
);
case
kParseErrorObjectMissCommaOrCurlyBracket
:
return
RAPIDJSON_ERROR_STRING
(
"Missing a comma or '}' after an object member."
);
case
kParseErrorArrayMissCommaOrSquareBracket
:
return
RAPIDJSON_ERROR_STRING
(
"Missing a comma or ']' after an array element."
);
case
kParseErrorStringUnicodeEscapeInvalidHex
:
return
RAPIDJSON_ERROR_STRING
(
"Incorrect hex digit after
\\
u escape in string."
);
case
kParseErrorStringUnicodeSurrogateInvalid
:
return
RAPIDJSON_ERROR_STRING
(
"The surrogate pair in string is invalid."
);
case
kParseErrorStringEscapeInvalid
:
return
RAPIDJSON_ERROR_STRING
(
"Invalid escape character in string."
);
case
kParseErrorStringMissQuotationMark
:
return
RAPIDJSON_ERROR_STRING
(
"Missing a closing quotation mark in string."
);
case
kParseErrorStringInvalidEncoding
:
return
RAPIDJSON_ERROR_STRING
(
"Invalid encoidng in string."
);
case
kParesErrorNumberTooBig
:
return
RAPIDJSON_ERROR_STRING
(
"Number too big to be stored in double."
);
case
kParseErrorNumberMissFraction
:
return
RAPIDJSON_ERROR_STRING
(
"Miss fraction part in number."
);
case
kParseErrorNumberMissExponent
:
return
RAPIDJSON_ERROR_STRING
(
"Miss exponent in number."
);
default
:
return
RAPIDJSON_ERROR_STRING
(
"Unknown error."
);
}
}
}
// namespace rapidjson
#endif // RAPIDJSON_ERROR_EN_H__
include/rapidjson/error/error.h
0 → 100644
View file @
ba50fe7d
#ifndef RAPIDJSON_ERROR_ERROR_H__
#define RAPIDJSON_ERROR_ERROR_H__
#include "../reader.h" // ParseErrorCode
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_ERROR_CHARTYPE
//! Character type of error messages.
/*! The default charater type is char.
On Windows, user can define this macro as TCHAR for supporting both
unicode/non-unicode settings.
*/
#ifndef RAPIDJSON_ERROR_CHARTYPE
#define RAPIDJSON_ERROR_CHARTYPE char
#endif
///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_ERROR_STRING
//! Macro for converting string literial to RAPIDJSON_ERROR_CHARTYPE[].
/*! By default this conversion macro does nothing.
On Windows, user can define this macro as _T(x) for supporting both
unicode/non-unicode settings.
*/
#ifndef RAPIDJSON_ERROR_STRING
#define RAPIDJSON_ERROR_STRING(x) x
#endif
namespace
rapidjson
{
//! Function pointer type of GetParseError().
/*! This is the prototype for GetParseError_X(), where X is a locale.
User can dynamically change locale in runtime, e.g.:
\code
GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
\endcode
*/
typedef
const
RAPIDJSON_ERROR_CHARTYPE
*
(
*
GetParseErrorFunc
)(
ParseErrorCode
);
}
// namespace rapidjson
#endif // RAPIDJSON_ERROR_ERROR_H__
include/rapidjson/reader.h
View file @
ba50fe7d
...
...
@@ -21,19 +21,18 @@
#endif
#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
#define RAPIDJSON_PARSE_ERROR_NORETURN(
msg
, offset) \
#define RAPIDJSON_PARSE_ERROR_NORETURN(
parseErrorCode
, offset) \
RAPIDJSON_MULTILINEMACRO_BEGIN
\
if
(
!
HasParseError
())
{
\
parseError_
=
msg
;
\
RAPIDJSON_ASSERT
(
!
HasParseError
());
/* Error can only be assigned once */
\
parseErrorCode_
=
parseErrorCode
;
\
errorOffset_
=
offset
;
\
}
\
RAPIDJSON_MULTILINEMACRO_END
RAPIDJSON_MULTILINEMACRO_END
#endif
#ifndef RAPIDJSON_PARSE_ERROR
#define RAPIDJSON_PARSE_ERROR(
msg
, offset) \
#define RAPIDJSON_PARSE_ERROR(
parseErrorCode
, offset) \
RAPIDJSON_MULTILINEMACRO_BEGIN
\
RAPIDJSON_PARSE_ERROR_NORETURN
(
msg
,
offset
);
\
RAPIDJSON_PARSE_ERROR_NORETURN
(
parseErrorCode
,
offset
);
\
return
;
\
RAPIDJSON_MULTILINEMACRO_END
#endif
...
...
@@ -50,6 +49,33 @@ enum ParseFlag {
kParseValidateEncodingFlag
=
2
//!< Validate encoding of JSON strings.
};
//! Error code of parsing.
enum
ParseErrorCode
{
kParseErrorNone
=
0
,
//!< No error.
kParseErrorDocumentEmpty
,
//!< The document is empty.
kParseErrorDocumentRootNotObjectOrArray
,
//!< The document root must be either object or array.
kParseErrorDocumentRootNotSingular
,
//!< The document root must not follow by other values.
kParseErrorValueInvalid
,
//!< Invalid value.
kParseErrorObjectMissName
,
//!< Missing a name for object member.
kParseErrorObjectMissColon
,
//!< Missing a colon after a name of object member.
kParseErrorObjectMissCommaOrCurlyBracket
,
//!< Missing a comma or '}' after an object member.
kParseErrorArrayMissCommaOrSquareBracket
,
//!< Missing a comma or ']' after an array element.
kParseErrorStringUnicodeEscapeInvalidHex
,
//!< Incorrect hex digit after \\u escape in string.
kParseErrorStringUnicodeSurrogateInvalid
,
//!< The surrogate pair in string is invalid.
kParseErrorStringEscapeInvalid
,
//!< Invalid escape character in string.
kParseErrorStringMissQuotationMark
,
//!< Missing a closing quotation mark in string.
kParseErrorStringInvalidEncoding
,
//!< Invalid encoidng in string.
kParesErrorNumberTooBig
,
//!< Number too big to be stored in double.
kParseErrorNumberMissFraction
,
//!< Miss fraction part in number.
kParseErrorNumberMissExponent
//!< Miss exponent in number.
};
///////////////////////////////////////////////////////////////////////////////
// Handler
...
...
@@ -218,7 +244,7 @@ public:
/*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
*/
GenericReader
(
Allocator
*
allocator
=
0
,
size_t
stackCapacity
=
kDefaultStackCapacity
)
:
stack_
(
allocator
,
stackCapacity
),
parseError
_
(
0
),
errorOffset_
(
0
)
{}
GenericReader
(
Allocator
*
allocator
=
0
,
size_t
stackCapacity
=
kDefaultStackCapacity
)
:
stack_
(
allocator
,
stackCapacity
),
parseError
Code_
(
kParseErrorNone
),
errorOffset_
(
0
)
{}
//! Parse JSON text.
/*! \tparam parseFlags Combination of ParseFlag.
...
...
@@ -230,18 +256,18 @@ public:
*/
template
<
unsigned
parseFlags
,
typename
InputStream
,
typename
Handler
>
bool
Parse
(
InputStream
&
is
,
Handler
&
handler
)
{
parseError
_
=
0
;
parseError
Code_
=
kParseErrorNone
;
errorOffset_
=
0
;
SkipWhitespace
(
is
);
if
(
is
.
Peek
()
==
'\0'
)
RAPIDJSON_PARSE_ERROR_NORETURN
(
"Text only contains white space(s)"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR_NORETURN
(
kParseErrorDocumentEmpty
,
is
.
Tell
());
else
{
switch
(
is
.
Peek
())
{
case
'{'
:
ParseObject
<
parseFlags
>
(
is
,
handler
);
break
;
case
'['
:
ParseArray
<
parseFlags
>
(
is
,
handler
);
break
;
default
:
RAPIDJSON_PARSE_ERROR_NORETURN
(
"Expect either an object or array at root"
,
is
.
Tell
());
default
:
RAPIDJSON_PARSE_ERROR_NORETURN
(
kParseErrorDocumentRootNotObjectOrArray
,
is
.
Tell
());
}
if
(
HasParseError
())
goto
out
;
...
...
@@ -249,7 +275,7 @@ public:
SkipWhitespace
(
is
);
if
(
is
.
Peek
()
!=
'\0'
)
RAPIDJSON_PARSE_ERROR_NORETURN
(
"Nothing should follow the root object or array."
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR_NORETURN
(
kParseErrorDocumentRootNotSingular
,
is
.
Tell
());
}
out
:
...
...
@@ -262,8 +288,10 @@ public:
return
Parse
<
0
>
(
is
,
handler
);
}
bool
HasParseError
()
const
{
return
parseError_
!=
0
;
}
const
char
*
GetParseError
()
const
{
return
parseError_
;
}
bool
HasParseError
()
const
{
return
parseErrorCode_
!=
kParseErrorNone
;
}
ParseErrorCode
GetParseErrorCode
()
const
{
return
parseErrorCode_
;
}
size_t
GetErrorOffset
()
const
{
return
errorOffset_
;
}
private
:
...
...
@@ -283,7 +311,7 @@ private:
for
(
SizeType
memberCount
=
0
;;)
{
if
(
is
.
Peek
()
!=
'"'
)
RAPIDJSON_PARSE_ERROR
(
"Name of an object member must be a string"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorObjectMissName
,
is
.
Tell
());
ParseString
<
parseFlags
>
(
is
,
handler
);
if
(
HasParseError
())
...
...
@@ -292,7 +320,7 @@ private:
SkipWhitespace
(
is
);
if
(
is
.
Take
()
!=
':'
)
RAPIDJSON_PARSE_ERROR
(
"There must be a colon after the name of object member"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorObjectMissColon
,
is
.
Tell
());
SkipWhitespace
(
is
);
...
...
@@ -307,7 +335,7 @@ private:
switch
(
is
.
Take
())
{
case
','
:
SkipWhitespace
(
is
);
break
;
case
'}'
:
handler
.
EndObject
(
memberCount
);
return
;
default
:
RAPIDJSON_PARSE_ERROR
(
"Must be a comma or '}' after an object member"
,
is
.
Tell
());
default
:
RAPIDJSON_PARSE_ERROR
(
kParseErrorObjectMissCommaOrCurlyBracket
,
is
.
Tell
());
}
}
}
...
...
@@ -337,7 +365,7 @@ private:
switch
(
is
.
Take
())
{
case
','
:
SkipWhitespace
(
is
);
break
;
case
']'
:
handler
.
EndArray
(
elementCount
);
return
;
default
:
RAPIDJSON_PARSE_ERROR
(
"Must be a comma or ']' after an array element."
,
is
.
Tell
());
default
:
RAPIDJSON_PARSE_ERROR
(
kParseErrorArrayMissCommaOrSquareBracket
,
is
.
Tell
());
}
}
}
...
...
@@ -350,7 +378,7 @@ private:
if
(
is
.
Take
()
==
'u'
&&
is
.
Take
()
==
'l'
&&
is
.
Take
()
==
'l'
)
handler
.
Null
();
else
RAPIDJSON_PARSE_ERROR
(
"Invalid value"
,
is
.
Tell
()
-
1
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorValueInvalid
,
is
.
Tell
()
-
1
);
}
template
<
unsigned
parseFlags
,
typename
InputStream
,
typename
Handler
>
...
...
@@ -361,7 +389,7 @@ private:
if
(
is
.
Take
()
==
'r'
&&
is
.
Take
()
==
'u'
&&
is
.
Take
()
==
'e'
)
handler
.
Bool
(
true
);
else
RAPIDJSON_PARSE_ERROR
(
"Invalid value"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorValueInvalid
,
is
.
Tell
());
}
template
<
unsigned
parseFlags
,
typename
InputStream
,
typename
Handler
>
...
...
@@ -372,7 +400,7 @@ private:
if
(
is
.
Take
()
==
'a'
&&
is
.
Take
()
==
'l'
&&
is
.
Take
()
==
's'
&&
is
.
Take
()
==
'e'
)
handler
.
Bool
(
false
);
else
RAPIDJSON_PARSE_ERROR
(
"Invalid value"
,
is
.
Tell
()
-
1
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorValueInvalid
,
is
.
Tell
()
-
1
);
}
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
...
...
@@ -391,7 +419,7 @@ private:
else
if
(
c
>=
'a'
&&
c
<=
'f'
)
codepoint
-=
'a'
-
10
;
else
{
RAPIDJSON_PARSE_ERROR_NORETURN
(
"Incorrect hex digit after
\\
u escape"
,
s
.
Tell
()
-
1
);
RAPIDJSON_PARSE_ERROR_NORETURN
(
kParseErrorStringUnicodeEscapeInvalidHex
,
s
.
Tell
()
-
1
);
return
0
;
}
}
...
...
@@ -468,16 +496,16 @@ private:
if
(
codepoint
>=
0xD800
&&
codepoint
<=
0xDBFF
)
{
// Handle UTF-16 surrogate pair
if
(
is
.
Take
()
!=
'\\'
||
is
.
Take
()
!=
'u'
)
RAPIDJSON_PARSE_ERROR
(
"Missing the second
\\
u in surrogate pair"
,
is
.
Tell
()
-
2
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorStringUnicodeSurrogateInvalid
,
is
.
Tell
()
-
2
);
unsigned
codepoint2
=
ParseHex4
(
is
);
if
(
codepoint2
<
0xDC00
||
codepoint2
>
0xDFFF
)
RAPIDJSON_PARSE_ERROR
(
"The second
\\
u in surrogate pair is invalid"
,
is
.
Tell
()
-
2
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorStringUnicodeSurrogateInvalid
,
is
.
Tell
()
-
2
);
codepoint
=
(((
codepoint
-
0xD800
)
<<
10
)
|
(
codepoint2
-
0xDC00
))
+
0x10000
;
}
TEncoding
::
Encode
(
os
,
codepoint
);
}
else
RAPIDJSON_PARSE_ERROR
(
"Unknown escape character"
,
is
.
Tell
()
-
1
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorStringEscapeInvalid
,
is
.
Tell
()
-
1
);
}
else
if
(
c
==
'"'
)
{
// Closing double quote
is
.
Take
();
...
...
@@ -485,14 +513,14 @@ private:
return
;
}
else
if
(
c
==
'\0'
)
RAPIDJSON_PARSE_ERROR
(
"lacks ending quotation before the end of string"
,
is
.
Tell
()
-
1
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorStringMissQuotationMark
,
is
.
Tell
()
-
1
);
else
if
((
unsigned
)
c
<
0x20
)
// RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
RAPIDJSON_PARSE_ERROR
(
"Incorrect unescaped character in string"
,
is
.
Tell
()
-
1
);
RAPIDJSON_PARSE_ERROR
(
kParseErrorStringEscapeInvalid
,
is
.
Tell
()
-
1
);
else
{
if
(
parseFlags
&
kParseValidateEncodingFlag
?
!
Transcoder
<
SEncoding
,
TEncoding
>::
Validate
(
is
,
os
)
:
!
Transcoder
<
SEncoding
,
TEncoding
>::
Transcode
(
is
,
os
))
RAPIDJSON_PARSE_ERROR
(
"Invalid encoding"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorStringInvalidEncoding
,
is
.
Tell
());
}
}
}
...
...
@@ -539,7 +567,7 @@ private:
}
}
else
RAPIDJSON_PARSE_ERROR
(
"Expect a value here."
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorValueInvalid
,
is
.
Tell
());
// Parse 64bit int
uint64_t
i64
=
0
;
...
...
@@ -572,7 +600,7 @@ private:
d
=
(
double
)
i64
;
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
if
(
d
>=
1E307
)
RAPIDJSON_PARSE_ERROR
(
"Number too big to store in double"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParesErrorNumberTooBig
,
is
.
Tell
());
d
=
d
*
10
+
(
s
.
Take
()
-
'0'
);
}
}
...
...
@@ -591,7 +619,7 @@ private:
--
expFrac
;
}
else
RAPIDJSON_PARSE_ERROR
(
"At least one digit in fraction part"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorNumberMissFraction
,
is
.
Tell
());
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
if
(
expFrac
>
-
16
)
{
...
...
@@ -624,11 +652,11 @@ private:
while
(
s
.
Peek
()
>=
'0'
&&
s
.
Peek
()
<=
'9'
)
{
exp
=
exp
*
10
+
(
s
.
Take
()
-
'0'
);
if
(
exp
>
308
)
RAPIDJSON_PARSE_ERROR
(
"Number too big to store in double"
,
is
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParesErrorNumberTooBig
,
is
.
Tell
());
}
}
else
RAPIDJSON_PARSE_ERROR
(
"At least one digit in exponent"
,
s
.
Tell
());
RAPIDJSON_PARSE_ERROR
(
kParseErrorNumberMissExponent
,
s
.
Tell
());
if
(
expMinus
)
exp
=
-
exp
;
...
...
@@ -673,7 +701,7 @@ private:
static
const
size_t
kDefaultStackCapacity
=
256
;
//!< Default stack capacity in bytes for storing a single decoded string.
internal
::
Stack
<
Allocator
>
stack_
;
//!< A stack for storing decoded string temporarily during non-destructive parsing.
const
char
*
parseError
_
;
ParseErrorCode
parseErrorCode
_
;
size_t
errorOffset_
;
};
// class GenericReader
...
...
test/unittest/readertest.cpp
View file @
ba50fe7d
...
...
@@ -147,8 +147,8 @@ TEST(Reader, ParseNumberHandler) {
#undef TEST_DOUBLE
}
TEST
(
Reader
,
ParseNumber
Handler
_Error
)
{
#define TEST_NUMBER_ERROR(str) \
TEST
(
Reader
,
ParseNumber_Error
)
{
#define TEST_NUMBER_ERROR(
errorCode,
str) \
{
\
char
buffer
[
1001
];
\
sprintf
(
buffer
,
"[%s]"
,
str
);
\
...
...
@@ -156,23 +156,27 @@ TEST(Reader, ParseNumberHandler_Error) {
BaseReaderHandler
<>
h
;
\
Reader
reader
;
\
EXPECT_FALSE
(
reader
.
Parse
<
0
>
(
s
,
h
));
\
EXPECT_EQ
(
errorCode
,
reader
.
GetParseErrorCode
());
\
}
TEST_NUMBER_ERROR
(
"a"
);
// At least one digit in integer part
TEST_NUMBER_ERROR
(
".1"
);
// At least one digit in integer part
// Number too big to be stored in double.
{
char
n1e309
[
311
];
// '1' followed by 309 '0'
n1e309
[
0
]
=
'1'
;
for
(
int
i
=
1
;
i
<
310
;
i
++
)
n1e309
[
i
]
=
'0'
;
n1e309
[
310
]
=
'\0'
;
TEST_NUMBER_ERROR
(
n1e309
);
// Number too big to store in double
TEST_NUMBER_ERROR
(
kParesErrorNumberTooBig
,
n1e309
);
}
TEST_NUMBER_ERROR
(
kParesErrorNumberTooBig
,
"1e309"
);
// Miss fraction part in number.
TEST_NUMBER_ERROR
(
kParseErrorNumberMissFraction
,
"1."
);
TEST_NUMBER_ERROR
(
kParseErrorNumberMissFraction
,
"1.a"
);
TEST_NUMBER_ERROR
(
"1."
);
// At least one digit in fraction part
TEST_NUMBER_ERROR
(
"1e309"
);
// Number too big to store in double
TEST_NUMBER_ERROR
(
"1e_"
);
// At least one digit in exponent
// Miss exponent in number.
TEST_NUMBER_ERROR
(
kParseErrorNumberMissExponent
,
"1e"
);
TEST_NUMBER_ERROR
(
kParseErrorNumberMissExponent
,
"1e_"
);
#undef TEST_NUMBER_ERROR
}
...
...
@@ -304,27 +308,38 @@ TEST(Reader, ParseString_NonDestructive) {
EXPECT_EQ
(
11u
,
h
.
length_
);
}
bool
TestString
(
const
char
*
str
)
{
ParseErrorCode
TestString
(
const
char
*
str
)
{
StringStream
s
(
str
);
BaseReaderHandler
<>
h
;
Reader
reader
;
return
reader
.
Parse
<
kParseValidateEncodingFlag
>
(
s
,
h
);
reader
.
Parse
<
kParseValidateEncodingFlag
>
(
s
,
h
);
return
reader
.
GetParseErrorCode
();
}
TEST
(
Reader
,
ParseString_Error
)
{
#define TEST_STRING_ERROR(errorCode, str)\
EXPECT_EQ
(
errorCode
,
TestString
(
str
))
#define ARRAY(...) { __VA_ARGS__ }
#define TEST_STRING
ARRAY
_ERROR(Encoding, utype, array) \
#define TEST_STRING
ENCODING
_ERROR(Encoding, utype, array) \
{
\
static
const
utype
ue
[]
=
array
;
\
static
const
Encoding
::
Ch
*
e
=
reinterpret_cast
<
const
Encoding
::
Ch
*>
(
&
ue
[
0
]);
\
EXPECT_
FALSE
(
TestString
(
e
));
\
EXPECT_
EQ
(
kParseErrorStringInvalidEncoding
,
TestString
(
e
));
\
}
EXPECT_FALSE
(
TestString
(
"[
\"\\
a
\"
]"
));
// Unknown escape character
EXPECT_FALSE
(
TestString
(
"[
\"\\
uABCG
\"
]"
));
// Incorrect hex digit after \\u escape
EXPECT_FALSE
(
TestString
(
"[
\"\\
uD800X
\"
]"
));
// Missing the second \\u in surrogate pair
EXPECT_FALSE
(
TestString
(
"[
\"\\
uD800
\\
uFFFF
\"
]"
));
// The second \\u in surrogate pair is invalid
EXPECT_FALSE
(
TestString
(
"[
\"
Test]"
));
// lacks ending quotation before the end of string
// Invalid escape character in string.
TEST_STRING_ERROR
(
kParseErrorStringEscapeInvalid
,
"[
\"\\
a
\"
]"
);
// Incorrect hex digit after \\u escape in string.
TEST_STRING_ERROR
(
kParseErrorStringUnicodeEscapeInvalidHex
,
"[
\"\\
uABCG
\"
]"
);
// The surrogate pair in string is invalid.
TEST_STRING_ERROR
(
kParseErrorStringUnicodeSurrogateInvalid
,
"[
\"\\
uD800X
\"
]"
);
TEST_STRING_ERROR
(
kParseErrorStringUnicodeSurrogateInvalid
,
"[
\"\\
uD800
\\
uFFFF
\"
]"
);
// Missing a closing quotation mark in string.
TEST_STRING_ERROR
(
kParseErrorStringMissQuotationMark
,
"[
\"
Test]"
);
// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
...
...
@@ -335,9 +350,9 @@ TEST(Reader, ParseString_Error) {
char
e
[]
=
{
'['
,
'\"'
,
0
,
'\"'
,
']'
,
'\0'
};
for
(
unsigned
char
c
=
0x80u
;
c
<=
0xBFu
;
c
++
)
{
e
[
2
]
=
c
;
bool
b
=
TestString
(
e
);
EXPECT_
FALSE
(
b
);
if
(
b
)
ParseErrorCode
error
=
TestString
(
e
);
EXPECT_
EQ
(
kParseErrorStringInvalidEncoding
,
error
);
if
(
error
!=
kParseErrorStringInvalidEncoding
)
std
::
cout
<<
(
unsigned
)(
unsigned
char
)
c
<<
std
::
endl
;
}
}
...
...
@@ -347,37 +362,37 @@ TEST(Reader, ParseString_Error) {
char
e
[]
=
{
'['
,
'\"'
,
0
,
' '
,
'\"'
,
']'
,
'\0'
};
for
(
unsigned
c
=
0xC0u
;
c
<=
0xFFu
;
c
++
)
{
e
[
2
]
=
(
char
)
c
;
EXPECT_FALSE
(
TestString
(
e
)
);
TEST_STRING_ERROR
(
kParseErrorStringInvalidEncoding
,
e
);
}
}
// 4 Overlong sequences
// 4.1 Examples of an overlong ASCII character
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xC0u
,
0xAFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xE0u
,
0x80u
,
0xAFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xF0u
,
0x80u
,
0x80u
,
0xAFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xC0u
,
0xAFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xE0u
,
0x80u
,
0xAFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xF0u
,
0x80u
,
0x80u
,
0xAFu
,
'\"'
,
']'
,
'\0'
));
// 4.2 Maximum overlong sequences
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xC1u
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xE0u
,
0x9Fu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xF0u
,
0x8Fu
,
0xBFu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xC1u
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xE0u
,
0x9Fu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xF0u
,
0x8Fu
,
0xBFu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
// 4.3 Overlong representation of the NUL character
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xC0u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xE0u
,
0x80u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xF0u
,
0x80u
,
0x80u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xC0u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xE0u
,
0x80u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xF0u
,
0x80u
,
0x80u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
// 5 Illegal code positions
// 5.1 Single UTF-16 surrogates
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xA0u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xADu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xAEu
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xAFu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xB0u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xBEu
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ARRAY
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xBFu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xA0u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xADu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xAEu
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xAFu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xB0u
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xBEu
,
0x80u
,
'\"'
,
']'
,
'\0'
));
TEST_STRING
ENCODING
_ERROR
(
UTF8
<>
,
unsigned
char
,
ARRAY
(
'['
,
'\"'
,
0xEDu
,
0xBFu
,
0xBFu
,
'\"'
,
']'
,
'\0'
));
#undef ARRAY
#undef TEST_STRINGARRAY_ERROR
...
...
@@ -416,7 +431,7 @@ TEST(Reader, ParseArray) {
}
TEST
(
Reader
,
ParseArray_Error
)
{
#define TEST_ARRAY_ERROR(str) \
#define TEST_ARRAY_ERROR(
errorCode,
str) \
{
\
char
buffer
[
1001
];
\
strncpy
(
buffer
,
str
,
1000
);
\
...
...
@@ -424,12 +439,13 @@ TEST(Reader, ParseArray_Error) {
BaseReaderHandler
<>
h
;
\
GenericReader
<
UTF8
<>
,
UTF8
<>
,
CrtAllocator
>
reader
;
\
EXPECT_FALSE
(
reader
.
Parse
<
0
>
(
s
,
h
));
\
EXPECT_EQ
(
errorCode
,
reader
.
GetParseErrorCode
());
\
}
// M
ust be
a comma or ']' after an array element.
TEST_ARRAY_ERROR
(
"[
"
);
TEST_ARRAY_ERROR
(
"[
}"
);
TEST_ARRAY_ERROR
(
"[1 2]"
);
// M
issing
a comma or ']' after an array element.
TEST_ARRAY_ERROR
(
kParseErrorArrayMissCommaOrSquareBracket
,
"[1
"
);
TEST_ARRAY_ERROR
(
kParseErrorArrayMissCommaOrSquareBracket
,
"[1
}"
);
TEST_ARRAY_ERROR
(
kParseErrorArrayMissCommaOrSquareBracket
,
"[1 2]"
);
#undef TEST_ARRAY_ERROR
}
...
...
@@ -519,39 +535,7 @@ TEST(Reader, Parse_EmptyObject) {
EXPECT_EQ
(
2u
,
h
.
step_
);
}
TEST
(
Reader
,
ParseObject_Error
)
{
#define TEST_OBJECT_ERROR(str) \
{
\
char
buffer
[
1001
];
\
strncpy
(
buffer
,
str
,
1000
);
\
InsituStringStream
s
(
buffer
);
\
BaseReaderHandler
<>
h
;
\
GenericReader
<
UTF8
<>
,
UTF8
<>
,
CrtAllocator
>
reader
;
\
EXPECT_FALSE
(
reader
.
Parse
<
0
>
(
s
,
h
));
\
}
// Name of an object member must be a string
TEST_OBJECT_ERROR
(
"{null:1}"
);
TEST_OBJECT_ERROR
(
"{true:1}"
);
TEST_OBJECT_ERROR
(
"{false:1}"
);
TEST_OBJECT_ERROR
(
"{1:1}"
);
TEST_OBJECT_ERROR
(
"{[]:1}"
);
TEST_OBJECT_ERROR
(
"{{}:1}"
);
TEST_OBJECT_ERROR
(
"{xyz:1}"
);
// There must be a colon after the name of object member
TEST_OBJECT_ERROR
(
"{
\"
a
\"
1}"
);
TEST_OBJECT_ERROR
(
"{
\"
a
\"
,1}"
);
// Must be a comma or '}' after an object member
TEST_OBJECT_ERROR
(
"{]"
);
TEST_OBJECT_ERROR
(
"{
\"
a
\"
:1]"
);
#undef TEST_OBJECT_ERROR
}
TEST
(
Reader
,
Parse_Error
)
{
#define TEST_ERROR(str) \
#define TEST_ERROR(errorCode, str) \
{
\
char
buffer
[
1001
];
\
strncpy
(
buffer
,
str
,
1000
);
\
...
...
@@ -559,31 +543,57 @@ TEST(Reader, Parse_Error) {
BaseReaderHandler
<>
h
;
\
Reader
reader
;
\
EXPECT_FALSE
(
reader
.
Parse
<
0
>
(
s
,
h
));
\
EXPECT_EQ
(
errorCode
,
reader
.
GetParseErrorCode
());
\
}
// Text only contains white space(s)
TEST_ERROR
(
""
);
TEST_ERROR
(
" "
);
TEST_ERROR
(
"
\n
"
);
TEST
(
Reader
,
ParseDocument_Error
)
{
// The document is empty.
TEST_ERROR
(
kParseErrorDocumentEmpty
,
""
);
TEST_ERROR
(
kParseErrorDocumentEmpty
,
" "
);
TEST_ERROR
(
kParseErrorDocumentEmpty
,
"
\n
"
);
// The document root must be either object or array.
TEST_ERROR
(
kParseErrorDocumentRootNotObjectOrArray
,
"null"
);
TEST_ERROR
(
kParseErrorDocumentRootNotObjectOrArray
,
"true"
);
TEST_ERROR
(
kParseErrorDocumentRootNotObjectOrArray
,
"false"
);
TEST_ERROR
(
kParseErrorDocumentRootNotObjectOrArray
,
"
\"
s
\"
"
);
TEST_ERROR
(
kParseErrorDocumentRootNotObjectOrArray
,
"0"
);
// The document root must not follow by other values.
TEST_ERROR
(
kParseErrorDocumentRootNotSingular
,
"[] 0"
);
TEST_ERROR
(
kParseErrorDocumentRootNotSingular
,
"{} 0"
);
}
// Expect either an object or array at root
TEST_ERROR
(
"null"
);
TEST_ERROR
(
"true"
);
TEST_ERROR
(
"false"
);
TEST_ERROR
(
"
\"
s
\"
"
);
TEST_ERROR
(
"0"
);
TEST
(
Reader
,
ParseValue_Error
)
{
// Invalid value.
TEST_ERROR
(
kParseErrorValueInvalid
,
"[nulL]"
);
TEST_ERROR
(
kParseErrorValueInvalid
,
"[truE]"
);
TEST_ERROR
(
kParseErrorValueInvalid
,
"[falsE]"
);
TEST_ERROR
(
kParseErrorValueInvalid
,
"[a]"
);
TEST_ERROR
(
kParseErrorValueInvalid
,
"[.1]"
);
}
// Nothing should follow the root object or array
TEST_ERROR
(
"[] 0"
);
TEST_ERROR
(
"{} 0"
);
TEST
(
Reader
,
ParseObject_Error
)
{
// Missing a name for object member.
TEST_ERROR
(
kParseErrorObjectMissName
,
"{1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{null:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{true:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{false:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{1:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{[]:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{{}:1}"
);
TEST_ERROR
(
kParseErrorObjectMissName
,
"{xyz:1}"
);
// Missing a colon after a name of object member.
TEST_ERROR
(
kParseErrorObjectMissColon
,
"{
\"
a
\"
1}"
);
TEST_ERROR
(
kParseErrorObjectMissColon
,
"{
\"
a
\"
,1}"
);
// Invalid value
TEST_ERROR
(
"nulL"
);
TEST_ERROR
(
"truE"
);
TEST_ERROR
(
"falsE"
);
// Must be a comma or '}' after an object member
TEST_ERROR
(
kParseErrorObjectMissCommaOrCurlyBracket
,
"{
\"
a
\"
:1]"
);
}
#undef TEST_ERROR
}
TEST
(
Reader
,
SkipWhitespace
)
{
StringStream
ss
(
" A
\t\t
B
\n
\n\n
C
\r\r
\r
D
\t\n\r
E"
);
...
...
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