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
2d78dbd6
Unverified
Commit
2d78dbd6
authored
Mar 06, 2020
by
Joseph Noir
Committed by
GitHub
Mar 06, 2020
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1058
Add parse function for node_id
parents
1541aa45
2cf81be9
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
219 additions
and
6 deletions
+219
-6
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+1
-0
libcaf_core/caf/node_id.hpp
libcaf_core/caf/node_id.hpp
+10
-2
libcaf_core/caf/parser_state.hpp
libcaf_core/caf/parser_state.hpp
+35
-1
libcaf_core/caf/uri.hpp
libcaf_core/caf/uri.hpp
+5
-0
libcaf_core/src/node_id.cpp
libcaf_core/src/node_id.cpp
+50
-2
libcaf_core/src/uri.cpp
libcaf_core/src/uri.cpp
+59
-0
libcaf_core/test/node_id.cpp
libcaf_core/test/node_id.cpp
+53
-0
libcaf_core/test/uri.cpp
libcaf_core/test/uri.cpp
+6
-1
No files found.
libcaf_core/CMakeLists.txt
View file @
2d78dbd6
...
@@ -249,6 +249,7 @@ set(CAF_CORE_TEST_SOURCES
...
@@ -249,6 +249,7 @@ set(CAF_CORE_TEST_SOURCES
test/mixin/sender.cpp
test/mixin/sender.cpp
test/mock_streaming_classes.cpp
test/mock_streaming_classes.cpp
test/native_streaming_classes.cpp
test/native_streaming_classes.cpp
test/node_id.cpp
test/optional.cpp
test/optional.cpp
test/or_else.cpp
test/or_else.cpp
test/pipeline_streaming.cpp
test/pipeline_streaming.cpp
...
...
libcaf_core/caf/node_id.hpp
View file @
2d78dbd6
...
@@ -103,6 +103,8 @@ public:
...
@@ -103,6 +103,8 @@ public:
static
bool
valid
(
const
host_id_type
&
x
)
noexcept
;
static
bool
valid
(
const
host_id_type
&
x
)
noexcept
;
static
bool
can_parse
(
string_view
str
)
noexcept
;
// -- interface implementation ---------------------------------------------
// -- interface implementation ---------------------------------------------
bool
valid
()
const
noexcept
override
;
bool
valid
()
const
noexcept
override
;
...
@@ -230,6 +232,9 @@ public:
...
@@ -230,6 +232,9 @@ public:
/// @endcond
/// @endcond
/// Returns whether `parse` would produce a valid node ID.
static
bool
can_parse
(
string_view
str
)
noexcept
;
/// @relates node_id
/// @relates node_id
friend
CAF_CORE_EXPORT
error
inspect
(
serializer
&
sink
,
node_id
&
x
);
friend
CAF_CORE_EXPORT
error
inspect
(
serializer
&
sink
,
node_id
&
x
);
...
@@ -327,8 +332,11 @@ CAF_CORE_EXPORT node_id make_node_id(
...
@@ -327,8 +332,11 @@ CAF_CORE_EXPORT node_id make_node_id(
/// @param process_id System-wide unique process identifier.
/// @param process_id System-wide unique process identifier.
/// @param host_hash Unique node ID as hexadecimal string representation.
/// @param host_hash Unique node ID as hexadecimal string representation.
/// @relates node_id
/// @relates node_id
CAF_CORE_EXPORT
optional
<
node_id
>
CAF_CORE_EXPORT
optional
<
node_id
>
make_node_id
(
uint32_t
process_id
,
make_node_id
(
uint32_t
process_id
,
const
std
::
string
&
host_hash
);
string_view
host_hash
);
/// @relates node_id
CAF_CORE_EXPORT
error
parse
(
string_view
str
,
node_id
&
dest
);
}
// namespace caf
}
// namespace caf
...
...
libcaf_core/caf/parser_state.hpp
View file @
2d78dbd6
...
@@ -91,7 +91,8 @@ struct parser_state {
...
@@ -91,7 +91,8 @@ struct parser_state {
c
=
next
();
c
=
next
();
}
}
/// Tries to read `x` as the next character (skips any whitespaces).
/// Tries to read `x` as the next character, automatically skipping leading
/// whitespaces.
bool
consume
(
char
x
)
noexcept
{
bool
consume
(
char
x
)
noexcept
{
skip_whitespaces
();
skip_whitespaces
();
if
(
current
()
==
x
)
{
if
(
current
()
==
x
)
{
...
@@ -100,6 +101,39 @@ struct parser_state {
...
@@ -100,6 +101,39 @@ struct parser_state {
}
}
return
false
;
return
false
;
}
}
/// Consumes the next character if it satisfies given predicate, automatically
/// skipping leading whitespaces.
template
<
class
Predicate
>
bool
consume_if
(
Predicate
predicate
)
noexcept
{
skip_whitespaces
();
if
(
predicate
(
current
()))
{
next
();
return
true
;
}
return
false
;
}
/// Tries to read `x` as the next character without automatically skipping
/// leading whitespaces.
bool
consume_strict
(
char
x
)
noexcept
{
if
(
current
()
==
x
)
{
next
();
return
true
;
}
return
false
;
}
/// Consumes the next character if it satisfies given predicate without
/// automatically skipping leading whitespaces.
template
<
class
Predicate
>
bool
consume_strict_if
(
Predicate
predicate
)
noexcept
{
if
(
predicate
(
current
()))
{
next
();
return
true
;
}
return
false
;
}
};
};
/// Returns an error object from the current code in `ps` as well as its
/// Returns an error object from the current code in `ps` as well as its
...
...
libcaf_core/caf/uri.hpp
View file @
2d78dbd6
...
@@ -121,6 +121,11 @@ public:
...
@@ -121,6 +121,11 @@ public:
int
compare
(
string_view
x
)
const
noexcept
;
int
compare
(
string_view
x
)
const
noexcept
;
// -- parsing ----------------------------------------------------------------
/// Returns whether `parse` would produce a valid URI.
static
bool
can_parse
(
string_view
str
)
noexcept
;
// -- friend functions -------------------------------------------------------
// -- friend functions -------------------------------------------------------
friend
CAF_CORE_EXPORT
error
inspect
(
caf
::
serializer
&
dst
,
uri
&
x
);
friend
CAF_CORE_EXPORT
error
inspect
(
caf
::
serializer
&
dst
,
uri
&
x
);
...
...
libcaf_core/src/node_id.cpp
View file @
2d78dbd6
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cstring>
#include <ctype.h>
#include <iterator>
#include <iterator>
#include <random>
#include <random>
#include <sstream>
#include <sstream>
...
@@ -31,10 +32,13 @@
...
@@ -31,10 +32,13 @@
#include "caf/detail/get_mac_addresses.hpp"
#include "caf/detail/get_mac_addresses.hpp"
#include "caf/detail/get_process_id.hpp"
#include "caf/detail/get_process_id.hpp"
#include "caf/detail/get_root_uuid.hpp"
#include "caf/detail/get_root_uuid.hpp"
#include "caf/detail/parse.hpp"
#include "caf/detail/parser/ascii_to_int.hpp"
#include "caf/detail/parser/ascii_to_int.hpp"
#include "caf/detail/ripemd_160.hpp"
#include "caf/detail/ripemd_160.hpp"
#include "caf/expected.hpp"
#include "caf/logger.hpp"
#include "caf/logger.hpp"
#include "caf/make_counted.hpp"
#include "caf/make_counted.hpp"
#include "caf/parser_state.hpp"
#include "caf/sec.hpp"
#include "caf/sec.hpp"
#include "caf/serializer.hpp"
#include "caf/serializer.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/string_algorithms.hpp"
...
@@ -93,6 +97,24 @@ bool node_id::default_data::valid(const host_id_type& x) noexcept {
...
@@ -93,6 +97,24 @@ bool node_id::default_data::valid(const host_id_type& x) noexcept {
return
!
std
::
all_of
(
x
.
begin
(),
x
.
end
(),
is_zero
);
return
!
std
::
all_of
(
x
.
begin
(),
x
.
end
(),
is_zero
);
}
}
bool
node_id
::
default_data
::
can_parse
(
string_view
str
)
noexcept
{
// Our format is "<20-byte-hex>#<pid>". With 2 characters per byte, this means
// a valid node ID has at least 42 characters.
if
(
str
.
size
()
<
42
)
return
false
;
string_parser_state
ps
{
str
.
begin
(),
str
.
end
()};
for
(
size_t
i
=
0
;
i
<
40
;
++
i
)
if
(
!
ps
.
consume_strict_if
(
isxdigit
))
return
false
;
if
(
!
ps
.
consume_strict
(
'#'
))
return
false
;
// We don't care for the value, but we invoke the actual number parser to make
// sure the value is in bounds.
uint32_t
dummy
;
detail
::
parse
(
ps
,
dummy
);
return
ps
.
code
==
pec
::
success
;
}
bool
node_id
::
default_data
::
valid
()
const
noexcept
{
bool
node_id
::
default_data
::
valid
()
const
noexcept
{
return
pid_
!=
0
&&
valid
(
host_
);
return
pid_
!=
0
&&
valid
(
host_
);
}
}
...
@@ -228,6 +250,10 @@ void node_id::swap(node_id& x) {
...
@@ -228,6 +250,10 @@ void node_id::swap(node_id& x) {
data_
.
swap
(
x
.
data_
);
data_
.
swap
(
x
.
data_
);
}
}
bool
node_id
::
can_parse
(
string_view
str
)
noexcept
{
return
default_data
::
can_parse
(
str
)
||
uri
::
can_parse
(
str
);
}
namespace
{
namespace
{
template
<
class
Serializer
>
template
<
class
Serializer
>
...
@@ -307,8 +333,7 @@ node_id make_node_id(uint32_t process_id,
...
@@ -307,8 +333,7 @@ node_id make_node_id(uint32_t process_id,
return
node_id
{
std
::
move
(
ptr
)};
return
node_id
{
std
::
move
(
ptr
)};
}
}
optional
<
node_id
>
make_node_id
(
uint32_t
process_id
,
optional
<
node_id
>
make_node_id
(
uint32_t
process_id
,
string_view
host_hash
)
{
const
std
::
string
&
host_hash
)
{
using
node_data
=
node_id
::
default_data
;
using
node_data
=
node_id
::
default_data
;
if
(
host_hash
.
size
()
!=
node_data
::
host_id_size
*
2
)
if
(
host_hash
.
size
()
!=
node_data
::
host_id_size
*
2
)
return
none
;
return
none
;
...
@@ -328,4 +353,27 @@ optional<node_id> make_node_id(uint32_t process_id,
...
@@ -328,4 +353,27 @@ optional<node_id> make_node_id(uint32_t process_id,
return
make_node_id
(
process_id
,
host_id
);
return
make_node_id
(
process_id
,
host_id
);
}
}
error
parse
(
string_view
str
,
node_id
&
dest
)
{
if
(
node_id
::
default_data
::
can_parse
(
str
))
{
CAF_ASSERT
(
str
.
size
()
>=
42
);
auto
host_hash
=
str
.
substr
(
0
,
40
);
auto
pid_str
=
str
.
substr
(
41
);
uint32_t
pid_val
=
0
;
if
(
auto
err
=
detail
::
parse
(
pid_str
,
pid_val
))
return
err
;
if
(
auto
nid
=
make_node_id
(
pid_val
,
host_hash
))
{
dest
=
std
::
move
(
*
nid
);
return
none
;
}
CAF_LOG_ERROR
(
"make_node_id failed after can_parse returned true"
);
return
sec
::
invalid_argument
;
}
if
(
auto
nid_uri
=
make_uri
(
str
))
{
dest
=
make_node_id
(
std
::
move
(
*
nid_uri
));
return
none
;
}
else
{
return
std
::
move
(
nid_uri
.
error
());
}
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/uri.cpp
View file @
2d78dbd6
...
@@ -98,6 +98,65 @@ int uri::compare(string_view x) const noexcept {
...
@@ -98,6 +98,65 @@ int uri::compare(string_view x) const noexcept {
return
string_view
{
str
()}.
compare
(
x
);
return
string_view
{
str
()}.
compare
(
x
);
}
}
// -- parsing ------------------------------------------------------------------
namespace
{
class
nop_builder
{
public:
template
<
class
T
>
nop_builder
&
scheme
(
T
&&
)
{
return
*
this
;
}
template
<
class
T
>
nop_builder
&
userinfo
(
T
&&
)
{
return
*
this
;
}
template
<
class
T
>
nop_builder
&
host
(
T
&&
)
{
return
*
this
;
}
template
<
class
T
>
nop_builder
&
port
(
T
&&
)
{
return
*
this
;
}
template
<
class
T
>
nop_builder
&
path
(
T
&&
)
{
return
*
this
;
}
template
<
class
T
>
nop_builder
&
query
(
T
&&
)
{
return
*
this
;
}
template
<
class
T
>
nop_builder
&
fragment
(
T
&&
)
{
return
*
this
;
}
};
}
// namespace
bool
uri
::
can_parse
(
string_view
str
)
noexcept
{
string_parser_state
ps
{
str
.
begin
(),
str
.
end
()};
nop_builder
builder
;
if
(
ps
.
consume
(
'<'
))
{
detail
::
parser
::
read_uri
(
ps
,
builder
);
if
(
ps
.
code
>
pec
::
trailing_character
)
return
false
;
if
(
!
ps
.
consume
(
'>'
))
return
false
;
}
else
{
detail
::
parser
::
read_uri
(
ps
,
builder
);
}
return
ps
.
code
==
pec
::
success
;
}
// -- friend functions ---------------------------------------------------------
// -- friend functions ---------------------------------------------------------
error
inspect
(
caf
::
serializer
&
dst
,
uri
&
x
)
{
error
inspect
(
caf
::
serializer
&
dst
,
uri
&
x
)
{
...
...
libcaf_core/test/node_id.cpp
0 → 100644
View file @
2d78dbd6
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE node_id
#include "caf/node_id.hpp"
#include "caf/test/dsl.hpp"
using
namespace
caf
;
#define CHECK_PARSE_OK(str, ...) \
do { \
CAF_CHECK(node_id::can_parse(str)); \
node_id nid; \
CAF_CHECK_EQUAL(parse(str, nid), none); \
CAF_CHECK_EQUAL(nid, make_node_id(__VA_ARGS__)); \
} while (false)
CAF_TEST
(
node
IDs
are
convertible
from
string
)
{
node_id
::
default_data
::
host_id_type
hash
{{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
,
15
,
16
,
17
,
18
,
19
,
20
,
}};
auto
uri_id
=
unbox
(
make_uri
(
"ip://foo:8080"
));
CHECK_PARSE_OK
(
"0102030405060708090A0B0C0D0E0F1011121314#1"
,
1
,
hash
);
CHECK_PARSE_OK
(
"0102030405060708090A0B0C0D0E0F1011121314#123"
,
123
,
hash
);
CHECK_PARSE_OK
(
"ip://foo:8080"
,
uri_id
);
}
#define CHECK_PARSE_FAIL(str) CAF_CHECK(!node_id::can_parse(str))
CAF_TEST
(
node
IDs
are
not
convertible
from
malformed
strings
)
{
// not URIs
CHECK_PARSE_FAIL
(
"foobar"
);
CHECK_PARSE_FAIL
(
"CAF#1"
);
// uint32_t overflow on the process ID
CHECK_PARSE_FAIL
(
"0102030405060708090A0B0C0D0E0F1011121314#42949672950"
);
}
libcaf_core/test/uri.cpp
View file @
2d78dbd6
...
@@ -209,6 +209,7 @@ uri operator "" _u(const char* cstr, size_t cstr_len) {
...
@@ -209,6 +209,7 @@ uri operator "" _u(const char* cstr, size_t cstr_len) {
bool
operator
""
_i
(
const
char
*
cstr
,
size_t
cstr_len
)
{
bool
operator
""
_i
(
const
char
*
cstr
,
size_t
cstr_len
)
{
uri
result
;
uri
result
;
string_view
str
{
cstr
,
cstr_len
};
string_view
str
{
cstr
,
cstr_len
};
CAF_CHECK
(
!
uri
::
can_parse
(
str
));
auto
err
=
parse
(
str
,
result
);
auto
err
=
parse
(
str
,
result
);
return
err
!=
none
;
return
err
!=
none
;
}
}
...
@@ -278,7 +279,11 @@ CAF_TEST(builder construction) {
...
@@ -278,7 +279,11 @@ CAF_TEST(builder construction) {
CAF_CHECK_EQUAL
(
escaped
,
"hi%20there://it%27s@me%2F/file%201#%5B42%5D"
);
CAF_CHECK_EQUAL
(
escaped
,
"hi%20there://it%27s@me%2F/file%201#%5B42%5D"
);
}
}
#define ROUNDTRIP(str) CAF_CHECK_EQUAL(str##_u, str)
#define ROUNDTRIP(str) \
do { \
CAF_CHECK(uri::can_parse(str)); \
CAF_CHECK_EQUAL(str##_u, str); \
} while (false)
CAF_TEST
(
from
string
)
{
CAF_TEST
(
from
string
)
{
// all combinations of components
// all combinations of components
...
...
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