Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
fc6ffc14
Commit
fc6ffc14
authored
Feb 14, 2022
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve error reporting of the JSON reader
parent
457fff7a
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
61 additions
and
18 deletions
+61
-18
libcaf_core/caf/json_reader.hpp
libcaf_core/caf/json_reader.hpp
+9
-0
libcaf_core/src/json_reader.cpp
libcaf_core/src/json_reader.cpp
+52
-18
No files found.
libcaf_core/caf/json_reader.hpp
View file @
fc6ffc14
...
@@ -206,6 +206,12 @@ public:
...
@@ -206,6 +206,12 @@ public:
private:
private:
[[
nodiscard
]]
position
pos
()
const
noexcept
;
[[
nodiscard
]]
position
pos
()
const
noexcept
;
void
append_current_field_name
(
std
::
string
&
str
);
std
::
string
current_field_name
();
std
::
string
mandatory_field_missing_str
(
string_view
name
);
template
<
bool
PopOrAdvanceOnSuccess
,
class
F
>
template
<
bool
PopOrAdvanceOnSuccess
,
class
F
>
bool
consume
(
const
char
*
fun_name
,
F
f
);
bool
consume
(
const
char
*
fun_name
,
F
f
);
...
@@ -238,6 +244,9 @@ private:
...
@@ -238,6 +244,9 @@ private:
detail
::
json
::
value
*
root_
=
nullptr
;
detail
::
json
::
value
*
root_
=
nullptr
;
string_view
field_type_suffix_
=
field_type_suffix_default
;
string_view
field_type_suffix_
=
field_type_suffix_default
;
/// Keeps track of the current field for better debugging output.
std
::
vector
<
string_view
>
field_
;
};
};
}
// namespace caf
}
// namespace caf
libcaf_core/src/json_reader.cpp
View file @
fc6ffc14
...
@@ -102,18 +102,18 @@ caf::string_view field_type(const caf::detail::json::object* obj,
...
@@ -102,18 +102,18 @@ caf::string_view field_type(const caf::detail::json::object* obj,
#define INVALID_AND_PAST_THE_END_CASES \
#define INVALID_AND_PAST_THE_END_CASES \
case position::invalid: \
case position::invalid: \
emplace_error(sec::runtime_error, class_name, fn,
\
emplace_error(sec::runtime_error, class_name, fn,
current_field_name(),
\
"found an invalid position"); \
"found an invalid position"); \
return false; \
return false; \
case position::past_the_end: \
case position::past_the_end: \
emplace_error(sec::runtime_error, class_name, fn,
\
emplace_error(sec::runtime_error, class_name, fn,
current_field_name(),
\
"tried reading past the end"); \
"tried reading past the end"); \
return false;
return false;
#define SCOPE(expected_position) \
#define SCOPE(expected_position) \
if (auto got = pos(); got != expected_position) { \
if (auto got = pos(); got != expected_position) { \
emplace_error(sec::runtime_error, class_name, __func__, \
emplace_error(sec::runtime_error, class_name, __func__, \
type_clash(expected_position, got));
\
current_field_name(), type_clash(expected_position, got));
\
return false; \
return false; \
}
}
...
@@ -122,14 +122,17 @@ namespace caf {
...
@@ -122,14 +122,17 @@ namespace caf {
// -- constructors, destructors, and assignment operators ----------------------
// -- constructors, destructors, and assignment operators ----------------------
json_reader
::
json_reader
()
:
super
()
{
json_reader
::
json_reader
()
:
super
()
{
field_
.
reserve
(
8
);
has_human_readable_format_
=
true
;
has_human_readable_format_
=
true
;
}
}
json_reader
::
json_reader
(
actor_system
&
sys
)
:
super
(
sys
)
{
json_reader
::
json_reader
(
actor_system
&
sys
)
:
super
(
sys
)
{
field_
.
reserve
(
8
);
has_human_readable_format_
=
true
;
has_human_readable_format_
=
true
;
}
}
json_reader
::
json_reader
(
execution_unit
*
ctx
)
:
super
(
ctx
)
{
json_reader
::
json_reader
(
execution_unit
*
ctx
)
:
super
(
ctx
)
{
field_
.
reserve
(
8
);
has_human_readable_format_
=
true
;
has_human_readable_format_
=
true
;
}
}
...
@@ -183,7 +186,8 @@ bool json_reader::fetch_next_object_type(type_id_t& type) {
...
@@ -183,7 +186,8 @@ bool json_reader::fetch_next_object_type(type_id_t& type) {
}
else
{
}
else
{
std
::
string
what
=
"no type ID available for @type: "
;
std
::
string
what
=
"no type ID available for @type: "
;
what
.
insert
(
what
.
end
(),
type_name
.
begin
(),
type_name
.
end
());
what
.
insert
(
what
.
end
(),
type_name
.
begin
(),
type_name
.
end
());
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
std
::
move
(
what
));
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
current_field_name
(),
std
::
move
(
what
));
return
false
;
return
false
;
}
}
}
else
{
}
else
{
...
@@ -202,16 +206,17 @@ bool json_reader::fetch_next_object_name(string_view& type_name) {
...
@@ -202,16 +206,17 @@ bool json_reader::fetch_next_object_name(string_view& type_name) {
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
"expected a string argument to @type"
);
"expected a string argument to @type"
);
return
false
;
return
false
;
}
}
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
"found no @type member"
);
"found no @type member"
);
return
false
;
return
false
;
}
}
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::object"
,
val
));
type_clash
(
"json::object"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -225,7 +230,7 @@ bool json_reader::begin_object(type_id_t, string_view) {
...
@@ -225,7 +230,7 @@ bool json_reader::begin_object(type_id_t, string_view) {
push
(
&
get
<
detail
::
json
::
object
>
(
val
.
data
));
push
(
&
get
<
detail
::
json
::
object
>
(
val
.
data
));
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::object"
,
val
));
type_clash
(
"json::object"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -247,6 +252,7 @@ bool json_reader::end_object() {
...
@@ -247,6 +252,7 @@ bool json_reader::end_object() {
return
true
;
return
true
;
default:
default:
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
current_field_name
(),
type_clash
(
"json::value or json::array"
,
current_pos
));
type_clash
(
"json::value or json::array"
,
current_pos
));
return
false
;
return
false
;
}
}
...
@@ -255,11 +261,12 @@ bool json_reader::end_object() {
...
@@ -255,11 +261,12 @@ bool json_reader::end_object() {
bool
json_reader
::
begin_field
(
string_view
name
)
{
bool
json_reader
::
begin_field
(
string_view
name
)
{
SCOPE
(
position
::
object
);
SCOPE
(
position
::
object
);
if
(
auto
member
=
find_member
(
top
<
position
::
object
>
(),
name
))
{
if
(
auto
member
=
find_member
(
top
<
position
::
object
>
(),
name
))
{
field_
.
push_back
(
name
);
push
(
member
->
val
);
push
(
member
->
val
);
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
"no such field: "
+
to_string
(
name
));
mandatory_field_missing_str
(
name
));
return
false
;
return
false
;
}
}
}
}
...
@@ -269,6 +276,7 @@ bool json_reader::begin_field(string_view name, bool& is_present) {
...
@@ -269,6 +276,7 @@ bool json_reader::begin_field(string_view name, bool& is_present) {
if
(
auto
member
=
find_member
(
top
<
position
::
object
>
(),
name
);
if
(
auto
member
=
find_member
(
top
<
position
::
object
>
(),
name
);
member
!=
nullptr
member
!=
nullptr
&&
member
->
val
->
data
.
index
()
!=
detail
::
json
::
value
::
null_index
)
{
&&
member
->
val
->
data
.
index
()
!=
detail
::
json
::
value
::
null_index
)
{
field_
.
push_back
(
name
);
push
(
member
->
val
);
push
(
member
->
val
);
is_present
=
true
;
is_present
=
true
;
}
else
{
}
else
{
...
@@ -285,7 +293,7 @@ bool json_reader::begin_field(string_view name, span<const type_id_t> types,
...
@@ -285,7 +293,7 @@ bool json_reader::begin_field(string_view name, span<const type_id_t> types,
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
"mandatory field missing"
);
mandatory_field_missing_str
(
name
)
);
return
false
;
return
false
;
}
}
}
else
{
}
else
{
...
@@ -304,6 +312,7 @@ bool json_reader::begin_field(string_view name, bool& is_present,
...
@@ -304,6 +312,7 @@ bool json_reader::begin_field(string_view name, bool& is_present,
if
(
auto
i
=
std
::
find
(
types
.
begin
(),
types
.
end
(),
id
);
if
(
auto
i
=
std
::
find
(
types
.
begin
(),
types
.
end
(),
id
);
i
!=
types
.
end
())
{
i
!=
types
.
end
())
{
index
=
static_cast
<
size_t
>
(
std
::
distance
(
types
.
begin
(),
i
));
index
=
static_cast
<
size_t
>
(
std
::
distance
(
types
.
begin
(),
i
));
field_
.
push_back
(
name
);
push
(
member
->
val
);
push
(
member
->
val
);
is_present
=
true
;
is_present
=
true
;
return
true
;
return
true
;
...
@@ -316,7 +325,9 @@ bool json_reader::begin_field(string_view name, bool& is_present,
...
@@ -316,7 +325,9 @@ bool json_reader::begin_field(string_view name, bool& is_present,
bool
json_reader
::
end_field
()
{
bool
json_reader
::
end_field
()
{
SCOPE
(
position
::
object
);
SCOPE
(
position
::
object
);
// Note: no pop() here, because the value(s) were already consumed.
// Note: no pop() here, because the value(s) were already consumed. Only
// update the field_ for debugging.
field_
.
pop_back
();
return
true
;
return
true
;
}
}
...
@@ -332,7 +343,7 @@ bool json_reader::begin_tuple(size_t size) {
...
@@ -332,7 +343,7 @@ bool json_reader::begin_tuple(size_t size) {
msg
+=
", got a list of size "
;
msg
+=
", got a list of size "
;
detail
::
print
(
msg
,
list_size
);
detail
::
print
(
msg
,
list_size
);
emplace_error
(
sec
::
conversion_failed
,
class_name
,
__func__
,
emplace_error
(
sec
::
conversion_failed
,
class_name
,
__func__
,
std
::
move
(
msg
));
current_field_name
(),
std
::
move
(
msg
));
return
false
;
return
false
;
}
}
}
else
{
}
else
{
...
@@ -373,7 +384,7 @@ bool json_reader::begin_sequence(size_t& size) {
...
@@ -373,7 +384,7 @@ bool json_reader::begin_sequence(size_t& size) {
push
(
sequence
{
ls
.
begin
(),
ls
.
end
()});
push
(
sequence
{
ls
.
begin
(),
ls
.
end
()});
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::array"
,
val
));
type_clash
(
"json::array"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -405,7 +416,7 @@ bool json_reader::begin_associative_array(size_t& size) {
...
@@ -405,7 +416,7 @@ bool json_reader::begin_associative_array(size_t& size) {
push
(
members
{
obj
->
begin
(),
obj
->
end
()});
push
(
members
{
obj
->
begin
(),
obj
->
end
()});
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::object"
,
val
));
type_clash
(
"json::object"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -441,7 +452,7 @@ bool json_reader::value(bool& x) {
...
@@ -441,7 +452,7 @@ bool json_reader::value(bool& x) {
x
=
std
::
get
<
bool
>
(
val
.
data
);
x
=
std
::
get
<
bool
>
(
val
.
data
);
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::boolean"
,
val
));
type_clash
(
"json::boolean"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -481,7 +492,7 @@ bool json_reader::consume(const char* fn, F f) {
...
@@ -481,7 +492,7 @@ bool json_reader::consume(const char* fn, F f) {
return
false
;
return
false
;
}
}
default:
default:
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::value"
,
current_pos
));
type_clash
(
"json::value"
,
current_pos
));
return
false
;
return
false
;
}
}
...
@@ -502,7 +513,7 @@ bool json_reader::integer(T& x) {
...
@@ -502,7 +513,7 @@ bool json_reader::integer(T& x) {
return
false
;
return
false
;
}
}
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::integer"
,
val
));
type_clash
(
"json::integer"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -558,7 +569,7 @@ bool json_reader::value(double& x) {
...
@@ -558,7 +569,7 @@ bool json_reader::value(double& x) {
x
=
std
::
get
<
double
>
(
val
.
data
);
x
=
std
::
get
<
double
>
(
val
.
data
);
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::real"
,
val
));
type_clash
(
"json::real"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -582,7 +593,7 @@ bool json_reader::value(std::string& x) {
...
@@ -582,7 +593,7 @@ bool json_reader::value(std::string& x) {
detail
::
print_unescaped
(
x
,
std
::
get
<
string_view
>
(
val
.
data
));
detail
::
print_unescaped
(
x
,
std
::
get
<
string_view
>
(
val
.
data
));
return
true
;
return
true
;
}
else
{
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
type_clash
(
"json::string"
,
val
));
type_clash
(
"json::string"
,
val
));
return
false
;
return
false
;
}
}
...
@@ -616,4 +627,27 @@ json_reader::position json_reader::pos() const noexcept {
...
@@ -616,4 +627,27 @@ json_reader::position json_reader::pos() const noexcept {
return
static_cast
<
position
>
(
st_
->
back
().
index
());
return
static_cast
<
position
>
(
st_
->
back
().
index
());
}
}
void
json_reader
::
append_current_field_name
(
std
::
string
&
result
)
{
result
+=
"ROOT"
;
for
(
auto
&
key
:
field_
)
{
result
+=
'.'
;
result
.
insert
(
result
.
end
(),
key
.
begin
(),
key
.
end
());
}
}
std
::
string
json_reader
::
current_field_name
()
{
std
::
string
result
;
append_current_field_name
(
result
);
return
result
;
}
std
::
string
json_reader
::
mandatory_field_missing_str
(
string_view
name
)
{
std
::
string
msg
=
"mandatory field '"
;
append_current_field_name
(
msg
);
msg
+=
'.'
;
msg
.
insert
(
msg
.
end
(),
name
.
begin
(),
name
.
end
());
msg
+=
"' missing"
;
return
msg
;
}
}
// namespace caf
}
// namespace caf
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