Skip to content

Commit

Permalink
feat: \u support
Browse files Browse the repository at this point in the history
  • Loading branch information
neko-para committed May 15, 2024
1 parent db365b1 commit 7726d56
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 4 deletions.
52 changes: 49 additions & 3 deletions include/parser/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#pragma once

#include <cctype>
#include <fstream>
#include <optional>
#include <ostream>
Expand Down Expand Up @@ -438,9 +439,54 @@ inline std::optional<string_t> parser<string_t, parsing_t, accel_traits>::parse_
case 't':
result.push_back('\t');
break;
// case 'u':
// result.push_back('\u');
// break;
case 'u': {
uint16_t cp = 0;
for (int i = 0; i < 4; i++) {
++_cur;
if (_cur == _end) {
return std::nullopt;
}
if (!std::isxdigit(static_cast<unsigned char>(*_cur))) {
return std::nullopt;
}
cp <<= 4;
if ('0' <= *_cur && *_cur <= '9') {
cp |= *_cur - '0';
}
else if ('a' <= *_cur && *_cur <= 'f') {
cp |= *_cur - 'a' + 10;
}
else if ('A' <= *_cur && *_cur <= 'F') {
cp |= *_cur - 'A' + 10;
}
else {
return std::nullopt;
}
}
if constexpr (std::is_same_v<typename string_t::value_type, char>) {
// utf8
if (cp <= 0x7F) {
result.push_back(static_cast<char>(cp));
}
else if (cp <= 0x7FF) {
result.push_back(static_cast<char>(((cp >> 6) & 0b00011111) | 0b11000000u));
result.push_back(static_cast<char>((cp & 0b00111111) | 0b10000000u));
}
else {
result.push_back(
static_cast<char>(((cp >> 12) & 0b00001111) | 0b11100000u));
result.push_back(static_cast<char>(((cp >> 6) & 0b00111111) | 0b10000000u));
result.push_back(static_cast<char>((cp & 0b00111111) | 0b10000000u));
}
}
else if constexpr (std::is_same_v<typename string_t::value_type, wchar_t>) {
result.push_back(cp);
}
else {
static_assert(false, "Unsupported type");
}
break;
}
default:
// Illegal backslash escape
return std::nullopt;
Expand Down
4 changes: 4 additions & 0 deletions test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "json5_test.h"
#include "precision_test.h"
#include "serializing_test.h"
#include "unicode_test.h"

int main()
{
Expand All @@ -27,6 +28,9 @@ int main()
std::cout << "\n*** precision_test ***\n" << std::endl;
success &= precision_test();

std::cout << "\n*** unicode_test ***\n" << std::endl;
success &= unicode_test();

if (!success) {
std::cout << "\n****** Test failed ******\n" << std::endl;
return -1;
Expand Down
2 changes: 1 addition & 1 deletion test/precision_test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#define MEOJSON_KEEP_FLOATING_PRECISION

#include "../include/json.hpp"
#include "json.hpp"

#include <iomanip>
#include <iostream>
Expand Down
25 changes: 25 additions & 0 deletions test/unicode_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "json.hpp"

#include <iomanip>
#include <iostream>

bool unicode_test()
{
std::string test = R"({ "test": "abc\u9a8fdef" })";
auto obj = json::parse(test);
if (!obj.has_value()) {
std::cout << "parse failed" << std::endl;
return false;
}
for (auto ch : obj.value().at("test").as_string()) {
std::cout << std::hex << std::setw(2)
<< static_cast<unsigned>(static_cast<unsigned char>(ch)) << ' ';
}
std::cout << std::endl;
for (auto ch : "abc\u9a8fdef") {
std::cout << std::hex << std::setw(2)
<< static_cast<unsigned>(static_cast<unsigned char>(ch)) << ' ';
}
std::cout << std::endl;
return obj.value().at("test").as_string() == "abc\u9a8fdef";
}
3 changes: 3 additions & 0 deletions test/unicode_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

extern bool unicode_test();

0 comments on commit 7726d56

Please sign in to comment.