Specify char type in JSON. (#8949)
char is defined as signed on x86 but unsigned on arm64 - Use `std::int8_t` instead of char. - Fix include when clang is pretending to be gcc.
This commit is contained in:
parent
5891f752c8
commit
a05799ed39
@ -1,5 +1,5 @@
|
|||||||
/*!
|
/**
|
||||||
* Copyright (c) by Contributors 2019-2022
|
* Copyright 2019-2023, XGBoost Contributors
|
||||||
*/
|
*/
|
||||||
#ifndef XGBOOST_JSON_IO_H_
|
#ifndef XGBOOST_JSON_IO_H_
|
||||||
#define XGBOOST_JSON_IO_H_
|
#define XGBOOST_JSON_IO_H_
|
||||||
@ -17,44 +17,26 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace xgboost {
|
namespace xgboost {
|
||||||
namespace detail {
|
/**
|
||||||
// Whether char is signed is undefined, as a result we might or might not need
|
|
||||||
// static_cast and std::to_string.
|
|
||||||
template <typename Char, std::enable_if_t<std::is_signed<Char>::value>* = nullptr>
|
|
||||||
std::string CharToStr(Char c) {
|
|
||||||
static_assert(std::is_same<Char, char>::value);
|
|
||||||
return std::string{c};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, std::enable_if_t<!std::is_signed<Char>::value>* = nullptr>
|
|
||||||
std::string CharToStr(Char c) {
|
|
||||||
static_assert(std::is_same<Char, char>::value);
|
|
||||||
return (c <= static_cast<char>(127) ? std::string{c} : std::to_string(c));
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
/*
|
|
||||||
* \brief A json reader, currently error checking and utf-8 is not fully supported.
|
* \brief A json reader, currently error checking and utf-8 is not fully supported.
|
||||||
*/
|
*/
|
||||||
class JsonReader {
|
class JsonReader {
|
||||||
|
public:
|
||||||
|
using Char = std::int8_t;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t constexpr static kMaxNumLength =
|
size_t constexpr static kMaxNumLength = std::numeric_limits<double>::max_digits10 + 1;
|
||||||
std::numeric_limits<double>::max_digits10 + 1;
|
|
||||||
|
|
||||||
struct SourceLocation {
|
struct SourceLocation {
|
||||||
private:
|
private:
|
||||||
size_t pos_ { 0 }; // current position in raw_str_
|
std::size_t pos_{0}; // current position in raw_str_
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SourceLocation() = default;
|
SourceLocation() = default;
|
||||||
size_t Pos() const { return pos_; }
|
size_t Pos() const { return pos_; }
|
||||||
|
|
||||||
void Forward() {
|
void Forward() { pos_++; }
|
||||||
pos_++;
|
void Forward(uint32_t n) { pos_ += n; }
|
||||||
}
|
|
||||||
void Forward(uint32_t n) {
|
|
||||||
pos_ += n;
|
|
||||||
}
|
|
||||||
} cursor_;
|
} cursor_;
|
||||||
|
|
||||||
StringView raw_str_;
|
StringView raw_str_;
|
||||||
@ -62,7 +44,7 @@ class JsonReader {
|
|||||||
protected:
|
protected:
|
||||||
void SkipSpaces();
|
void SkipSpaces();
|
||||||
|
|
||||||
char GetNextChar() {
|
Char GetNextChar() {
|
||||||
if (XGBOOST_EXPECT((cursor_.Pos() == raw_str_.size()), false)) {
|
if (XGBOOST_EXPECT((cursor_.Pos() == raw_str_.size()), false)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -71,24 +53,24 @@ class JsonReader {
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
char PeekNextChar() {
|
Char PeekNextChar() {
|
||||||
if (cursor_.Pos() == raw_str_.size()) {
|
if (cursor_.Pos() == raw_str_.size()) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
char ch = raw_str_[cursor_.Pos()];
|
Char ch = raw_str_[cursor_.Pos()];
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \brief Skip spaces and consume next character. */
|
/* \brief Skip spaces and consume next character. */
|
||||||
char GetNextNonSpaceChar() {
|
Char GetNextNonSpaceChar() {
|
||||||
SkipSpaces();
|
SkipSpaces();
|
||||||
return GetNextChar();
|
return GetNextChar();
|
||||||
}
|
}
|
||||||
/* \brief Consume next character without first skipping empty space, throw when the next
|
/* \brief Consume next character without first skipping empty space, throw when the next
|
||||||
* character is not the expected one.
|
* character is not the expected one.
|
||||||
*/
|
*/
|
||||||
char GetConsecutiveChar(char expected_char) {
|
Char GetConsecutiveChar(char expected_char) {
|
||||||
char result = GetNextChar();
|
Char result = GetNextChar();
|
||||||
if (XGBOOST_EXPECT(result != expected_char, false)) { Expect(expected_char, result); }
|
if (XGBOOST_EXPECT(result != expected_char, false)) { Expect(expected_char, result); }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -96,7 +78,7 @@ class JsonReader {
|
|||||||
void Error(std::string msg) const;
|
void Error(std::string msg) const;
|
||||||
|
|
||||||
// Report expected character
|
// Report expected character
|
||||||
void Expect(char c, char got) {
|
void Expect(Char c, Char got) {
|
||||||
std::string msg = "Expecting: \"";
|
std::string msg = "Expecting: \"";
|
||||||
msg += c;
|
msg += c;
|
||||||
msg += "\", got: \"";
|
msg += "\", got: \"";
|
||||||
@ -105,7 +87,7 @@ class JsonReader {
|
|||||||
} else if (got == 0) {
|
} else if (got == 0) {
|
||||||
msg += "\\0\"";
|
msg += "\\0\"";
|
||||||
} else {
|
} else {
|
||||||
msg += detail::CharToStr(got) + " \"";
|
msg += std::to_string(got) + " \"";
|
||||||
}
|
}
|
||||||
Error(msg);
|
Error(msg);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
// clang with libstdc++ works as well
|
// clang with libstdc++ works as well
|
||||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__sun) && !defined(sun) && \
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__sun) && !defined(sun) && \
|
||||||
!defined(__APPLE__) && __has_include(<omp.h>)
|
!defined(__APPLE__) && __has_include(<omp.h>) && __has_include(<parallel/algorithm>)
|
||||||
#define GCC_HAS_PARALLEL 1
|
#define GCC_HAS_PARALLEL 1
|
||||||
#endif // GLIC_VERSION
|
#endif // GLIC_VERSION
|
||||||
|
|
||||||
|
|||||||
@ -333,7 +333,7 @@ size_t constexpr JsonReader::kMaxNumLength;
|
|||||||
Json JsonReader::Parse() {
|
Json JsonReader::Parse() {
|
||||||
while (true) {
|
while (true) {
|
||||||
SkipSpaces();
|
SkipSpaces();
|
||||||
char c = PeekNextChar();
|
auto c = PeekNextChar();
|
||||||
if (c == -1) { break; }
|
if (c == -1) { break; }
|
||||||
|
|
||||||
if (c == '{') {
|
if (c == '{') {
|
||||||
@ -408,13 +408,13 @@ void JsonReader::Error(std::string msg) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool IsSpace(char c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t'; }
|
bool IsSpace(JsonReader::Char c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t'; }
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
// Json class
|
// Json class
|
||||||
void JsonReader::SkipSpaces() {
|
void JsonReader::SkipSpaces() {
|
||||||
while (cursor_.Pos() < raw_str_.size()) {
|
while (cursor_.Pos() < raw_str_.size()) {
|
||||||
char c = raw_str_[cursor_.Pos()];
|
Char c = raw_str_[cursor_.Pos()];
|
||||||
if (IsSpace(c)) {
|
if (IsSpace(c)) {
|
||||||
cursor_.Forward();
|
cursor_.Forward();
|
||||||
} else {
|
} else {
|
||||||
@ -436,12 +436,12 @@ void ParseStr(std::string const& str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Json JsonReader::ParseString() {
|
Json JsonReader::ParseString() {
|
||||||
char ch { GetConsecutiveChar('\"') }; // NOLINT
|
Char ch { GetConsecutiveChar('\"') }; // NOLINT
|
||||||
std::string str;
|
std::string str;
|
||||||
while (true) {
|
while (true) {
|
||||||
ch = GetNextChar();
|
ch = GetNextChar();
|
||||||
if (ch == '\\') {
|
if (ch == '\\') {
|
||||||
char next = static_cast<char>(GetNextChar());
|
Char next{GetNextChar()};
|
||||||
switch (next) {
|
switch (next) {
|
||||||
case 'r': str += u8"\r"; break;
|
case 'r': str += u8"\r"; break;
|
||||||
case 'n': str += u8"\n"; break;
|
case 'n': str += u8"\n"; break;
|
||||||
@ -466,8 +466,8 @@ Json JsonReader::ParseString() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Json JsonReader::ParseNull() {
|
Json JsonReader::ParseNull() {
|
||||||
char ch = GetNextNonSpaceChar();
|
Char ch = GetNextNonSpaceChar();
|
||||||
std::string buffer{ch};
|
std::string buffer{static_cast<char>(ch)};
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
buffer.push_back(GetNextChar());
|
buffer.push_back(GetNextChar());
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ Json JsonReader::ParseNull() {
|
|||||||
Json JsonReader::ParseArray() {
|
Json JsonReader::ParseArray() {
|
||||||
std::vector<Json> data;
|
std::vector<Json> data;
|
||||||
|
|
||||||
char ch { GetConsecutiveChar('[') }; // NOLINT
|
Char ch { GetConsecutiveChar('[') }; // NOLINT
|
||||||
while (true) {
|
while (true) {
|
||||||
if (PeekNextChar() == ']') {
|
if (PeekNextChar() == ']') {
|
||||||
GetConsecutiveChar(']');
|
GetConsecutiveChar(']');
|
||||||
@ -503,7 +503,7 @@ Json JsonReader::ParseObject() {
|
|||||||
|
|
||||||
Object::Map data;
|
Object::Map data;
|
||||||
SkipSpaces();
|
SkipSpaces();
|
||||||
char ch = PeekNextChar();
|
auto ch = PeekNextChar();
|
||||||
|
|
||||||
if (ch == '}') {
|
if (ch == '}') {
|
||||||
GetConsecutiveChar('}');
|
GetConsecutiveChar('}');
|
||||||
@ -652,7 +652,7 @@ Json JsonReader::ParseNumber() {
|
|||||||
|
|
||||||
Json JsonReader::ParseBoolean() {
|
Json JsonReader::ParseBoolean() {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
char ch = GetNextNonSpaceChar();
|
Char ch = GetNextNonSpaceChar();
|
||||||
std::string const t_value = u8"true";
|
std::string const t_value = u8"true";
|
||||||
std::string const f_value = u8"false";
|
std::string const f_value = u8"false";
|
||||||
|
|
||||||
@ -737,7 +737,8 @@ Json UBJReader::ParseArray() {
|
|||||||
case 'L':
|
case 'L':
|
||||||
return ParseTypedArray<I64Array>(n);
|
return ParseTypedArray<I64Array>(n);
|
||||||
default:
|
default:
|
||||||
LOG(FATAL) << "`" + std::string{type} + "` is not supported for typed array."; // NOLINT
|
LOG(FATAL) << "`" + std::string{static_cast<char>(type)} + // NOLINT
|
||||||
|
"` is not supported for typed array.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<Json> results;
|
std::vector<Json> results;
|
||||||
@ -794,7 +795,7 @@ Json UBJReader::Load() {
|
|||||||
|
|
||||||
Json UBJReader::Parse() {
|
Json UBJReader::Parse() {
|
||||||
while (true) {
|
while (true) {
|
||||||
char c = PeekNextChar();
|
auto c = PeekNextChar();
|
||||||
if (c == -1) {
|
if (c == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user