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
68641365
Unverified
Commit
68641365
authored
Sep 05, 2019
by
Joseph Noir
Committed by
GitHub
Sep 05, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #899
Improve stringification_inspector implementation
parents
5dff9fbc
3f1a546f
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
296 additions
and
233 deletions
+296
-233
libcaf_core/caf/deep_to_string.hpp
libcaf_core/caf/deep_to_string.hpp
+17
-27
libcaf_core/caf/detail/parser/read_timespan.hpp
libcaf_core/caf/detail/parser/read_timespan.hpp
+2
-2
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+84
-146
libcaf_core/src/actor_system_config.cpp
libcaf_core/src/actor_system_config.cpp
+1
-1
libcaf_core/src/stringification_inspector.cpp
libcaf_core/src/stringification_inspector.cpp
+134
-31
libcaf_core/test/deep_to_string.cpp
libcaf_core/test/deep_to_string.cpp
+29
-7
libcaf_core/test/message.cpp
libcaf_core/test/message.cpp
+3
-3
libcaf_core/test/serialization.cpp
libcaf_core/test/serialization.cpp
+25
-15
libcaf_core/test/serializer_impl.cpp
libcaf_core/test/serializer_impl.cpp
+1
-1
No files found.
libcaf_core/caf/deep_to_string.hpp
View file @
68641365
...
@@ -18,47 +18,37 @@
...
@@ -18,47 +18,37 @@
#pragma once
#pragma once
#include <array>
#include <tuple>
#include <string>
#include <string>
#include <utility>
#include <tuple>
#include <functional>
#include <type_traits>
#include "caf/atom.hpp"
#include "caf/detail/apply_args.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/stringification_inspector.hpp"
#include "caf/detail/stringification_inspector.hpp"
namespace
caf
{
namespace
caf
{
class
deep_to_string_t
{
public:
constexpr
deep_to_string_t
()
{
// nop
}
template
<
class
...
Ts
>
std
::
string
operator
()(
Ts
&&
...
xs
)
const
{
std
::
string
result
;
detail
::
stringification_inspector
f
{
result
};
f
(
std
::
forward
<
Ts
>
(
xs
)...);
return
result
;
}
};
/// Unrolls collections such as vectors/maps, decomposes
/// Unrolls collections such as vectors/maps, decomposes
/// tuples/pairs/arrays, auto-escapes strings and calls
/// tuples/pairs/arrays, auto-escapes strings and calls
/// `to_string` for user-defined types via argument-dependent
/// `to_string` for user-defined types via argument-dependent
/// loopkup (ADL). Any user-defined type that does not
/// loopkup (ADL). Any user-defined type that does not
/// provide a `to_string` is mapped to `<unprintable>`.
/// provide a `to_string` is mapped to `<unprintable>`.
constexpr
deep_to_string_t
deep_to_string
=
deep_to_string_t
{};
template
<
class
...
Ts
>
std
::
string
deep_to_string
(
const
Ts
&
...
xs
)
{
std
::
string
result
;
detail
::
stringification_inspector
f
{
result
};
f
(
xs
...);
return
result
;
}
struct
deep_to_string_t
{
template
<
class
...
Ts
>
std
::
string
operator
()(
const
Ts
&
...
xs
)
const
{
return
deep_to_string
(
xs
...);
}
};
/// Convenience function for `deep_to_string(std::forward_as_tuple(xs...))`.
/// Convenience function for `deep_to_string(std::forward_as_tuple(xs...))`.
template
<
class
...
Ts
>
template
<
class
...
Ts
>
std
::
string
deep_to_string_as_tuple
(
Ts
&
&
...
xs
)
{
std
::
string
deep_to_string_as_tuple
(
const
Ts
&
...
xs
)
{
return
deep_to_string
(
std
::
forward_as_tuple
(
std
::
forward
<
Ts
>
(
xs
)
...));
return
deep_to_string
(
std
::
forward_as_tuple
(
xs
...));
}
}
}
// namespace caf
}
// namespace caf
libcaf_core/caf/detail/parser/read_timespan.hpp
View file @
68641365
...
@@ -46,11 +46,11 @@ void read_timespan(state<Iterator, Sentinel>& ps, Consumer&& consumer,
...
@@ -46,11 +46,11 @@ void read_timespan(state<Iterator, Sentinel>& ps, Consumer&& consumer,
struct
interim_consumer
{
struct
interim_consumer
{
using
value_type
=
int64_t
;
using
value_type
=
int64_t
;
void
value
(
int64_t
y
)
{
void
value
(
value_type
y
)
{
x
=
y
;
x
=
y
;
}
}
int64_t
x
=
0
;
value_type
x
=
0
;
};
};
interim_consumer
ic
;
interim_consumer
ic
;
timespan
result
;
timespan
result
;
...
...
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
68641365
...
@@ -19,16 +19,15 @@
...
@@ -19,16 +19,15 @@
#pragma once
#pragma once
#include <chrono>
#include <chrono>
#include <functional>
#include <string>
#include <string>
#include <type_traits>
#include <type_traits>
#include <vector>
#include <vector>
#include "caf/atom.hpp"
#include "caf/detail/append_hex.hpp"
#include "caf/detail/append_hex.hpp"
#include "caf/detail/apply_args.hpp"
#include "caf/detail/apply_args.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/
error
.hpp"
#include "caf/
fwd
.hpp"
#include "caf/meta/annotation.hpp"
#include "caf/meta/annotation.hpp"
#include "caf/meta/hex_formatted.hpp"
#include "caf/meta/hex_formatted.hpp"
#include "caf/meta/omittable.hpp"
#include "caf/meta/omittable.hpp"
...
@@ -68,84 +67,82 @@ public:
...
@@ -68,84 +67,82 @@ public:
/// Prints a separator to the result string.
/// Prints a separator to the result string.
void
sep
();
void
sep
();
inline
void
traverse
()
noexcept
{
void
consume
(
atom_value
x
);
// end of recursion
}
void
consume
(
atom_value
&
x
);
void
consume
(
string_view
str
);
void
consume
(
string_view
str
);
void
consume
(
timespan
&
x
);
void
consume
(
timespan
x
);
void
consume
(
timestamp
&
x
);
void
consume
(
timestamp
x
);
template
<
class
Clock
,
class
Duration
>
void
consume
(
bool
x
);
void
consume
(
std
::
chrono
::
time_point
<
Clock
,
Duration
>&
x
)
{
timestamp
tmp
{
std
::
chrono
::
duration_cast
<
timespan
>
(
x
.
time_since_epoch
())};
consume
(
tmp
);
}
template
<
class
Rep
,
class
Period
>
void
consume
(
const
void
*
ptr
);
void
consume
(
std
::
chrono
::
duration
<
Rep
,
Period
>&
x
)
{
auto
tmp
=
std
::
chrono
::
duration_cast
<
timespan
>
(
x
);
void
consume
(
const
char
*
cstr
);
consume
(
tmp
);
void
consume
(
const
std
::
vector
<
bool
>&
xs
);
template
<
class
T
>
enable_if_t
<
std
::
is_floating_point
<
T
>::
value
>
consume
(
T
x
)
{
result_
+=
std
::
to_string
(
x
);
}
}
inline
void
consume
(
bool
&
x
)
{
template
<
class
T
>
result_
+=
x
?
"true"
:
"false"
;
enable_if_t
<
std
::
is_integral
<
T
>::
value
&&
std
::
is_signed
<
T
>::
value
>
consume
(
T
x
)
{
consume_int
(
static_cast
<
int64_t
>
(
x
));
}
}
inline
void
consume
(
const
char
*
cstr
)
{
template
<
class
T
>
if
(
cstr
==
nullptr
)
{
enable_if_t
<
std
::
is_integral
<
T
>::
value
&&
std
::
is_unsigned
<
T
>::
value
>
result_
+=
"null"
;
consume
(
T
x
)
{
}
else
{
consume_int
(
static_cast
<
uint64_t
>
(
x
));
string_view
tmp
{
cstr
,
strlen
(
cstr
)};
consume
(
tmp
);
}
}
}
inline
void
consume
(
char
*
cstr
)
{
template
<
class
Clock
,
class
Duration
>
consume
(
const_cast
<
const
char
*>
(
cstr
));
void
consume
(
std
::
chrono
::
time_point
<
Clock
,
Duration
>
x
)
{
timestamp
tmp
{
std
::
chrono
::
duration_cast
<
timespan
>
(
x
.
time_since_epoch
())};
consume
(
tmp
);
}
}
template
<
class
T
>
template
<
class
Rep
,
class
Period
>
enable_if_tt
<
std
::
is_arithmetic
<
T
>>
consume
(
T
&
x
)
{
void
consume
(
std
::
chrono
::
duration
<
Rep
,
Period
>
x
)
{
result_
+=
std
::
to_string
(
x
);
auto
tmp
=
std
::
chrono
::
duration_cast
<
timespan
>
(
x
);
consume
(
tmp
);
}
}
//
unwrap std::ref
//
Unwrap std::ref.
template
<
class
T
>
template
<
class
T
>
void
consume
(
std
::
reference_wrapper
<
T
>
&
x
)
{
void
consume
(
std
::
reference_wrapper
<
T
>
x
)
{
return
consume
(
x
.
get
());
return
consume
(
x
.
get
());
}
}
/// Picks up user-defined `to_string` functions.
/// Picks up user-defined `to_string` functions.
template
<
class
T
>
template
<
class
T
>
enable_if_t
<!
std
::
is_pointer
<
T
>::
value
&&
has_to_string
<
T
>::
value
>
enable_if_t
<!
std
::
is_pointer
<
T
>::
value
&&
has_to_string
<
T
>::
value
>
consume
(
T
&
x
)
{
consume
(
const
T
&
x
)
{
result_
+=
to_string
(
x
);
result_
+=
to_string
(
x
);
}
}
/// Delegates to `inspect(*this, x)` if available and `T`
/// Delegates to `inspect(*this, x)` if available and `T`
does not provide
///
does not provide a `to_string`
.
///
a `to_string` overload
.
template
<
class
T
>
template
<
class
T
>
enable_if_t
<
enable_if_t
<
is_inspectable
<
stringification_inspector
,
T
>::
value
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
has_to_string
<
T
>::
value
>
&&
!
has_to_string
<
T
>::
value
>
consume
(
const
T
&
x
)
{
consume
(
T
&
x
)
{
inspect
(
*
this
,
const_cast
<
T
&>
(
x
));
inspect
(
*
this
,
x
);
}
}
template
<
class
F
,
class
S
>
template
<
class
F
,
class
S
>
void
consume
(
std
::
pair
<
F
,
S
>&
x
)
{
void
consume
(
const
std
::
pair
<
F
,
S
>&
x
)
{
result_
+=
'('
;
result_
+=
'('
;
traverse
(
deconst
(
x
.
first
),
deconst
(
x
.
second
)
);
traverse
(
x
.
first
,
x
.
second
);
result_
+=
')'
;
result_
+=
')'
;
}
}
template
<
class
...
Ts
>
template
<
class
...
Ts
>
void
consume
(
std
::
tuple
<
Ts
...
>&
x
)
{
void
consume
(
const
std
::
tuple
<
Ts
...
>&
x
)
{
result_
+=
'('
;
result_
+=
'('
;
apply_args
(
*
this
,
get_indices
(
x
),
x
);
apply_args
(
*
this
,
get_indices
(
x
),
x
);
result_
+=
')'
;
result_
+=
')'
;
...
@@ -154,69 +151,58 @@ public:
...
@@ -154,69 +151,58 @@ public:
template
<
class
T
>
template
<
class
T
>
enable_if_t
<
is_map_like
<
T
>::
value
enable_if_t
<
is_map_like
<
T
>::
value
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
&&
!
has_to_string
<
T
>::
value
>
&&
!
has_to_string
<
T
>::
value
>
consume
(
T
&
xs
)
{
consume
(
const
T
&
xs
)
{
result_
+=
'{'
;
result_
+=
'{'
;
for
(
const
auto
&
kvp
:
xs
)
{
for
(
const
auto
&
kvp
:
xs
)
{
sep
();
sep
();
consume
(
deconst
(
kvp
.
first
)
);
consume
(
kvp
.
first
);
result_
+=
" = "
;
result_
+=
" = "
;
consume
(
deconst
(
kvp
.
second
)
);
consume
(
kvp
.
second
);
}
}
result_
+=
'}'
;
result_
+=
'}'
;
}
}
template
<
class
T
>
template
<
class
Iterator
>
enable_if_t
<
is_iterable
<
T
>::
value
&&
!
is_map_like
<
T
>::
value
void
consume_range
(
Iterator
first
,
Iterator
last
)
{
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
&&
!
has_to_string
<
T
>::
value
>
consume
(
T
&
xs
)
{
result_
+=
'['
;
result_
+=
'['
;
// use a hand-written for loop instead of for-each to avoid
while
(
first
!=
last
)
{
// range-loop-analysis warnings when using this function with vector<bool>
for
(
auto
i
=
xs
.
begin
();
i
!=
xs
.
end
();
++
i
)
{
sep
();
sep
();
consume
(
deconst
(
*
i
)
);
consume
(
*
first
++
);
}
}
result_
+=
']'
;
result_
+=
']'
;
}
}
template
<
class
T
>
template
<
class
T
>
enable_if_t
<
has_peek_all
<
T
>::
value
enable_if_t
<
is_iterable
<
T
>::
value
&&
!
is_map_like
<
T
>::
value
&&
!
is_iterable
<
T
>::
value
// pick begin()/end() over peek_all
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
has_to_string
<
T
>::
value
>
&&
!
has_to_string
<
T
>::
value
>
consume
(
T
&
xs
)
{
consume
(
const
T
&
xs
)
{
result_
+=
'['
;
consume_range
(
xs
.
begin
(),
xs
.
end
());
xs
.
peek_all
(
*
this
);
result_
+=
']'
;
}
template
<
class
T
>
void
consume
(
T
*
xs
,
size_t
n
)
{
result_
+=
'('
;
for
(
size_t
i
=
0
;
i
<
n
;
++
i
)
{
sep
();
consume
(
deconst
(
xs
[
i
]));
}
result_
+=
')'
;
}
}
template
<
class
T
,
size_t
S
>
template
<
class
T
,
size_t
S
>
void
consume
(
std
::
array
<
T
,
S
>&
xs
)
{
void
consume
(
const
T
(
&
xs
)[
S
]
)
{
return
consume
(
xs
.
data
(),
S
);
return
consume
_range
(
xs
,
xs
+
S
);
}
}
template
<
class
T
,
size_t
S
>
template
<
class
T
>
void
consume
(
T
(
&
xs
)[
S
])
{
enable_if_t
<
has_peek_all
<
T
>::
value
return
consume
(
xs
,
S
);
&&
!
is_iterable
<
T
>::
value
// pick begin()/end() over peek_all
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
has_to_string
<
T
>::
value
>
consume
(
const
T
&
xs
)
{
result_
+=
'['
;
xs
.
peek_all
(
*
this
);
result_
+=
']'
;
}
}
template
<
class
T
>
template
<
class
T
>
enable_if_t
<!
std
::
is_same
<
decay_t
<
T
>
,
void
>::
value
>
enable_if_t
<
consume
(
T
*&
ptr
)
{
std
::
is_pointer
<
T
>::
value
&&
!
std
::
is_same
<
void
,
typename
std
::
remove_pointer
<
T
>::
type
>::
value
>
consume
(
const
T
ptr
)
{
if
(
ptr
)
{
if
(
ptr
)
{
result_
+=
'*'
;
result_
+=
'*'
;
consume
(
*
ptr
);
consume
(
*
ptr
);
...
@@ -225,68 +211,22 @@ public:
...
@@ -225,68 +211,22 @@ public:
}
}
}
}
inline
void
consume
(
const
void
*
ptr
)
{
result_
+=
"0x"
;
auto
int_val
=
reinterpret_cast
<
intptr_t
>
(
ptr
);
consume
(
int_val
);
}
/// Print duration types with nanosecond resolution.
template
<
class
Rep
>
void
consume
(
std
::
chrono
::
duration
<
Rep
,
std
::
nano
>&
x
)
{
result_
+=
std
::
to_string
(
x
.
count
());
result_
+=
"ns"
;
}
/// Print duration types with microsecond resolution.
template
<
class
Rep
>
void
consume
(
std
::
chrono
::
duration
<
Rep
,
std
::
micro
>&
x
)
{
result_
+=
std
::
to_string
(
x
.
count
());
result_
+=
"us"
;
}
/// Print duration types with millisecond resolution.
template
<
class
Rep
>
void
consume
(
std
::
chrono
::
duration
<
Rep
,
std
::
milli
>&
x
)
{
result_
+=
std
::
to_string
(
x
.
count
());
result_
+=
"ms"
;
}
/// Print duration types with second resolution.
template
<
class
Rep
>
void
consume
(
std
::
chrono
::
duration
<
Rep
,
std
::
ratio
<
1
>>&
x
)
{
result_
+=
std
::
to_string
(
x
.
count
());
result_
+=
"s"
;
}
/// Print duration types with minute resolution.
template
<
class
Rep
>
void
consume
(
std
::
chrono
::
duration
<
Rep
,
std
::
ratio
<
60
>>&
x
)
{
result_
+=
std
::
to_string
(
x
.
count
());
result_
+=
"min"
;
}
/// Print duration types with hour resolution.
template
<
class
Rep
>
void
consume
(
std
::
chrono
::
duration
<
Rep
,
std
::
ratio
<
3600
>>&
x
)
{
result_
+=
std
::
to_string
(
x
.
count
());
result_
+=
"h"
;
}
/// Fallback printing `<unprintable>`.
/// Fallback printing `<unprintable>`.
template
<
class
T
>
template
<
class
T
>
enable_if_t
<
enable_if_t
<!
is_iterable
<
T
>::
value
&&
!
has_peek_all
<
T
>::
value
!
is_iterable
<
T
>::
value
&&
!
std
::
is_pointer
<
T
>::
value
&&
!
has_peek_all
<
T
>::
value
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
std
::
is_pointer
<
T
>::
value
&&
!
std
::
is_arithmetic
<
T
>::
value
&&
!
is_inspectable
<
stringification_inspector
,
T
>::
value
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
&&
!
std
::
is_arithmetic
<
T
>::
value
&&
!
has_to_string
<
T
>::
value
>
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
consume
(
const
T
&
)
{
&&
!
has_to_string
<
T
>::
value
>
consume
(
T
&
)
{
result_
+=
"<unprintable>"
;
result_
+=
"<unprintable>"
;
}
}
void
traverse
()
{
// end of recursion
}
template
<
class
T
,
class
...
Ts
>
template
<
class
T
,
class
...
Ts
>
void
traverse
(
const
meta
::
hex_formatted_t
&
,
const
T
&
x
,
const
Ts
&
...
xs
)
{
void
traverse
(
const
meta
::
hex_formatted_t
&
,
const
T
&
x
,
const
Ts
&
...
xs
)
{
sep
();
sep
();
...
@@ -336,7 +276,7 @@ public:
...
@@ -336,7 +276,7 @@ public:
enable_if_t
<!
meta
::
is_annotation
<
T
>::
value
&&
!
is_callable
<
T
>::
value
>
enable_if_t
<!
meta
::
is_annotation
<
T
>::
value
&&
!
is_callable
<
T
>::
value
>
traverse
(
const
T
&
x
,
const
Ts
&
...
xs
)
{
traverse
(
const
T
&
x
,
const
Ts
&
...
xs
)
{
sep
();
sep
();
consume
(
deconst
(
x
)
);
consume
(
x
);
traverse
(
xs
...);
traverse
(
xs
...);
}
}
...
@@ -349,14 +289,12 @@ public:
...
@@ -349,14 +289,12 @@ public:
}
}
private:
private:
template
<
class
T
>
void
consume_int
(
int64_t
x
);
T
&
deconst
(
const
T
&
x
)
{
return
const_cast
<
T
&>
(
x
);
void
consume_int
(
uint64_t
x
);
}
std
::
string
&
result_
;
std
::
string
&
result_
;
};
};
}
// namespace detail
}
// namespace detail
}
// namespace caf
}
// namespace caf
libcaf_core/src/actor_system_config.cpp
View file @
68641365
...
@@ -336,7 +336,7 @@ void print(const config_value::dictionary& xs, indentation indent) {
...
@@ -336,7 +336,7 @@ void print(const config_value::dictionary& xs, indentation indent) {
cout
<<
indent
<<
kvp
.
first
<<
" = "
<<
to_string
(
kvp
.
second
)
<<
'\n'
;
cout
<<
indent
<<
kvp
.
first
<<
" = "
<<
to_string
(
kvp
.
second
)
<<
'\n'
;
}
}
}
}
}
;
}
}
// namespace <anonymous>
}
// namespace <anonymous>
...
...
libcaf_core/src/stringification_inspector.cpp
View file @
68641365
...
@@ -18,8 +18,35 @@
...
@@ -18,8 +18,35 @@
#include "caf/detail/stringification_inspector.hpp"
#include "caf/detail/stringification_inspector.hpp"
#include <algorithm>
#include <ctime>
#include <ctime>
#include "caf/atom.hpp"
namespace
{
void
escape
(
std
::
string
&
result
,
char
c
)
{
switch
(
c
)
{
default:
result
+=
c
;
break
;
case
'\n'
:
result
+=
R"(\n)"
;
break
;
case
'\t'
:
result
+=
R"(\t)"
;
break
;
case
'\\'
:
result
+=
R"(\\)"
;
break
;
case
'"'
:
result
+=
R"(\")"
;
break
;
}
}
}
// namespace
namespace
caf
{
namespace
caf
{
namespace
detail
{
namespace
detail
{
...
@@ -36,7 +63,7 @@ void stringification_inspector::sep() {
...
@@ -36,7 +63,7 @@ void stringification_inspector::sep() {
}
}
}
}
void
stringification_inspector
::
consume
(
atom_value
&
x
)
{
void
stringification_inspector
::
consume
(
atom_value
x
)
{
result_
+=
'\''
;
result_
+=
'\''
;
result_
+=
to_string
(
x
);
result_
+=
to_string
(
x
);
result_
+=
'\''
;
result_
+=
'\''
;
...
@@ -54,42 +81,54 @@ void stringification_inspector::consume(string_view str) {
...
@@ -54,42 +81,54 @@ void stringification_inspector::consume(string_view str) {
}
}
// Escape string.
// Escape string.
result_
+=
'"'
;
result_
+=
'"'
;
for
(
char
c
:
str
)
{
for
(
char
c
:
str
)
switch
(
c
)
{
escape
(
result_
,
c
);
default:
result_
+=
c
;
break
;
case
'\\'
:
result_
+=
R"(\\)"
;
break
;
case
'"'
:
result_
+=
R"(\")"
;
break
;
}
}
result_
+=
'"'
;
result_
+=
'"'
;
}
}
void
stringification_inspector
::
consume
(
timespan
&
x
)
{
void
stringification_inspector
::
consume
(
timespan
x
)
{
auto
count
=
x
.
count
();
auto
ns
=
x
.
count
();
auto
res
=
[
&
](
const
char
*
suffix
)
{
if
(
ns
%
1000
>
0
)
{
result_
+=
std
::
to_string
(
count
);
consume
(
ns
);
result_
+=
suffix
;
result_
+=
"ns"
;
};
return
;
// Check whether it's nano-, micro-, or milliseconds.
for
(
auto
suffix
:
{
"ns"
,
"us"
,
"ms"
})
{
if
(
count
%
1000
!=
0
)
return
res
(
suffix
);
count
/=
1000
;
}
}
// After the loop we only need to differentiate between seconds and minutes.
auto
us
=
ns
/
1000
;
if
(
count
%
60
!=
0
)
if
(
us
%
1000
>
0
)
{
return
res
(
"s"
);
consume
(
us
);
count
/=
60
;
result_
+=
"us"
;
return
res
(
"min"
);
return
;
}
auto
ms
=
us
/
1000
;
if
(
ms
%
1000
>
0
)
{
consume
(
ms
);
result_
+=
"ms"
;
return
;
}
auto
s
=
ms
/
1000
;
if
(
s
%
60
>
0
)
{
consume
(
s
);
result_
+=
"s"
;
return
;
}
auto
min
=
s
/
60
;
if
(
min
%
60
>
0
)
{
consume
(
min
);
result_
+=
"min"
;
return
;
}
auto
h
=
min
/
60
;
if
(
min
%
24
>
0
)
{
consume
(
h
);
result_
+=
"h"
;
return
;
}
auto
d
=
h
/
24
;
consume
(
d
);
result_
+=
"d"
;
}
}
void
stringification_inspector
::
consume
(
timestamp
&
x
)
{
void
stringification_inspector
::
consume
(
timestamp
x
)
{
char
buf
[
64
];
char
buf
[
64
];
auto
y
=
std
::
chrono
::
time_point_cast
<
timestamp
::
clock
::
duration
>
(
x
);
auto
y
=
std
::
chrono
::
time_point_cast
<
timestamp
::
clock
::
duration
>
(
x
);
auto
z
=
timestamp
::
clock
::
to_time_t
(
y
);
auto
z
=
timestamp
::
clock
::
to_time_t
(
y
);
...
@@ -104,5 +143,69 @@ void stringification_inspector::consume(timestamp& x) {
...
@@ -104,5 +143,69 @@ void stringification_inspector::consume(timestamp& x) {
result_
+=
frac
;
result_
+=
frac
;
}
}
void
stringification_inspector
::
consume
(
bool
x
)
{
result_
+=
x
?
"true"
:
"false"
;
}
void
stringification_inspector
::
consume
(
const
void
*
ptr
)
{
result_
+=
"0x"
;
consume
(
reinterpret_cast
<
intptr_t
>
(
ptr
));
}
void
stringification_inspector
::
consume
(
const
char
*
cstr
)
{
if
(
cstr
==
nullptr
)
{
result_
+=
"<null>"
;
return
;
}
if
(
cstr
[
0
]
==
'\0'
)
{
result_
+=
R"("")"
;
return
;
}
if
(
cstr
[
0
]
==
'"'
)
{
// Assume an already escaped string.
result_
+=
cstr
;
return
;
}
// Escape string.
result_
+=
'"'
;
for
(
char
c
=
*
cstr
++
;
c
!=
'\0'
;
c
=
*
cstr
++
)
escape
(
result_
,
c
);
result_
+=
'"'
;
}
void
stringification_inspector
::
consume
(
const
std
::
vector
<
bool
>&
xs
)
{
result_
+=
'['
;
for
(
bool
x
:
xs
)
{
sep
();
consume
(
x
);
}
result_
+=
']'
;
}
void
stringification_inspector
::
consume_int
(
int64_t
x
)
{
if
(
x
>=
0
)
return
consume_int
(
static_cast
<
uint64_t
>
(
x
));
result_
+=
'-'
;
auto
begin
=
result_
.
size
();
result_
+=
-
(
x
%
10
)
+
'0'
;
x
/=
10
;
while
(
x
!=
0
)
{
result_
+=
-
(
x
%
10
)
+
'0'
;
x
/=
10
;
}
std
::
reverse
(
result_
.
begin
()
+
begin
,
result_
.
end
());
}
void
stringification_inspector
::
consume_int
(
uint64_t
x
)
{
auto
begin
=
result_
.
size
();
result_
+=
(
x
%
10
)
+
'0'
;
x
/=
10
;
while
(
x
!=
0
)
{
result_
+=
(
x
%
10
)
+
'0'
;
x
/=
10
;
}
std
::
reverse
(
result_
.
begin
()
+
begin
,
result_
.
end
());
}
}
// namespace detail
}
// namespace detail
}
// namespace caf
}
// namespace caf
libcaf_core/test/deep_to_string.cpp
View file @
68641365
...
@@ -32,16 +32,38 @@ void foobar() {
...
@@ -32,16 +32,38 @@ void foobar() {
}
// namespace <anonymous>
}
// namespace <anonymous>
#define CHECK_DEEP_TO_STRING(val, str) CAF_CHECK_EQUAL(deep_to_string(val), str)
CAF_TEST
(
timespans
)
{
CAF_TEST
(
timespans
)
{
CAF_CHECK_EQUAL
(
deep_to_string
(
timespan
{
1
}),
"1ns"
);
CHECK_DEEP_TO_STRING
(
timespan
{
1
},
"1ns"
);
CAF_CHECK_EQUAL
(
deep_to_string
(
timespan
{
1000
}),
"1us"
);
CHECK_DEEP_TO_STRING
(
timespan
{
1000
},
"1us"
);
CAF_CHECK_EQUAL
(
deep_to_string
(
timespan
{
1000000
}),
"1ms"
);
CHECK_DEEP_TO_STRING
(
timespan
{
1000000
},
"1ms"
);
CAF_CHECK_EQUAL
(
deep_to_string
(
timespan
{
1000000000
}),
"1s"
);
CHECK_DEEP_TO_STRING
(
timespan
{
1000000000
},
"1s"
);
CAF_CHECK_EQUAL
(
deep_to_string
(
timespan
{
60000000000
}),
"1min"
);
CHECK_DEEP_TO_STRING
(
timespan
{
60000000000
},
"1min"
);
}
CAF_TEST
(
integer
lists
)
{
int
carray
[]
=
{
1
,
2
,
3
,
4
};
using
array_type
=
std
::
array
<
int
,
4
>
;
CHECK_DEEP_TO_STRING
(
std
::
list
<
int
>
({
1
,
2
,
3
,
4
}),
"[1, 2, 3, 4]"
);
CHECK_DEEP_TO_STRING
(
std
::
vector
<
int
>
({
1
,
2
,
3
,
4
}),
"[1, 2, 3, 4]"
);
CHECK_DEEP_TO_STRING
(
std
::
set
<
int
>
({
1
,
2
,
3
,
4
}),
"[1, 2, 3, 4]"
);
CHECK_DEEP_TO_STRING
(
array_type
({{
1
,
2
,
3
,
4
}}),
"[1, 2, 3, 4]"
);
CHECK_DEEP_TO_STRING
(
carray
,
"[1, 2, 3, 4]"
);
}
CAF_TEST
(
boolean
lists
)
{
bool
carray
[]
=
{
false
,
true
};
using
array_type
=
std
::
array
<
bool
,
2
>
;
CHECK_DEEP_TO_STRING
(
std
::
list
<
bool
>
({
false
,
true
}),
"[false, true]"
);
CHECK_DEEP_TO_STRING
(
std
::
vector
<
bool
>
({
false
,
true
}),
"[false, true]"
);
CHECK_DEEP_TO_STRING
(
std
::
set
<
bool
>
({
false
,
true
}),
"[false, true]"
);
CHECK_DEEP_TO_STRING
(
array_type
({{
false
,
true
}}),
"[false, true]"
);
CHECK_DEEP_TO_STRING
(
carray
,
"[false, true]"
);
}
}
CAF_TEST
(
pointers
)
{
CAF_TEST
(
pointers
)
{
auto
i
=
42
;
auto
i
=
42
;
C
AF_CHECK_EQUAL
(
deep_to_string
(
&
i
)
,
"*42"
);
C
HECK_DEEP_TO_STRING
(
&
i
,
"*42"
);
C
AF_CHECK_EQUAL
(
deep_to_string
(
foobar
)
,
"<fun>"
);
C
HECK_DEEP_TO_STRING
(
foobar
,
"<fun>"
);
}
}
libcaf_core/test/message.cpp
View file @
68641365
...
@@ -272,10 +272,10 @@ CAF_TEST(tuples_to_string) {
...
@@ -272,10 +272,10 @@ CAF_TEST(tuples_to_string) {
}
}
CAF_TEST
(
arrays_to_string
)
{
CAF_TEST
(
arrays_to_string
)
{
CAF_CHECK_EQUAL
(
msg_as_string
(
s1
{}),
"(
(10, 20, 30)
)"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
s1
{}),
"(
[10, 20, 30]
)"
);
auto
msg2
=
make_message
(
s2
{});
auto
msg2
=
make_message
(
s2
{});
s2
tmp
;
s2
tmp
;
tmp
.
value
[
0
][
1
]
=
100
;
tmp
.
value
[
0
][
1
]
=
100
;
CAF_CHECK_EQUAL
(
to_string
(
msg2
),
"(
((1, 10), (2, 20), (3, 30), (4, 40))
)"
);
CAF_CHECK_EQUAL
(
to_string
(
msg2
),
"(
[[1, 10], [2, 20], [3, 30], [4, 40]]
)"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
s3
{}),
"(
(1, 2, 3, 4)
)"
);
CAF_CHECK_EQUAL
(
msg_as_string
(
s3
{}),
"(
[1, 2, 3, 4]
)"
);
}
}
libcaf_core/test/serialization.cpp
View file @
68641365
...
@@ -554,7 +554,7 @@ SERIALIZATION_TEST(bool_vector_size_0) {
...
@@ -554,7 +554,7 @@ SERIALIZATION_TEST(bool_vector_size_0) {
SERIALIZATION_TEST
(
bool_vector_size_1
)
{
SERIALIZATION_TEST
(
bool_vector_size_1
)
{
std
::
vector
<
bool
>
xs
{
true
};
std
::
vector
<
bool
>
xs
{
true
};
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
"[
1
]"
);
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
"[
true
]"
);
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
}
...
@@ -563,11 +563,14 @@ SERIALIZATION_TEST(bool_vector_size_63) {
...
@@ -563,11 +563,14 @@ SERIALIZATION_TEST(bool_vector_size_63) {
std
::
vector
<
bool
>
xs
;
std
::
vector
<
bool
>
xs
;
for
(
int
i
=
0
;
i
<
63
;
++
i
)
for
(
int
i
=
0
;
i
<
63
;
++
i
)
xs
.
push_back
(
i
%
3
==
0
);
xs
.
push_back
(
i
%
3
==
0
);
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
CAF_CHECK_EQUAL
(
"[1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, "
deep_to_string
(
xs
),
"0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, "
"[true, false, false, true, false, false, true, false, false, true, false, "
"1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, "
"false, true, false, false, true, false, false, true, false, false, true, "
"0, 1, 0, 0]"
);
"false, false, true, false, false, true, false, false, true, false, false, "
"true, false, false, true, false, false, true, false, false, true, false, "
"false, true, false, false, true, false, false, true, false, false, true, "
"false, false, true, false, false, true, false, false]"
);
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
}
...
@@ -577,10 +580,14 @@ SERIALIZATION_TEST(bool_vector_size_64) {
...
@@ -577,10 +580,14 @@ SERIALIZATION_TEST(bool_vector_size_64) {
for
(
int
i
=
0
;
i
<
64
;
++
i
)
for
(
int
i
=
0
;
i
<
64
;
++
i
)
xs
.
push_back
(
i
%
5
==
0
);
xs
.
push_back
(
i
%
5
==
0
);
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
"[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, "
"[true, false, false, false, false, true, false, false, "
"0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, "
"false, false, true, false, false, false, false, true, "
"0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, "
"false, false, false, false, true, false, false, false, "
"0, 1, 0, 0, 0]"
);
"false, true, false, false, false, false, true, false, "
"false, false, false, true, false, false, false, false, "
"true, false, false, false, false, true, false, false, "
"false, false, true, false, false, false, false, true, "
"false, false, false, false, true, false, false, false]"
);
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
}
...
@@ -589,11 +596,14 @@ SERIALIZATION_TEST(bool_vector_size_65) {
...
@@ -589,11 +596,14 @@ SERIALIZATION_TEST(bool_vector_size_65) {
std
::
vector
<
bool
>
xs
;
std
::
vector
<
bool
>
xs
;
for
(
int
i
=
0
;
i
<
65
;
++
i
)
for
(
int
i
=
0
;
i
<
65
;
++
i
)
xs
.
push_back
(
!
(
i
%
7
==
0
));
xs
.
push_back
(
!
(
i
%
7
==
0
));
CAF_CHECK_EQUAL
(
deep_to_string
(
xs
),
CAF_CHECK_EQUAL
(
"[0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, "
deep_to_string
(
xs
),
"1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, "
"[false, true, true, true, true, true, true, false, true, true, true, "
"1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, "
"true, true, true, false, true, true, true, true, true, true, false, true, "
"1, 1, 1, 1, 0, 1]"
);
"true, true, true, true, true, false, true, true, true, true, true, true, "
"false, true, true, true, true, true, true, false, true, true, true, true, "
"true, true, false, true, true, true, true, true, true, false, true, true, "
"true, true, true, true, false, true]"
);
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
CAF_CHECK_EQUAL
(
xs
,
msg_roundtrip
(
xs
));
}
}
libcaf_core/test/serializer_impl.cpp
View file @
68641365
...
@@ -165,4 +165,4 @@ CAF_TEST(serialize and deserialize with std::vector<uint8_t>) {
...
@@ -165,4 +165,4 @@ CAF_TEST(serialize and deserialize with std::vector<uint8_t>) {
CAF_CHECK_EQUAL
(
data_to_serialize
,
deserialized_data
);
CAF_CHECK_EQUAL
(
data_to_serialize
,
deserialized_data
);
}
}
CAF_TEST_FIXTURE_SCOPE_END
()
;
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