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
b51414da
Commit
b51414da
authored
Jan 14, 2021
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new deserializer for reading JSON input
parent
9a120d9a
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
937 additions
and
2 deletions
+937
-2
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+2
-0
libcaf_core/caf/detail/json.hpp
libcaf_core/caf/detail/json.hpp
+14
-0
libcaf_core/caf/detail/print.hpp
libcaf_core/caf/detail/print.hpp
+47
-0
libcaf_core/caf/error.hpp
libcaf_core/caf/error.hpp
+7
-0
libcaf_core/caf/json_reader.hpp
libcaf_core/caf/json_reader.hpp
+220
-0
libcaf_core/caf/load_inspector.hpp
libcaf_core/caf/load_inspector.hpp
+1
-1
libcaf_core/caf/save_inspector.hpp
libcaf_core/caf/save_inspector.hpp
+1
-1
libcaf_core/src/json_reader.cpp
libcaf_core/src/json_reader.cpp
+562
-0
libcaf_core/test/json_reader.cpp
libcaf_core/test/json_reader.cpp
+83
-0
No files found.
libcaf_core/CMakeLists.txt
View file @
b51414da
...
...
@@ -156,6 +156,7 @@ caf_add_component(
src/ipv6_address.cpp
src/ipv6_endpoint.cpp
src/ipv6_subnet.cpp
src/json_reader.cpp
src/json_writer.cpp
src/load_inspector.cpp
src/local_actor.cpp
...
...
@@ -295,6 +296,7 @@ caf_add_component(
ipv6_address
ipv6_endpoint
ipv6_subnet
json_reader
json_writer
load_inspector
logger
...
...
libcaf_core/caf/detail/json.hpp
View file @
b51414da
...
...
@@ -40,6 +40,20 @@ public:
using
data_type
=
std
::
variant
<
null_t
,
int64_t
,
double
,
bool
,
string_view
,
array
,
object
>
;
static
constexpr
size_t
null_index
=
0
;
static
constexpr
size_t
integer_index
=
1
;
static
constexpr
size_t
double_index
=
2
;
static
constexpr
size_t
bool_index
=
3
;
static
constexpr
size_t
string_index
=
4
;
static
constexpr
size_t
array_index
=
5
;
static
constexpr
size_t
object_index
=
6
;
data_type
data
;
};
...
...
libcaf_core/caf/detail/print.hpp
View file @
b51414da
...
...
@@ -47,6 +47,53 @@ void print_escaped(Buffer& buf, string_view str) {
buf
.
push_back
(
'"'
);
}
template
<
class
Buffer
>
void
print_unescaped
(
Buffer
&
buf
,
string_view
str
)
{
buf
.
reserve
(
buf
.
size
()
+
str
.
size
());
auto
i
=
str
.
begin
();
auto
e
=
str
.
end
();
while
(
i
!=
e
)
{
switch
(
*
i
)
{
default:
buf
.
push_back
(
*
i
);
++
i
;
break
;
case
'\\'
:
if
(
++
i
!=
e
)
{
switch
(
*
i
)
{
case
'"'
:
buf
.
push_back
(
'"'
);
break
;
case
'\\'
:
buf
.
push_back
(
'\\'
);
break
;
case
'b'
:
buf
.
push_back
(
'\b'
);
break
;
case
'f'
:
buf
.
push_back
(
'\f'
);
break
;
case
'n'
:
buf
.
push_back
(
'\n'
);
break
;
case
'r'
:
buf
.
push_back
(
'\r'
);
break
;
case
't'
:
buf
.
push_back
(
'\t'
);
break
;
case
'v'
:
buf
.
push_back
(
'\v'
);
break
;
default:
buf
.
push_back
(
'?'
);
}
++
i
;
}
}
}
}
template
<
class
Buffer
>
void
print
(
Buffer
&
buf
,
none_t
)
{
using
namespace
caf
::
literals
;
...
...
libcaf_core/caf/error.hpp
View file @
b51414da
...
...
@@ -145,6 +145,13 @@ public:
int
compare
(
uint8_t
code
,
type_id_t
category
)
const
noexcept
;
// -- modifiers --------------------------------------------------------------
/// Reverts this error to "not an error" as if calling `*this = error{}`.
void
reset
()
noexcept
{
data_
.
reset
();
}
// -- static convenience functions -------------------------------------------
/// @cond PRIVATE
...
...
libcaf_core/caf/json_reader.hpp
0 → 100644
View file @
b51414da
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include "caf/deserializer.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/detail/json.hpp"
#include "caf/string_view.hpp"
#include <variant>
namespace
caf
{
/// Deserializes an inspectable object from a JSON-formatted string.
class
CAF_CORE_EXPORT
json_reader
:
public
deserializer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
deserializer
;
struct
sequence
{
detail
::
json
::
array
::
const_iterator
pos
;
detail
::
json
::
array
::
const_iterator
end
;
bool
at_end
()
const
noexcept
{
return
pos
==
end
;
}
auto
&
current
()
{
return
*
pos
;
}
void
advance
()
{
++
pos
;
}
};
struct
members
{
detail
::
json
::
object
::
const_iterator
pos
;
detail
::
json
::
object
::
const_iterator
end
;
bool
at_end
()
const
noexcept
{
return
pos
==
end
;
}
auto
&
current
()
{
return
*
pos
;
}
void
advance
()
{
++
pos
;
}
};
using
json_key
=
string_view
;
using
value_type
=
std
::
variant
<
const
detail
::
json
::
value
*
,
const
detail
::
json
::
object
*
,
detail
::
json
::
null_t
,
json_key
,
sequence
,
members
>
;
using
stack_allocator
=
detail
::
monotonic_buffer_resource
::
allocator
<
value_type
>
;
using
stack_type
=
std
::
vector
<
value_type
,
stack_allocator
>
;
/// Denotes the type at the current position.
enum
class
position
{
value
,
object
,
null
,
key
,
sequence
,
members
,
past_the_end
,
invalid
,
};
// -- constructors, destructors, and assignment operators --------------------
json_reader
();
explicit
json_reader
(
actor_system
&
sys
);
explicit
json_reader
(
execution_unit
*
ctx
);
json_reader
(
const
json_reader
&
)
=
delete
;
json_reader
&
operator
=
(
const
json_reader
&
)
=
delete
;
~
json_reader
()
override
;
// -- modifiers --------------------------------------------------------------
/// Removes any loaded JSON data and reclaims all memory resources.
void
reset
();
/// Parses @p json_text into an internal representation. After loading the
/// JSON input, the reader is ready for attempting to deserialize inspectable
/// objects.
/// @warning The internal data structure keeps pointers into @p json_text.
/// Hence, the buffer pointed to by the string view must remain valid
/// until either destroying this reader or calling `reset`.
/// @note Implicitly calls `reset`.
bool
load
(
string_view
json_text
);
/// Reverts the state of the reader back to where it was after calling `load`.
/// @post The reader is ready for attempting to deserialize another
/// inspectable object.
void
revert
();
// -- overrides --------------------------------------------------------------
bool
fetch_next_object_type
(
type_id_t
&
type
)
override
;
bool
begin_object
(
type_id_t
type
,
string_view
name
)
override
;
bool
end_object
()
override
;
bool
begin_field
(
string_view
)
override
;
bool
begin_field
(
string_view
name
,
bool
&
is_present
)
override
;
bool
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
types
,
size_t
&
index
)
override
;
bool
begin_field
(
string_view
name
,
bool
&
is_present
,
span
<
const
type_id_t
>
types
,
size_t
&
index
)
override
;
bool
end_field
()
override
;
bool
begin_tuple
(
size_t
size
)
override
;
bool
end_tuple
()
override
;
bool
begin_key_value_pair
()
override
;
bool
end_key_value_pair
()
override
;
bool
begin_sequence
(
size_t
&
size
)
override
;
bool
end_sequence
()
override
;
bool
begin_associative_array
(
size_t
&
size
)
override
;
bool
end_associative_array
()
override
;
bool
value
(
byte
&
x
)
override
;
bool
value
(
bool
&
x
)
override
;
bool
value
(
int8_t
&
x
)
override
;
bool
value
(
uint8_t
&
x
)
override
;
bool
value
(
int16_t
&
x
)
override
;
bool
value
(
uint16_t
&
x
)
override
;
bool
value
(
int32_t
&
x
)
override
;
bool
value
(
uint32_t
&
x
)
override
;
bool
value
(
int64_t
&
x
)
override
;
bool
value
(
uint64_t
&
x
)
override
;
bool
value
(
float
&
x
)
override
;
bool
value
(
double
&
x
)
override
;
bool
value
(
long
double
&
x
)
override
;
bool
value
(
std
::
string
&
x
)
override
;
bool
value
(
std
::
u16string
&
x
)
override
;
bool
value
(
std
::
u32string
&
x
)
override
;
bool
value
(
span
<
byte
>
x
)
override
;
private:
[[
nodiscard
]]
position
pos
()
const
noexcept
;
template
<
bool
PopOrAdvanceOnSuccess
,
class
F
>
bool
consume
(
const
char
*
fun_name
,
F
f
);
template
<
class
T
>
bool
integer
(
T
&
x
);
template
<
position
P
>
auto
&
top
()
noexcept
{
return
std
::
get
<
static_cast
<
size_t
>
(
P
)
>
(
st_
->
back
());
}
template
<
position
P
>
const
auto
&
top
()
const
noexcept
{
return
std
::
get
<
static_cast
<
size_t
>
(
P
)
>
(
st_
->
back
());
}
void
pop
()
{
st_
->
pop_back
();
}
template
<
class
T
>
void
push
(
T
&&
x
)
{
st_
->
emplace_back
(
std
::
forward
<
T
>
(
x
));
}
detail
::
monotonic_buffer_resource
buf_
;
stack_type
*
st_
=
nullptr
;
detail
::
json
::
value
*
root_
=
nullptr
;
};
}
// namespace caf
libcaf_core/caf/load_inspector.hpp
View file @
b51414da
...
...
@@ -42,7 +42,7 @@ public:
template
<
class
...
Ts
>
void
emplace_error
(
Ts
&&
...
xs
)
{
err_
=
make_error
(
xs
...);
err_
=
make_error
(
std
::
forward
<
Ts
>
(
xs
)
...);
}
const
error
&
get_error
()
const
noexcept
{
...
...
libcaf_core/caf/save_inspector.hpp
View file @
b51414da
...
...
@@ -42,7 +42,7 @@ public:
template
<
class
...
Ts
>
void
emplace_error
(
Ts
&&
...
xs
)
{
err_
=
make_error
(
xs
...);
err_
=
make_error
(
std
::
forward
<
Ts
>
(
xs
)
...);
}
const
error
&
get_error
()
const
noexcept
{
...
...
libcaf_core/src/json_reader.cpp
0 → 100644
View file @
b51414da
This diff is collapsed.
Click to expand it.
libcaf_core/test/json_reader.cpp
0 → 100644
View file @
b51414da
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#define CAF_SUITE json_reader
#include "caf/json_reader.hpp"
#include "core-test.hpp"
#include "caf/dictionary.hpp"
using
namespace
caf
;
namespace
{
struct
fixture
{
template
<
class
T
>
void
add_test_case
(
string_view
input
,
T
val
)
{
auto
f
=
[
this
,
input
,
obj
{
std
::
move
(
val
)}]()
->
bool
{
auto
tmp
=
T
{};
auto
res
=
CHECK
(
reader
.
load
(
input
))
// parse JSON
&&
CHECK
(
reader
.
apply
(
tmp
));
// deserialize object
if
(
res
)
{
if
constexpr
(
std
::
is_same
<
T
,
message
>::
value
)
res
=
CHECK_EQ
(
to_string
(
tmp
),
to_string
(
obj
));
else
res
=
CHECK_EQ
(
tmp
,
obj
);
}
if
(
!
res
)
MESSAGE
(
"rejected input: "
<<
input
);
return
res
;
};
test_cases
.
emplace_back
(
std
::
move
(
f
));
}
template
<
class
T
,
class
...
Ts
>
std
::
vector
<
T
>
ls
(
Ts
...
xs
)
{
return
{
std
::
move
(
xs
)...};
}
template
<
class
T
>
using
dict
=
dictionary
<
T
>
;
fixture
();
json_reader
reader
;
std
::
vector
<
std
::
function
<
bool
()
>>
test_cases
;
};
fixture
::
fixture
()
{
add_test_case
(
R"_(true)_"
,
true
);
add_test_case
(
R"_(false)_"
,
false
);
add_test_case
(
R"_([true, false])_"
,
ls
<
bool
>
(
true
,
false
));
add_test_case
(
R"_(42)_"
,
int32_t
{
42
});
add_test_case
(
R"_([1, 2, 3])_"
,
ls
<
int32_t
>
(
1
,
2
,
3
));
add_test_case
(
R"_(2.0)_"
,
2.0
);
add_test_case
(
R"_([2.0, 4.0, 8.0])_"
,
ls
<
double
>
(
2.0
,
4.0
,
8.0
));
add_test_case
(
R"_("hello \"world\"!")_"
,
std
::
string
{
R"_(hello "world"!)_"
});
add_test_case
(
R"_(["hello", "world"])_"
,
ls
<
std
::
string
>
(
"hello"
,
"world"
));
add_test_case
(
R"_({"a": 1, "b": 2})_"
,
my_request
(
1
,
2
));
add_test_case
(
R"_({"a": 1, "b": 2})_"
,
dict
<
int
>
({{
"a"
,
1
},
{
"b"
,
2
}}));
add_test_case
(
R"_([{"@type": "my_request", "a": 1, "b": 2}])_"
,
make_message
(
my_request
(
1
,
2
)));
}
}
// namespace
CAF_TEST_FIXTURE_SCOPE
(
json_reader_tests
,
fixture
)
CAF_TEST
(
json
baselines
)
{
size_t
baseline_index
=
0
;
detail
::
monotonic_buffer_resource
resource
;
for
(
auto
&
f
:
test_cases
)
{
MESSAGE
(
"test case at index "
<<
baseline_index
++
);
if
(
!
f
())
if
(
auto
reason
=
reader
.
get_error
())
MESSAGE
(
"JSON reader stopped due to: "
<<
reason
);
}
}
CAF_TEST_FIXTURE_SCOPE_END
()
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