未验证 提交 cdae258b 编写于 作者: G Gareth Sylvester-Bradley 提交者: GitHub

[#1349] Expose json::value::parse for UTF8 string on Windows (#1350)

上级 cb7ca74e
......@@ -390,17 +390,37 @@ public:
/// <summary>
/// Parses a string and construct a JSON value.
/// </summary>
/// <param name="value">The C++ value to create a JSON value from, a C++ STL double-byte string</param>
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string of the
/// platform-native character width</param>
_ASYNCRTIMP static value __cdecl parse(const utility::string_t& value);
/// <summary>
/// Attempts to parse a string and construct a JSON value.
/// </summary>
/// <param name="value">The C++ value to create a JSON value from, a C++ STL double-byte string</param>
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string of the
/// platform-native character width</param>
/// <param name="errorCode">If parsing fails, the error code is greater than 0</param>
/// <returns>The parsed object. Returns web::json::value::null if failed</returns>
_ASYNCRTIMP static value __cdecl parse(const utility::string_t& value, std::error_code& errorCode);
#ifdef _WIN32
/// <summary>
/// Parses a string and construct a JSON value.
/// </summary>
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string in
/// UTF8 format</param>
_ASYNCRTIMP static value __cdecl parse(const std::string& value);
/// <summary>
/// Attempts to parse a string and construct a JSON value.
/// </summary>
/// <param name="value">The C++ value to create a JSON value from, a C++ STL string in
/// UTF8 format</param>
/// <param name="errorCode">If parsing fails, the error code is greater than 0</param>
/// <returns>The parsed object. Returns web::json::value::null if failed</returns>
_ASYNCRTIMP static value __cdecl parse(const std::string& value, std::error_code& errorCode);
#endif
/// <summary>
/// Serializes the current JSON value to a C++ string.
/// </summary>
......
......@@ -1120,10 +1120,11 @@ std::unique_ptr<web::json::details::_Value> JSON_Parser<CharType>::_ParseValue(
} // namespace json
} // namespace web
static web::json::value _parse_stream(utility::istream_t& stream)
template<typename CharType>
static web::json::value _parse_stream(std::basic_istream<CharType>& stream)
{
web::json::details::JSON_StreamParser<utility::char_t> parser(stream);
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
web::json::details::JSON_StreamParser<CharType> parser(stream);
typename web::json::details::JSON_Parser<CharType>::Token tkn;
parser.GetNextToken(tkn);
if (tkn.m_error)
......@@ -1136,7 +1137,7 @@ static web::json::value _parse_stream(utility::istream_t& stream)
{
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
}
else if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
else if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
{
web::json::details::CreateException(tkn,
_XPLATSTR("Left-over characters in stream after parsing a JSON value"));
......@@ -1144,10 +1145,11 @@ static web::json::value _parse_stream(utility::istream_t& stream)
return value;
}
static web::json::value _parse_stream(utility::istream_t& stream, std::error_code& error)
template<typename CharType>
static web::json::value _parse_stream(std::basic_istream<CharType>& stream, std::error_code& error)
{
web::json::details::JSON_StreamParser<utility::char_t> parser(stream);
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
web::json::details::JSON_StreamParser<CharType> parser(stream);
typename web::json::details::JSON_Parser<CharType>::Token tkn;
parser.GetNextToken(tkn);
if (tkn.m_error)
......@@ -1157,7 +1159,7 @@ static web::json::value _parse_stream(utility::istream_t& stream, std::error_cod
}
auto returnObject = parser.ParseValue(tkn);
if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
{
web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream);
}
......@@ -1166,11 +1168,11 @@ static web::json::value _parse_stream(utility::istream_t& stream, std::error_cod
return returnObject;
}
#ifdef _WIN32
static web::json::value _parse_narrow_stream(std::istream& stream)
template<typename CharType>
static web::json::value _parse_string(const std::basic_string<CharType>& str)
{
web::json::details::JSON_StreamParser<char> parser(stream);
web::json::details::JSON_StreamParser<char>::Token tkn;
web::json::details::JSON_StringParser<CharType> parser(str);
typename web::json::details::JSON_Parser<CharType>::Token tkn;
parser.GetNextToken(tkn);
if (tkn.m_error)
......@@ -1183,7 +1185,7 @@ static web::json::value _parse_narrow_stream(std::istream& stream)
{
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
}
else if (tkn.kind != web::json::details::JSON_Parser<char>::Token::TKN_EOF)
else if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
{
web::json::details::CreateException(tkn,
_XPLATSTR("Left-over characters in stream after parsing a JSON value"));
......@@ -1191,10 +1193,11 @@ static web::json::value _parse_narrow_stream(std::istream& stream)
return value;
}
static web::json::value _parse_narrow_stream(std::istream& stream, std::error_code& error)
template<typename CharType>
static web::json::value _parse_string(const std::basic_string<CharType>& str, std::error_code& error)
{
web::json::details::JSON_StreamParser<char> parser(stream);
web::json::details::JSON_StreamParser<char>::Token tkn;
web::json::details::JSON_StringParser<CharType> parser(str);
typename web::json::details::JSON_Parser<CharType>::Token tkn;
parser.GetNextToken(tkn);
if (tkn.m_error)
......@@ -1204,7 +1207,7 @@ static web::json::value _parse_narrow_stream(std::istream& stream, std::error_co
}
auto returnObject = parser.ParseValue(tkn);
if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
if (tkn.kind != web::json::details::JSON_Parser<CharType>::Token::TKN_EOF)
{
returnObject = web::json::value();
web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream);
......@@ -1213,53 +1216,12 @@ static web::json::value _parse_narrow_stream(std::istream& stream, std::error_co
error = std::move(tkn.m_error);
return returnObject;
}
#endif
web::json::value web::json::value::parse(const utility::string_t& str)
{
web::json::details::JSON_StringParser<utility::char_t> parser(str);
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
parser.GetNextToken(tkn);
if (tkn.m_error)
{
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
}
auto value = parser.ParseValue(tkn);
if (tkn.m_error)
{
web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message()));
}
else if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
{
web::json::details::CreateException(tkn,
_XPLATSTR("Left-over characters in stream after parsing a JSON value"));
}
return value;
}
web::json::value web::json::value::parse(const utility::string_t& str) { return _parse_string(str); }
web::json::value web::json::value::parse(const utility::string_t& str, std::error_code& error)
{
web::json::details::JSON_StringParser<utility::char_t> parser(str);
web::json::details::JSON_Parser<utility::char_t>::Token tkn;
parser.GetNextToken(tkn);
if (tkn.m_error)
{
error = std::move(tkn.m_error);
return web::json::value();
}
auto returnObject = parser.ParseValue(tkn);
if (tkn.kind != web::json::details::JSON_Parser<utility::char_t>::Token::TKN_EOF)
{
returnObject = web::json::value();
web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream);
}
error = std::move(tkn.m_error);
return returnObject;
return _parse_string(str, error);
}
web::json::value web::json::value::parse(utility::istream_t& stream) { return _parse_stream(stream); }
......@@ -1270,10 +1232,17 @@ web::json::value web::json::value::parse(utility::istream_t& stream, std::error_
}
#ifdef _WIN32
web::json::value web::json::value::parse(std::istream& stream) { return _parse_narrow_stream(stream); }
web::json::value web::json::value::parse(const std::string& str) { return _parse_string(str); }
web::json::value web::json::value::parse(const std::string& str, std::error_code& error)
{
return _parse_string(str, error);
}
web::json::value web::json::value::parse(std::istream& stream) { return _parse_stream(stream); }
web::json::value web::json::value::parse(std::istream& stream, std::error_code& error)
{
return _parse_narrow_stream(stream, error);
return _parse_stream(stream, error);
}
#endif
......@@ -347,7 +347,7 @@ SUITE(parsing_tests)
VERIFY_ARE_EQUAL(U("K"), str.as_string());
str = json::value::parse(U("\"\\u20AC\""));
// Euro sign as a hexidecmial UTF-8
// Euro sign as a hexadecimal UTF-8
const auto euro = to_string_t("\xE2\x82\xAC");
VERIFY_ARE_EQUAL(euro, str.as_string());
......@@ -631,30 +631,34 @@ SUITE(parsing_tests)
TEST(byte_ptr_parsing_array)
{
char s[] = "[ \"test1\",true]";
json::value v = json::value::parse(s);
std::stringstream ss;
ss << s;
json::value v = json::value::parse(ss);
auto s2 = v.serialize();
json::value vv = json::value::parse(ss);
VERIFY_ARE_EQUAL(v, vv);
auto s2 = v.serialize();
VERIFY_ARE_EQUAL(s2, U("[\"test1\",true]"));
std::stringstream os;
v.serialize(os);
vv.serialize(os);
VERIFY_ARE_EQUAL(s2, to_string_t(os.str()));
}
TEST(byte_ptr_parsing_object)
{
char s[] = "{\"test1\":true }";
json::value v = json::value::parse(s);
std::stringstream ss;
ss << s;
json::value v = json::value::parse(ss);
auto s2 = v.serialize();
json::value vv = json::value::parse(ss);
VERIFY_ARE_EQUAL(v, vv);
auto s2 = v.serialize();
VERIFY_ARE_EQUAL(s2, U("{\"test1\":true}"));
std::stringstream os;
v.serialize(os);
vv.serialize(os);
VERIFY_ARE_EQUAL(s2, to_string_t(os.str()));
}
......@@ -662,16 +666,18 @@ SUITE(parsing_tests)
{
utility::string_t ws = U("\"こんにちは\"");
std::string s = to_utf8string(ws);
json::value v = json::value::parse(s);
std::stringstream ss;
ss << s;
json::value v = json::value::parse(ss);
auto s2 = v.serialize();
json::value vv = json::value::parse(ss);
VERIFY_ARE_EQUAL(v, vv);
auto s2 = v.serialize();
VERIFY_ARE_EQUAL(s2, ws);
std::stringstream os;
v.serialize(os);
vv.serialize(os);
VERIFY_ARE_EQUAL(s2, to_string_t(os.str()));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册