Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Jan Koniarik
emlabcpp
Commits
aee523a3
Commit
aee523a3
authored
Oct 14, 2021
by
Jan Koniarik
Browse files
final refactoring of protocol lib and simple checks from clang tidy
parent
ba0646b9
Pipeline
#99396
failed with stage
in 1 minute and 7 seconds
Changes
16
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.clang-tidy
View file @
aee523a3
...
...
@@ -2,7 +2,7 @@
Checks: >
-*,
bugprone-*,
cppcore*, -cppcoreguidelines-owning-memory,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-macro-usage,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-pro-type-union-access,
cppcore*, -cppcoreguidelines-owning-memory,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-macro-usage,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-reinterpret-cast,
performance*,
modernize*, -modernize-use-trailing-return-type,-modernize-avoid-c-arrays
readbility*,
...
...
Makefile
View file @
aee523a3
...
...
@@ -8,7 +8,7 @@ clean:
rm
-rf
./build
build_test
:
cmake
-Bbuild
$(EXTRAARGS)
cmake
-Bbuild
$(EXTRAARGS)
-DCMAKE_EXPORT_COMPILE_COMMANDS
=
1
make
-Cbuild
-j
exec_test
:
build_test
...
...
include/emlabcpp/either.h
View file @
aee523a3
...
...
@@ -103,6 +103,9 @@ public:
either
&
operator
=
(
either
&&
other
)
noexcept
{
if
(
this
==
&
other
)
{
return
*
this
;
}
if
(
other
.
id_
==
item
::
LEFT
)
{
*
this
=
std
::
move
(
other
.
left_
);
}
else
{
...
...
@@ -134,11 +137,12 @@ public:
return
*
this
;
}
either
&
operator
=
(
either_unique_right
<
LH
,
RH
>
auto
&&
other
)
template
<
either_unique_right
<
LH
,
RH
>
T
>
either
&
operator
=
(
T
&&
other
)
{
destruct
();
id_
=
item
::
RIGHT
;
new
(
&
right_
)
right_item
(
std
::
move
(
other
)
);
new
(
&
right_
)
right_item
(
std
::
forward
<
T
>
(
other
)
);
return
*
this
;
}
...
...
@@ -401,8 +405,8 @@ inline auto assemble_left_collect_right( FirstE&& first, Eithers&&... others ) r
auto
convert
=
[
&
]
<
typename
Either
>
(
Either
&&
either
)
{
using
left_type
=
typename
std
::
remove_reference_t
<
Either
>::
left_item
;
return
std
::
move
(
either
)
.
convert_left
(
[
&
](
auto
item
)
{
//
return
std
::
forward
<
Either
>
(
either
)
.
convert_left
(
[
&
](
auto
item
)
{
return
std
::
make_optional
(
std
::
move
(
item
)
);
}
)
.
convert_right
(
[
&
](
auto
item
)
{
...
...
@@ -415,7 +419,7 @@ inline auto assemble_left_collect_right( FirstE&& first, Eithers&&... others ) r
return
assemble_optionals
(
convert
(
std
::
forward
<
FirstE
>
(
first
)
),
convert
(
std
::
forward
<
Eithers
>
(
others
)
)...
)
.
convert_right
(
[
&
](
empty_assembly_tag
)
{
//
.
convert_right
(
[
&
](
empty_assembly_tag
)
{
return
collection
;
}
);
}
...
...
include/emlabcpp/protocol/base.h
View file @
aee523a3
...
...
@@ -20,6 +20,9 @@ struct protocol_result
T
val
;
};
template
<
bounded_derived
size_type
,
typename
T
>
protocol_result
(
size_type
,
T
)
->
protocol_result
<
size_type
,
T
>
;
// Concept that matches types considered base - serialized directly by using byte shifting.
template
<
typename
T
>
concept
protocol_base_type
=
std
::
is_integral_v
<
T
>
||
std
::
is_enum_v
<
T
>
;
...
...
include/emlabcpp/protocol/decl.h
View file @
aee523a3
...
...
@@ -79,7 +79,7 @@ struct protocol_decl< protocol_sizeless_message< N > >
template
<
protocol_declarable
D
,
auto
Offset
>
struct
protocol_decl
<
protocol_offset
<
D
,
Offset
>
>
{
using
def_type
=
protocol_offset
<
D
,
Offset
>::
def_type
;
using
def_type
=
typename
protocol_offset
<
D
,
Offset
>::
def_type
;
using
def_decl
=
protocol_decl
<
def_type
>
;
using
value_type
=
typename
def_decl
::
value_type
;
...
...
@@ -107,7 +107,7 @@ struct protocol_decl< protocol_sized_buffer< CounterDecl, D > >
{
using
counter_decl
=
protocol_decl
<
CounterDecl
>
;
using
sub_decl
=
protocol_decl
<
D
>
;
using
value_type
=
sub_decl
::
value_type
;
using
value_type
=
typename
sub_decl
::
value_type
;
static
constexpr
std
::
size_t
max_size
=
counter_decl
::
max_size
+
sub_decl
::
max_size
;
};
...
...
include/emlabcpp/protocol/def.h
View file @
aee523a3
...
...
@@ -12,9 +12,14 @@
namespace
emlabcpp
{
// protocol_def<T,E> structure defines how type T should be serialized and deserialized. Each type
// or kind of types should overlead this structure and use same attributes as protocol_decl<T,E>. E
// is edianess of the serialization used.
template
<
typename
,
protocol_endianess_enum
>
struct
protocol_def
;
// protocol_def_check<T> concept verifies that 'T' is valid overload of protocol_def. Use this in
// tests of custom protocol_def overloads.
template
<
typename
T
>
concept
protocol_def_check
=
requires
()
{
...
...
@@ -608,7 +613,8 @@ struct protocol_def< protocol_group< Ds... >, Endianess >
sub_def
::
deserialize
(
buffer
).
match
(
[
&
](
auto
sub_res
)
{
opt_res
.
emplace
(
sub_res
.
used
,
value_type
{
sub_res
.
val
}
);
opt_res
=
protocol_result
<
size_type
,
value_type
>
{
sub_res
.
used
,
value_type
{
sub_res
.
val
}
};
},
[
&
](
protocol_error_record
)
{}
);
return
bool
(
opt_res
);
...
...
include/emlabcpp/protocol/error.h
View file @
aee523a3
...
...
@@ -9,7 +9,9 @@ namespace emlabcpp
// unique in that namespace, part of the error is also index of byte that caused the problem. These
// can be easily sent with the protocol lib itself.
using
protocol_mark
=
std
::
array
<
char
,
8
>
;
struct
protocol_mark
:
std
::
array
<
char
,
8
>
{
};
struct
protocol_error_record
{
...
...
include/emlabcpp/protocol/handler.h
View file @
aee523a3
...
...
@@ -5,6 +5,11 @@
namespace
emlabcpp
{
// protocol_handler< T > should be used to execute actual serialization and deserealization of
// protocol definition. It provides serialize/extract methods that should be used by the user.
//
// You may want to have this class (With the include) to be present in separate .cpp file, as the
// compile time can be quite heavy.
template
<
typename
T
>
struct
protocol_handler
{
...
...
@@ -14,7 +19,7 @@ struct protocol_handler
static
message_type
serialize
(
value_type
val
)
{
std
::
array
<
uint8_t
,
decl
::
max_size
>
buffer
;
std
::
array
<
uint8_t
,
decl
::
max_size
>
buffer
{}
;
bounded
used
=
decl
::
serialize_at
(
buffer
,
val
);
EMLABCPP_ASSERT
(
*
used
<=
decl
::
max_size
);
...
...
include/emlabcpp/protocol/message.h
View file @
aee523a3
...
...
@@ -9,6 +9,8 @@
namespace
emlabcpp
{
// Protocol library has custom type that represents message, however this is just simple overaly
// over std::array that remembers how many bytes are used.
template
<
std
::
size_t
N
>
class
protocol_message
{
...
...
@@ -117,6 +119,10 @@ protected:
}
};
// Sizeless message is class that behaves in a same way as normal protocol_message, however it is
// serialized differently. Protocol message stores how many bytes it's made of before the data
// itself in the final message, sizless message does not and greedely tries to parse rest of the
// buffer during the parsing process.
template
<
std
::
size_t
N
>
class
protocol_sizeless_message
:
public
protocol_message
<
N
>
{
...
...
@@ -148,6 +154,7 @@ namespace detail
}
}
// namespace detail
// concept matches any type that is protocol_message or derives from it.
template
<
typename
T
>
concept
protocol_message_derived
=
requires
(
T
val
)
{
...
...
include/emlabcpp/protocol/register_handler.h
View file @
aee523a3
...
...
@@ -6,6 +6,10 @@
namespace
emlabcpp
{
// Handler for serialization and extraction of datatypes used by the register_map. This provides
// interface for handling conversion of bytes to types used in the map. `serialize` and `extract`
// works directly with the types used by the map, based on compile time key. `select` and `insert`
// works with the map itself based on runtime information.
template
<
typename
Map
>
struct
protocol_register_handler
{
...
...
@@ -31,7 +35,7 @@ struct protocol_register_handler
return
*
message_type
::
make
(
view_n
(
buffer
.
begin
(),
*
used
)
);
}
static
message_type
se
rialize
(
const
map_type
&
m
,
key_type
key
)
static
message_type
se
lect
(
const
map_type
&
m
,
key_type
key
)
{
return
m
.
with_register
(
key
,
[
&
]
<
typename
reg_type
>
(
const
reg_type
&
reg
)
{
return
serialize
<
reg_type
::
key
>
(
reg
.
value
);
...
...
@@ -49,6 +53,22 @@ struct protocol_register_handler
return
sub_res
.
val
;
}
);
}
template
<
typename
Buffer
>
static
std
::
optional
<
protocol_error_record
>
insert
(
map_type
&
m
,
key_type
key
,
Buffer
&&
buff
)
{
std
::
optional
<
protocol_error_record
>
res
;
m
.
setup_register
(
key
,
[
&
]
<
typename
reg_type
>
()
{
return
extract
<
reg_type
::
key
>
(
buff
)
.
convert_right
(
[
&
](
auto
err
)
{
res
=
err
;
return
m
.
template
get_val
<
reg_type
::
key
>();
}
)
.
join
();
}
);
return
res
;
}
};
}
// namespace emlabcpp
include/emlabcpp/protocol/register_map.h
View file @
aee523a3
...
...
@@ -6,14 +6,14 @@
namespace
emlabcpp
{
template
<
auto
Key
,
typename
DefType
>
// Structure that represents definition of one register in the map. It also contains the value
// itself.
template
<
auto
Key
,
protocol_declarable
D
>
struct
protocol_reg
{
using
key_type
=
decltype
(
Key
);
static
constexpr
key_type
key
=
Key
;
using
def_type
=
DefType
;
using
def_type
=
D
;
using
key_type
=
decltype
(
Key
);
static
constexpr
key_type
key
=
Key
;
using
decl
=
protocol_decl
<
def_type
>
;
using
value_type
=
typename
decl
::
value_type
;
static
constexpr
std
::
size_t
size
=
decl
::
max_size
;
...
...
@@ -21,6 +21,13 @@ struct protocol_reg
value_type
value
;
};
// Register map is abstraction to work with registers of external devices. It stores values of
// serializable types that can be accessed based on key (usually enum representing address of
// register in the device).You can access the value based on the key itself, both at compile time
// and at runtime. You can also iterate over the values and there is handler that allows
// serialization and deserialization of bytes into the values defined in the map. This includes
// additional information that can be accessed about the map. This can also be used as simple table
// of configuration values.
template
<
typename
...
Regs
>
class
protocol_register_map
{
...
...
include/emlabcpp/protocol/streams.h
View file @
aee523a3
...
...
@@ -26,16 +26,17 @@ inline std::ostream& operator<<( std::ostream& os, const protocol_message< N >&
return
os
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
protocol_
error_record
&
rec
)
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
protocol_
mark
&
m
)
{
for
(
char
c
:
rec
.
ns
)
{
os
<<
c
;
}
os
<<
"::"
;
for
(
char
c
:
rec
.
err
)
{
for
(
char
c
:
m
)
{
os
<<
c
;
}
return
os
<<
" ("
<<
rec
.
byte_index
<<
")"
;
return
os
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
protocol_error_record
&
rec
)
{
return
os
<<
rec
.
ns
<<
"::"
<<
rec
.
err
<<
" ("
<<
rec
.
byte_index
<<
")"
;
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
protocol_endianess_enum
&
val
)
...
...
include/emlabcpp/protocol/tuple.h
View file @
aee523a3
...
...
@@ -5,6 +5,16 @@
namespace
emlabcpp
{
// protocol_tuple is high levle alternative to use just 'std::tuple' that is more friendly for
// standalone protocols. It is designed for message that are simply a set of serialized items. It
// also provieds more readable syntax. The template arguments at first configurate the protocol and
// later is follow by items present in the tuple, this can also be added with
// protocol_tuple::with_items alias that appends the items. For example:
//
// protocol_tuple< PROTOCOL_BIG_ENDIAN >::with_items< uint32_t, uint32_t >;
//
// serializes/deserializes in same way as 'std::tuple<uint32_t,uint32_t>' configured for big
// endianess.
template
<
protocol_endianess_enum
Endianess
,
typename
...
Ds
>
struct
protocol_tuple
:
protocol_def_type_base
{
...
...
include/emlabcpp/static_vector.h
View file @
aee523a3
...
...
@@ -53,11 +53,10 @@ public:
}
static_vector
&
operator
=
(
const
static_vector
&
other
)
{
if
(
this
==
&
other
)
{
return
*
this
;
if
(
this
!=
&
other
)
{
this
->~
static_vector
();
::
new
(
this
)
static_vector
(
other
);
}
this
->~
static_vector
();
::
new
(
this
)
static_vector
(
other
);
return
*
this
;
}
static_vector
&
operator
=
(
static_vector
&&
other
)
noexcept
...
...
@@ -187,8 +186,7 @@ private:
::
new
(
gen_ptr
)
T
(
std
::
forward
<
Args
>
(
args
)...
);
}
// Reference to the item in data_storage. std::launder is necessary here per the paper
// linked above.
// Reference to the item in data_storage.
[[
nodiscard
]]
reference
ref_item
(
size_type
i
)
{
return
*
std
::
launder
(
reinterpret_cast
<
T
*
>
(
&
data_
[
i
]
)
);
...
...
tests/protocol_def_test.cpp
View file @
aee523a3
...
...
@@ -59,7 +59,8 @@ struct valid_test_case : protocol_test_fixture
};
template
<
protocol_endianess_enum
Endianess
,
typename
T
>
std
::
function
<
protocol_test_fixture
*
()
>
make_valid_test_case
(
T
val
,
std
::
vector
<
uint8_t
>
buff
)
std
::
function
<
protocol_test_fixture
*
()
>
make_valid_test_case
(
T
val
,
const
std
::
vector
<
uint8_t
>&
buff
)
{
return
[
=
]()
{
return
new
valid_test_case
<
Endianess
,
T
>
(
val
,
buff
);
...
...
@@ -68,7 +69,7 @@ std::function< protocol_test_fixture*() > make_valid_test_case( T val, std::vect
template
<
protocol_endianess_enum
Endianess
,
typename
T
>
std
::
function
<
protocol_test_fixture
*
()
>
make_specific_valid_test_case
(
typename
protocol_def
<
T
,
Endianess
>::
value_type
val
,
std
::
vector
<
uint8_t
>
buff
)
const
std
::
vector
<
uint8_t
>
&
buff
)
{
return
[
=
]()
{
return
new
valid_test_case
<
Endianess
,
T
>
(
val
,
buff
);
...
...
@@ -117,7 +118,7 @@ struct invalid_test_case : protocol_test_fixture
template
<
typename
T
>
std
::
function
<
protocol_test_fixture
*
()
>
make_invalid_test_case
(
std
::
vector
<
uint8_t
>
buff
,
protocol_error_record
rec
)
make_invalid_test_case
(
const
std
::
vector
<
uint8_t
>
&
buff
,
const
protocol_error_record
&
rec
)
{
return
[
=
]()
{
return
new
invalid_test_case
<
T
>
(
buff
,
rec
);
...
...
tests/protocol_sophisticated_test.cpp
View file @
aee523a3
...
...
@@ -100,10 +100,10 @@ struct valid_test_case : protocol_test_fixture
template
<
typename
Group
>
std
::
function
<
protocol_test_fixture
*
()
>
make_valid_test_case
(
typename
Group
::
value_type
val
,
std
::
vector
<
uint8_t
>
buff
)
make_valid_test_case
(
typename
Group
::
value_type
val
,
const
std
::
vector
<
uint8_t
>
&
buff
)
{
return
[
=
]()
{
return
new
valid_test_case
<
Group
>
(
val
,
std
::
move
(
buff
)
);
return
new
valid_test_case
<
Group
>
(
val
,
buff
);
};
}
...
...
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