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
Hide 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:
private:
[[
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
>
bool
consume
(
const
char
*
fun_name
,
F
f
);
...
...
@@ -238,6 +244,9 @@ private:
detail
::
json
::
value
*
root_
=
nullptr
;
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
libcaf_core/src/json_reader.cpp
View file @
fc6ffc14
...
...
@@ -102,18 +102,18 @@ caf::string_view field_type(const caf::detail::json::object* obj,
#define INVALID_AND_PAST_THE_END_CASES \
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"); \
return false; \
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"); \
return false;
#define SCOPE(expected_position) \
if (auto got = pos(); got != expected_position) { \
emplace_error(sec::runtime_error, class_name, __func__, \
type_clash(expected_position, got));
\
current_field_name(), type_clash(expected_position, got));
\
return false; \
}
...
...
@@ -122,14 +122,17 @@ namespace caf {
// -- constructors, destructors, and assignment operators ----------------------
json_reader
::
json_reader
()
:
super
()
{
field_
.
reserve
(
8
);
has_human_readable_format_
=
true
;
}
json_reader
::
json_reader
(
actor_system
&
sys
)
:
super
(
sys
)
{
field_
.
reserve
(
8
);
has_human_readable_format_
=
true
;
}
json_reader
::
json_reader
(
execution_unit
*
ctx
)
:
super
(
ctx
)
{
field_
.
reserve
(
8
);
has_human_readable_format_
=
true
;
}
...
...
@@ -183,7 +186,8 @@ bool json_reader::fetch_next_object_type(type_id_t& type) {
}
else
{
std
::
string
what
=
"no type ID available for @type: "
;
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
;
}
}
else
{
...
...
@@ -202,16 +206,17 @@ bool json_reader::fetch_next_object_name(string_view& type_name) {
return
true
;
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
"expected a string argument to @type"
);
return
false
;
}
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
emplace_error
(
sec
::
runtime_error
,
class_name
,
fn
,
current_field_name
(),
"found no @type member"
);
return
false
;
}
}
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
));
return
false
;
}
...
...
@@ -225,7 +230,7 @@ bool json_reader::begin_object(type_id_t, string_view) {
push
(
&
get
<
detail
::
json
::
object
>
(
val
.
data
));
return
true
;
}
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
));
return
false
;
}
...
...
@@ -247,6 +252,7 @@ bool json_reader::end_object() {
return
true
;
default:
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
current_field_name
(),
type_clash
(
"json::value or json::array"
,
current_pos
));
return
false
;
}
...
...
@@ -255,11 +261,12 @@ bool json_reader::end_object() {
bool
json_reader
::
begin_field
(
string_view
name
)
{
SCOPE
(
position
::
object
);
if
(
auto
member
=
find_member
(
top
<
position
::
object
>
(),
name
))
{
field_
.
push_back
(
name
);
push
(
member
->
val
);
return
true
;
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
"no such field: "
+
to_string
(
name
));
mandatory_field_missing_str
(
name
));
return
false
;
}
}
...
...
@@ -269,6 +276,7 @@ bool json_reader::begin_field(string_view name, bool& is_present) {
if
(
auto
member
=
find_member
(
top
<
position
::
object
>
(),
name
);
member
!=
nullptr
&&
member
->
val
->
data
.
index
()
!=
detail
::
json
::
value
::
null_index
)
{
field_
.
push_back
(
name
);
push
(
member
->
val
);
is_present
=
true
;
}
else
{
...
...
@@ -285,7 +293,7 @@ bool json_reader::begin_field(string_view name, span<const type_id_t> types,
return
true
;
}
else
{
emplace_error
(
sec
::
runtime_error
,
class_name
,
__func__
,
"mandatory field missing"
);
mandatory_field_missing_str
(
name
)
);
return
false
;
}
}
else
{
...
...
@@ -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
);
i
!=
types
.
end
())
{
index
=
static_cast
<
size_t
>
(
std
::
distance
(
types
.
begin
(),
i
));
field_
.
push_back
(
name
);
push
(
member
->
val
);
is_present
=
true
;
return
true
;
...
...
@@ -316,7 +325,9 @@ bool json_reader::begin_field(string_view name, bool& is_present,
bool
json_reader
::
end_field
()
{
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
;
}
...
...
@@ -332,7 +343,7 @@ bool json_reader::begin_tuple(size_t size) {
msg
+=
", got a list of size "
;
detail
::
print
(
msg
,
list_size
);
emplace_error
(
sec
::
conversion_failed
,
class_name
,
__func__
,
std
::
move
(
msg
));
current_field_name
(),
std
::
move
(
msg
));
return
false
;
}
}
else
{
...
...
@@ -373,7 +384,7 @@ bool json_reader::begin_sequence(size_t& size) {
push
(
sequence
{
ls
.
begin
(),
ls
.
end
()});
return
true
;
}
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
));
return
false
;
}
...
...
@@ -405,7 +416,7 @@ bool json_reader::begin_associative_array(size_t& size) {
push
(
members
{
obj
->
begin
(),
obj
->
end
()});
return
true
;
}
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
));
return
false
;
}
...
...
@@ -441,7 +452,7 @@ bool json_reader::value(bool& x) {
x
=
std
::
get
<
bool
>
(
val
.
data
);
return
true
;
}
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
));
return
false
;
}
...
...
@@ -481,7 +492,7 @@ bool json_reader::consume(const char* fn, F f) {
return
false
;
}
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
));
return
false
;
}
...
...
@@ -502,7 +513,7 @@ bool json_reader::integer(T& x) {
return
false
;
}
}
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
));
return
false
;
}
...
...
@@ -558,7 +569,7 @@ bool json_reader::value(double& x) {
x
=
std
::
get
<
double
>
(
val
.
data
);
return
true
;
}
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
));
return
false
;
}
...
...
@@ -582,7 +593,7 @@ bool json_reader::value(std::string& x) {
detail
::
print_unescaped
(
x
,
std
::
get
<
string_view
>
(
val
.
data
));
return
true
;
}
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
));
return
false
;
}
...
...
@@ -616,4 +627,27 @@ json_reader::position json_reader::pos() const noexcept {
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
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