Commit 6533b333 authored by Niels's avatar Niels

Merge pull request #22 from Teemperor/unicode_escaping

Unicode escaping
parents 8d9c2bea a866a9d9
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<Objective-C-extensions>
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
<option name="RELEASE_STYLE" value="IVAR" />
<file>
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="ClassPredef" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Function" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Class" />
</file>
<class>
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.objc.util.OCDeclarationKind" value="DeallocMethod" />
</class>
</Objective-C-extensions>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="ProjectRootManager" version="2" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/json.iml" filepath="$PROJECT_DIR$/.idea/json.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
...@@ -4,6 +4,9 @@ project(json) ...@@ -4,6 +4,9 @@ project(json)
# Enable C++11 and set flags for coverage testing # Enable C++11 and set flags for coverage testing
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O0 --coverage -fprofile-arcs -ftest-coverage") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O0 --coverage -fprofile-arcs -ftest-coverage")
# Make everything public for testing purposes
add_definitions(-Dprivate=public)
# If not specified, use Debug as build type (necessary for coverage testing) # If not specified, use Debug as build type (necessary for coverage testing)
if( NOT CMAKE_BUILD_TYPE ) if( NOT CMAKE_BUILD_TYPE )
set( CMAKE_BUILD_TYPE Debug CACHE STRING set( CMAKE_BUILD_TYPE Debug CACHE STRING
......
This diff is collapsed.
...@@ -421,6 +421,12 @@ class json ...@@ -421,6 +421,12 @@ class json
inline void error(const std::string&) __attribute__((noreturn)); inline void error(const std::string&) __attribute__((noreturn));
/// parse a quoted string /// parse a quoted string
inline std::string parseString(); inline std::string parseString();
/// transforms a unicode codepoint to it's UTF-8 presentation
std::string codePointToUTF8(unsigned int codePoint);
/// parses 4 hex characters that represent a unicode code point
inline unsigned int parse4HexCodePoint();
/// parses \uXXXX[\uXXXX] unicode escape characters
inline std::string parseUnicodeEscape();
/// parse a Boolean "true" /// parse a Boolean "true"
inline void parseTrue(); inline void parseTrue();
/// parse a Boolean "false" /// parse a Boolean "false"
......
...@@ -1672,6 +1672,50 @@ TEST_CASE("Parser") ...@@ -1672,6 +1672,50 @@ TEST_CASE("Parser")
CHECK_THROWS_AS(json::parse("\""), std::invalid_argument); CHECK_THROWS_AS(json::parse("\""), std::invalid_argument);
} }
SECTION("unicode_escaping")
{
// two tests for uppercase and lowercase hex
// normal forward slash in ASCII range
CHECK(json::parse("\"\\u002F\"") == json("/"));
CHECK(json::parse("\"\\u002f\"") == json("/"));
// german a umlaut
CHECK(json::parse("\"\\u00E4\"") == json(u8"\u00E4"));
CHECK(json::parse("\"\\u00e4\"") == json(u8"\u00E4"));
// weird d
CHECK(json::parse("\"\\u0111\"") == json(u8"\u0111"));
// unicode arrow left
CHECK(json::parse("\"\\u2190\"") == json(u8"\u2190"));
// pleasing osiris by testing hieroglyph support
CHECK(json::parse("\"\\uD80C\\uDC60\"") == json(u8"\U00013060"));
CHECK(json::parse("\"\\ud80C\\udc60\"") == json(u8"\U00013060"));
// no hex numbers behind the \u
CHECK_THROWS_AS(json::parse("\"\\uD80v\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uD80 A\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uD8v\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uDv\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uv\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\u\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\u\\u\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"a\\uD80vAz\""), std::invalid_argument);
// missing part of a surrogate pair
CHECK_THROWS_AS(json::parse("\"bla \\uD80C bla\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uD80C bla bla\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"bla bla \\uD80C bla bla\""), std::invalid_argument);
// senseless surrogate pair
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), std::invalid_argument);
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), std::invalid_argument);
// test private code point converter function
CHECK_NOTHROW(json::parser("").codePointToUTF8(0x10FFFE));
CHECK_NOTHROW(json::parser("").codePointToUTF8(0x10FFFF));
CHECK_THROWS_AS(json::parser("").codePointToUTF8(0x110000), std::invalid_argument);
CHECK_THROWS_AS(json::parser("").codePointToUTF8(0x110001), std::invalid_argument);
}
SECTION("boolean") SECTION("boolean")
{ {
// accept the exact values // accept the exact values
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment