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
89115514
Commit
89115514
authored
Jan 29, 2015
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add `message::filter` function & CLI utility
parent
ac19cd13
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
487 additions
and
142 deletions
+487
-142
examples/qtsupport/qt_group_chat.cpp
examples/qtsupport/qt_group_chat.cpp
+47
-77
examples/remote_actors/distributed_calculator.cpp
examples/remote_actors/distributed_calculator.cpp
+30
-36
examples/remote_actors/group_chat.cpp
examples/remote_actors/group_chat.cpp
+10
-11
libcaf_core/caf/message.hpp
libcaf_core/caf/message.hpp
+104
-9
libcaf_core/caf/message_builder.hpp
libcaf_core/caf/message_builder.hpp
+8
-0
libcaf_core/src/message.cpp
libcaf_core/src/message.cpp
+167
-5
libcaf_core/src/message_builder.cpp
libcaf_core/src/message_builder.cpp
+0
-4
unit_testing/CMakeLists.txt
unit_testing/CMakeLists.txt
+1
-0
unit_testing/test_message.cpp
unit_testing/test_message.cpp
+120
-0
No files found.
examples/qtsupport/qt_group_chat.cpp
View file @
89115514
...
@@ -21,89 +21,59 @@
...
@@ -21,89 +21,59 @@
#include <QApplication>
#include <QApplication>
#include "caf/all.hpp"
#include "caf/all.hpp"
#include "cppa/opt.hpp"
#include "ui_chatwindow.h" // auto generated from chatwindow.ui
#include "ui_chatwindow.h" // auto generated from chatwindow.ui
using
namespace
std
;
using
namespace
std
;
using
namespace
caf
;
using
namespace
caf
;
/*
namespace {
struct line { string str; };
istream& operator>>(istream& is, line& l) {
getline(is, l.str);
return is;
}
any_tuple s_last_line;
any_tuple split_line(const line& l) {
vector<string> result;
stringstream strs(l.str);
string tmp;
while (getline(strs, tmp, ' ')) {
if (!tmp.empty()) result.push_back(std::move(tmp));
}
s_last_line = any_tuple::view(std::move(result));
return s_last_line;
}
} // namespace <anonymous>
*/
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
string
name
;
string
name
;
string
group_id
;
string
group_id
;
auto
res
=
message_builder
(
argv
+
1
,
argv
+
argc
).
filter_cli
({
options_description
desc
;
{
"name,n"
,
"set chat name"
,
name
},
bool
args_valid
=
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
{
"group,g"
,
"join chat group"
,
group_id
}
on_opt1
(
'n'
,
"name"
,
&
desc
,
"set name"
)
>>
rd_arg
(
name
),
});
on_opt1
(
'g'
,
"group"
,
&
desc
,
"join group <arg1>"
)
>>
rd_arg
(
group_id
),
if
(
!
res
.
remainder
.
empty
())
{
on_opt0
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
std
::
cerr
<<
res
.
helptext
<<
std
::
endl
;
);
return
1
;
}
group
gptr
;
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
// evaluate group parameter
return
0
;
if
(
!
group_id
.
empty
())
{
}
auto
p
=
group_id
.
find
(
':'
);
group
gptr
;
if
(
p
==
std
::
string
::
npos
)
{
// evaluate group parameter
cerr
<<
"*** error parsing argument "
<<
group_id
if
(
!
group_id
.
empty
())
{
<<
", expected format: <module_name>:<group_id>"
;
auto
p
=
group_id
.
find
(
':'
);
}
if
(
p
==
std
::
string
::
npos
)
{
else
{
cerr
<<
"*** error parsing argument "
<<
group_id
try
{
<<
", expected format: <module_name>:<group_id>"
;
gptr
=
group
::
get
(
group_id
.
substr
(
0
,
p
),
}
else
{
group_id
.
substr
(
p
+
1
));
try
{
}
gptr
=
group
::
get
(
group_id
.
substr
(
0
,
p
),
group_id
.
substr
(
p
+
1
));
catch
(
exception
&
e
)
{
}
catch
(
exception
&
e
)
{
ostringstream
err
;
ostringstream
err
;
cerr
<<
"*** exception: group::get(
\"
"
<<
group_id
.
substr
(
0
,
p
)
cerr
<<
"*** exception: group::get(
\"
"
<<
group_id
.
substr
(
0
,
p
)
<<
"
\"
,
\"
"
<<
group_id
.
substr
(
p
+
1
)
<<
"
\"
) failed; "
<<
"
\"
,
\"
"
<<
group_id
.
substr
(
p
+
1
)
<<
"
\"
) failed; "
<<
to_verbose_string
(
e
)
<<
endl
;
<<
to_verbose_string
(
e
)
<<
endl
;
}
}
}
}
if
(
!
args_valid
)
print_desc_and_exit
(
&
desc
)();
QApplication
app
(
argc
,
argv
);
app
.
setQuitOnLastWindowClosed
(
true
);
QMainWindow
mw
;
Ui
::
ChatWindow
helper
;
helper
.
setupUi
(
&
mw
);
auto
client
=
helper
.
chatwidget
->
as_actor
();
if
(
!
name
.
empty
())
{
send_as
(
client
,
client
,
atom
(
"setName"
),
move
(
name
));
}
if
(
gptr
)
{
send_as
(
client
,
client
,
atom
(
"join"
),
gptr
);
}
}
mw
.
show
();
}
auto
res
=
app
.
exec
();
QApplication
app
(
argc
,
argv
);
shutdown
();
app
.
setQuitOnLastWindowClosed
(
true
);
await_all_actors_done
();
QMainWindow
mw
;
return
res
;
Ui
::
ChatWindow
helper
;
helper
.
setupUi
(
&
mw
);
auto
client
=
helper
.
chatwidget
->
as_actor
();
if
(
!
name
.
empty
())
{
send_as
(
client
,
client
,
atom
(
"setName"
),
move
(
name
));
}
if
(
gptr
)
{
send_as
(
client
,
client
,
atom
(
"join"
),
gptr
);
}
mw
.
show
();
auto
app_res
=
app
.
exec
();
await_all_actors_done
();
shutdown
();
return
app_res
;
}
}
examples/remote_actors/distributed_calculator.cpp
View file @
89115514
...
@@ -21,9 +21,6 @@
...
@@ -21,9 +21,6 @@
#include "caf/all.hpp"
#include "caf/all.hpp"
#include "caf/io/all.hpp"
#include "caf/io/all.hpp"
// the options_description API is deprecated
#include "cppa/opt.hpp"
using
namespace
std
;
using
namespace
std
;
using
namespace
caf
;
using
namespace
caf
;
...
@@ -183,41 +180,40 @@ void client_repl(const string& host, uint16_t port) {
...
@@ -183,41 +180,40 @@ void client_repl(const string& host, uint16_t port) {
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
string
mode
;
string
host
;
uint16_t
port
=
0
;
uint16_t
port
=
0
;
options_description
desc
;
string
host
=
"localhost"
;
auto
set_mode
=
[
&
](
const
string
&
arg
)
->
function
<
bool
()
>
{
auto
res
=
message_builder
(
argv
+
1
,
argv
+
argc
).
to_message
().
filter_cli
({
return
[
arg
,
&
mode
]()
->
bool
{
{
"port,p"
,
"set port (either to publish at or to connect to)"
,
port
},
if
(
!
mode
.
empty
())
{
{
"host,H"
,
"set host (client mode only, default: localhost)"
,
host
},
cerr
<<
"mode already set to "
<<
mode
<<
endl
;
{
"server,s"
,
"run in server mode"
},
return
false
;
{
"client,c"
,
"run in client mode"
}
}
});
mode
=
move
(
arg
);
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
return
true
;
return
0
;
};
}
};
if
(
!
res
.
remainder
.
empty
())
{
string
copts
=
"client options"
;
cerr
<<
"*** invalid command line options"
<<
endl
<<
res
.
helptext
<<
endl
;
string
sopts
=
"server options"
;
return
1
;
bool
args_valid
=
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
}
on_opt1
(
'p'
,
"port"
,
&
desc
,
"set port"
)
>>
rd_arg
(
port
),
bool
is_server
=
res
.
opts
.
count
(
"server"
)
>
0
;
on_opt1
(
'H'
,
"host"
,
&
desc
,
"set host (default: localhost)"
,
copts
)
>>
rd_arg
(
host
),
if
(
is_server
==
(
res
.
opts
.
count
(
"client"
)
>
0
))
{
on_opt0
(
's'
,
"server"
,
&
desc
,
"run in server mode"
,
sopts
)
>>
set_mode
(
"server"
),
if
(
is_server
)
{
on_opt0
(
'c'
,
"client"
,
&
desc
,
"run in client mode"
,
copts
)
>>
set_mode
(
"client"
),
cerr
<<
"*** cannot be server and client at the same time"
<<
endl
;
on_opt0
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
}
else
{
);
cerr
<<
"*** either --server or --client option must be set"
<<
endl
;
if
(
!
args_valid
||
port
==
0
||
mode
.
empty
())
{
}
if
(
port
==
0
)
cerr
<<
"*** no port specified"
<<
endl
;
return
1
;
if
(
mode
.
empty
())
cerr
<<
"*** no mode specified"
<<
endl
;
}
cerr
<<
endl
;
if
(
!
is_server
&&
port
==
0
)
{
auto
description_printer
=
print_desc
(
&
desc
,
cerr
);
cerr
<<
"*** no port to server specified"
<<
endl
;
description_printer
();
return
1
;
return
-
1
;
}
}
if
(
mode
==
"server"
)
{
if
(
is_server
)
{
try
{
try
{
// try to publish math actor at given port
// try to publish math actor at given port
io
::
publish
(
spawn
(
calculator
),
port
);
cout
<<
"*** try publish at port "
<<
port
<<
endl
;
auto
p
=
io
::
publish
(
spawn
(
calculator
),
port
);
cout
<<
"*** server successfully published at port "
<<
p
<<
endl
;
}
}
catch
(
exception
&
e
)
{
catch
(
exception
&
e
)
{
cerr
<<
"*** unable to publish math actor at port "
<<
port
<<
"
\n
"
cerr
<<
"*** unable to publish math actor at port "
<<
port
<<
"
\n
"
...
@@ -226,10 +222,8 @@ int main(int argc, char** argv) {
...
@@ -226,10 +222,8 @@ int main(int argc, char** argv) {
}
}
}
}
else
{
else
{
if
(
host
.
empty
())
host
=
"localhost"
;
client_repl
(
host
,
port
);
client_repl
(
host
,
port
);
}
}
await_all_actors_done
();
await_all_actors_done
();
shutdown
();
shutdown
();
return
0
;
}
}
examples/remote_actors/group_chat.cpp
View file @
89115514
...
@@ -18,9 +18,6 @@
...
@@ -18,9 +18,6 @@
#include "caf/all.hpp"
#include "caf/all.hpp"
#include "caf/io/all.hpp"
#include "caf/io/all.hpp"
// the options_description API is deprecated
#include "cppa/opt.hpp"
using
namespace
std
;
using
namespace
std
;
using
namespace
caf
;
using
namespace
caf
;
...
@@ -80,14 +77,16 @@ void client(event_based_actor* self, const string& name) {
...
@@ -80,14 +77,16 @@ void client(event_based_actor* self, const string& name) {
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
string
name
;
string
name
;
string
group_id
;
string
group_id
;
options_description
desc
;
auto
res
=
message_builder
(
argv
+
1
,
argv
+
argc
).
filter_cli
({
bool
args_valid
=
match_stream
<
string
>
(
argv
+
1
,
argv
+
argc
)
(
{
"name,n"
,
"set name"
,
name
},
on_opt1
(
'n'
,
"name"
,
&
desc
,
"set name"
)
>>
rd_arg
(
name
),
{
"group,g"
,
"join group"
,
group_id
}
on_opt1
(
'g'
,
"group"
,
&
desc
,
"join group <arg1>"
)
>>
rd_arg
(
group_id
),
});
on_opt0
(
'h'
,
"help"
,
&
desc
,
"print help"
)
>>
print_desc_and_exit
(
&
desc
)
if
(
!
res
.
remainder
.
empty
())
{
);
std
::
cout
<<
res
.
helptext
<<
std
::
endl
;
if
(
!
args_valid
)
{
return
1
;
print_desc_and_exit
(
&
desc
)();
}
if
(
res
.
opts
.
count
(
"help"
)
>
0
)
{
return
0
;
}
}
while
(
name
.
empty
())
{
while
(
name
.
empty
())
{
cout
<<
"please enter your name: "
<<
flush
;
cout
<<
"please enter your name: "
<<
flush
;
...
...
libcaf_core/caf/message.hpp
View file @
89115514
...
@@ -20,10 +20,13 @@
...
@@ -20,10 +20,13 @@
#ifndef CAF_MESSAGE_HPP
#ifndef CAF_MESSAGE_HPP
#define CAF_MESSAGE_HPP
#define CAF_MESSAGE_HPP
#include <tuple>
#include <type_traits>
#include <type_traits>
#include "caf/atom.hpp"
#include "caf/atom.hpp"
#include "caf/config.hpp"
#include "caf/config.hpp"
#include "caf/from_string.hpp"
#include "caf/skip_message.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/int_list.hpp"
#include "caf/detail/comparable.hpp"
#include "caf/detail/comparable.hpp"
...
@@ -93,29 +96,34 @@ class message {
...
@@ -93,29 +96,34 @@ class message {
}
}
/**
/**
* Creates a new
tupl
e with all but the first n values.
* Creates a new
messag
e with all but the first n values.
*/
*/
message
drop
(
size_t
n
)
const
;
message
drop
(
size_t
n
)
const
;
/**
/**
* Creates a new
tupl
e with all but the last n values.
* Creates a new
messag
e with all but the last n values.
*/
*/
message
drop_right
(
size_t
n
)
const
;
message
drop_right
(
size_t
n
)
const
;
/**
/**
* Creates a new
tupl
e from the first n values.
* Creates a new
messag
e from the first n values.
*/
*/
inline
message
take
(
size_t
n
)
const
{
inline
message
take
(
size_t
n
)
const
{
return
n
>=
size
()
?
*
this
:
drop_right
(
size
()
-
n
);
return
n
>=
size
()
?
*
this
:
drop_right
(
size
()
-
n
);
}
}
/**
/**
* Creates a new
tupl
e from the last n values.
* Creates a new
messag
e from the last n values.
*/
*/
inline
message
take_right
(
size_t
n
)
const
{
inline
message
take_right
(
size_t
n
)
const
{
return
n
>=
size
()
?
*
this
:
drop
(
size
()
-
n
);
return
n
>=
size
()
?
*
this
:
drop
(
size
()
-
n
);
}
}
/**
* Creates a new message of size `n` starting at element `pos`.
*/
message
slice
(
size_t
pos
,
size_t
n
)
const
;
/**
/**
* Gets a mutable pointer to the element at position @p p.
* Gets a mutable pointer to the element at position @p p.
*/
*/
...
@@ -199,21 +207,91 @@ class message {
...
@@ -199,21 +207,91 @@ class message {
}
}
/**
/**
* Checks whether this
tupl
e is dynamically typed, i.e.,
* Checks whether this
messag
e is dynamically typed, i.e.,
* its types were not known at compile time.
* its types were not known at compile time.
*/
*/
bool
dynamically_typed
()
const
;
bool
dynamically_typed
()
const
;
/**
/**
* Applies
@p handler
to this message and returns the result
* Applies
`handler`
to this message and returns the result
* of `handler(*this)`.
* of `handler(*this)`.
*/
*/
optional
<
message
>
apply
(
message_handler
handler
);
optional
<
message
>
apply
(
message_handler
handler
);
/**
* Returns a new message consisting of all elements that were *not*
* matched by `handler`.
*/
message
filter
(
message_handler
handler
)
const
;
/**
* Stores the name of a command line option ("<long name>[,<short name>]")
* along with a description and a callback.
*/
struct
cli_arg
{
std
::
string
name
;
std
::
string
text
;
std
::
function
<
bool
(
const
std
::
string
&
)
>
fun
;
inline
cli_arg
(
std
::
string
nstr
,
std
::
string
tstr
)
:
name
(
std
::
move
(
nstr
)),
text
(
std
::
move
(
tstr
))
{
// nop
}
inline
cli_arg
(
std
::
string
nstr
,
std
::
string
tstr
,
std
::
string
&
arg
)
:
name
(
std
::
move
(
nstr
)),
text
(
std
::
move
(
tstr
))
{
fun
=
[
&
arg
](
const
std
::
string
&
str
)
->
bool
{
arg
=
str
;
return
true
;
};
}
inline
cli_arg
(
std
::
string
nstr
,
std
::
string
tstr
,
std
::
vector
<
std
::
string
>&
arg
)
:
name
(
std
::
move
(
nstr
)),
text
(
std
::
move
(
tstr
))
{
fun
=
[
&
arg
](
const
std
::
string
&
str
)
->
bool
{
arg
.
push_back
(
str
);
return
true
;
};
}
template
<
class
T
>
cli_arg
(
std
::
string
nstr
,
std
::
string
tstr
,
T
&
arg
)
:
name
(
std
::
move
(
nstr
)),
text
(
std
::
move
(
tstr
))
{
fun
=
[
&
arg
](
const
std
::
string
&
str
)
->
bool
{
auto
res
=
from_string
<
T
>
(
str
);
if
(
!
res
)
{
return
false
;
}
arg
=
*
res
;
return
true
;
};
}
template
<
class
T
>
cli_arg
(
std
::
string
nstr
,
std
::
string
tstr
,
std
::
vector
<
T
>&
arg
)
:
name
(
std
::
move
(
nstr
)),
text
(
std
::
move
(
tstr
))
{
fun
=
[
&
arg
](
const
std
::
string
&
str
)
->
bool
{
auto
res
=
from_string
<
T
>
(
str
);
if
(
!
res
)
{
return
false
;
}
arg
.
push_back
(
*
res
);
return
true
;
};
}
};
struct
cli_res
;
/**
* A simplistic interface for using `filter` to parse command line options.
*/
cli_res
filter_cli
(
std
::
vector
<
cli_arg
>
args
)
const
;
/** @cond PRIVATE */
/** @cond PRIVATE */
inline
uint32_t
type_token
()
const
{
inline
uint32_t
type_token
()
const
{
return
m_vals
->
type_token
()
;
return
m_vals
?
m_vals
->
type_token
()
:
0xFFFFFFFF
;
}
}
inline
void
force_detach
()
{
inline
void
force_detach
()
{
...
@@ -224,7 +302,7 @@ class message {
...
@@ -224,7 +302,7 @@ class message {
explicit
message
(
raw_ptr
);
explicit
message
(
raw_ptr
);
inline
const
std
::
string
*
tuple_type_names
()
const
{
inline
std
::
string
tuple_type_names
()
const
{
return
m_vals
->
tuple_type_names
();
return
m_vals
->
tuple_type_names
();
}
}
...
@@ -246,9 +324,26 @@ class message {
...
@@ -246,9 +324,26 @@ class message {
/** @endcond */
/** @endcond */
private:
private:
message
filter_impl
(
size_t
start
,
message_handler
handler
)
const
;
data_ptr
m_vals
;
data_ptr
m_vals
;
};
/**
* Stores the result of `message::filter_cli`.
*/
struct
message
::
cli_res
{
/**
* Stores the remaining (unmatched) arguments.
*/
message
remainder
;
/**
* Stores the names of all active options.
*/
std
::
set
<
std
::
string
>
opts
;
/**
* Stores the automatically generated help text.
*/
std
::
string
helptext
;
};
};
/**
/**
...
...
libcaf_core/caf/message_builder.hpp
View file @
89115514
...
@@ -90,6 +90,14 @@ class message_builder {
...
@@ -90,6 +90,14 @@ class message_builder {
*/
*/
message
to_message
();
message
to_message
();
inline
message
filter
(
message_handler
f
)
{
return
to_message
().
filter
(
f
);
}
inline
message
::
cli_res
filter_cli
(
std
::
vector
<
message
::
cli_arg
>
args
)
{
return
to_message
().
filter_cli
(
std
::
move
(
args
));
}
/**
/**
* Convenience function for `to_message().apply(handler).
* Convenience function for `to_message().apply(handler).
*/
*/
...
...
libcaf_core/src/message.cpp
View file @
89115514
...
@@ -18,7 +18,11 @@
...
@@ -18,7 +18,11 @@
******************************************************************************/
******************************************************************************/
#include "caf/message.hpp"
#include "caf/message.hpp"
#include <iostream>
#include "caf/message_handler.hpp"
#include "caf/message_handler.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/detail/singletons.hpp"
#include "caf/detail/singletons.hpp"
#include "caf/detail/decorated_tuple.hpp"
#include "caf/detail/decorated_tuple.hpp"
...
@@ -90,8 +94,17 @@ message message::drop_right(size_t n) const {
...
@@ -90,8 +94,17 @@ message message::drop_right(size_t n) const {
return
message
{};
return
message
{};
}
}
std
::
vector
<
size_t
>
mapping
(
size
()
-
n
);
std
::
vector
<
size_t
>
mapping
(
size
()
-
n
);
size_t
i
=
0
;
std
::
iota
(
mapping
.
begin
(),
mapping
.
end
(),
size_t
{
0
});
std
::
generate
(
mapping
.
begin
(),
mapping
.
end
(),
[
&
]
{
return
i
++
;
});
return
message
{
detail
::
decorated_tuple
::
create
(
m_vals
,
std
::
move
(
mapping
))};
}
message
message
::
slice
(
size_t
pos
,
size_t
n
)
const
{
auto
s
=
size
();
if
(
pos
>=
s
)
{
return
message
{};
}
std
::
vector
<
size_t
>
mapping
(
std
::
min
(
s
-
pos
,
n
));
std
::
iota
(
mapping
.
begin
(),
mapping
.
end
(),
pos
);
return
message
{
detail
::
decorated_tuple
::
create
(
m_vals
,
std
::
move
(
mapping
))};
return
message
{
detail
::
decorated_tuple
::
create
(
m_vals
,
std
::
move
(
mapping
))};
}
}
...
@@ -103,11 +116,160 @@ message::const_iterator message::begin() const {
...
@@ -103,11 +116,160 @@ message::const_iterator message::begin() const {
return
m_vals
?
m_vals
->
begin
()
:
const_iterator
{
nullptr
,
0
};
return
m_vals
?
m_vals
->
begin
()
:
const_iterator
{
nullptr
,
0
};
}
}
/**
* Returns an iterator to the end.
*/
message
::
const_iterator
message
::
end
()
const
{
message
::
const_iterator
message
::
end
()
const
{
return
m_vals
?
m_vals
->
end
()
:
const_iterator
{
nullptr
,
0
};
return
m_vals
?
m_vals
->
end
()
:
const_iterator
{
nullptr
,
0
};
}
}
message
message
::
filter_impl
(
size_t
start
,
message_handler
handler
)
const
{
auto
s
=
size
();
for
(
size_t
i
=
start
;
i
<
s
;
++
i
)
{
for
(
size_t
n
=
(
s
-
i
)
;
n
>
0
;
--
n
)
{
auto
res
=
handler
(
slice
(
i
,
n
));
if
(
res
)
{
std
::
vector
<
size_t
>
mapping
(
s
);
std
::
iota
(
mapping
.
begin
(),
mapping
.
end
(),
size_t
{
0
});
auto
first
=
mapping
.
begin
()
+
static_cast
<
ptrdiff_t
>
(
i
);
auto
last
=
first
+
static_cast
<
ptrdiff_t
>
(
n
);
mapping
.
erase
(
first
,
last
);
if
(
mapping
.
empty
())
{
return
message
{};
}
message
next
{
detail
::
decorated_tuple
::
create
(
m_vals
,
std
::
move
(
mapping
))};
return
next
.
filter_impl
(
i
,
handler
);
}
}
}
return
*
this
;
}
message
message
::
filter
(
message_handler
handler
)
const
{
return
filter_impl
(
0
,
handler
);
}
message
::
cli_res
message
::
filter_cli
(
std
::
vector
<
cli_arg
>
cliargs
)
const
{
std
::
set
<
std
::
string
>
opts
;
cli_arg
dummy
{
"help,h"
,
""
};
std
::
map
<
std
::
string
,
cli_arg
*>
shorts
;
std
::
map
<
std
::
string
,
cli_arg
*>
longs
;
shorts
[
"-h"
]
=
&
dummy
;
shorts
[
"-?"
]
=
&
dummy
;
longs
[
"--help"
]
=
&
dummy
;
for
(
auto
&
cliarg
:
cliargs
)
{
std
::
vector
<
std
::
string
>
s
;
split
(
s
,
cliarg
.
name
,
is_any_of
(
","
),
token_compress_on
);
if
(
s
.
size
()
==
2
&&
s
.
back
().
size
()
==
1
)
{
longs
[
"--"
+
s
.
front
()]
=
&
cliarg
;
shorts
[
"-"
+
s
.
back
()]
=
&
cliarg
;
}
else
if
(
s
.
size
()
==
1
)
{
longs
[
s
.
front
()]
=
&
cliarg
;
}
else
{
throw
std
::
invalid_argument
(
"invalid option name: "
+
cliarg
.
name
);
}
}
auto
insert_opt_name
=
[
&
](
const
cli_arg
*
ptr
)
{
auto
separator
=
ptr
->
name
.
find
(
','
);
if
(
separator
==
std
::
string
::
npos
)
{
opts
.
insert
(
ptr
->
name
);
}
else
{
opts
.
insert
(
ptr
->
name
.
substr
(
0
,
separator
));
}
};
auto
res
=
filter
({
[
&
](
const
std
::
string
&
arg
)
->
optional
<
skip_message_t
>
{
if
(
arg
.
empty
()
||
arg
.
front
()
!=
'-'
)
{
return
skip_message
();
}
auto
i
=
shorts
.
find
(
arg
);
if
(
i
!=
shorts
.
end
())
{
if
(
i
->
second
->
fun
)
{
return
skip_message
();
}
insert_opt_name
(
i
->
second
);
return
none
;
}
auto
eq_pos
=
arg
.
find
(
'='
);
auto
j
=
longs
.
find
(
arg
.
substr
(
0
,
eq_pos
));
if
(
j
!=
longs
.
end
())
{
if
(
j
->
second
->
fun
)
{
if
(
eq_pos
==
std
::
string
::
npos
)
{
std
::
cerr
<<
"missing argument to "
<<
arg
<<
std
::
endl
;
return
none
;
}
if
(
!
j
->
second
->
fun
(
arg
.
substr
(
eq_pos
+
1
)))
{
std
::
cerr
<<
"invalid value for option "
<<
j
->
second
->
name
<<
": "
<<
arg
<<
std
::
endl
;
return
none
;
}
insert_opt_name
(
j
->
second
);
return
none
;
}
insert_opt_name
(
j
->
second
);
return
none
;
}
std
::
cerr
<<
"unknown command line option: "
<<
arg
<<
std
::
endl
;
return
none
;
},
[
&
](
const
std
::
string
&
arg1
,
const
std
::
string
&
arg2
)
->
optional
<
skip_message_t
>
{
if
(
arg1
.
size
()
<
2
||
arg1
[
0
]
!=
'-'
||
arg1
[
1
]
==
'-'
)
{
return
skip_message
();
}
auto
i
=
shorts
.
find
(
arg1
);
if
(
i
!=
shorts
.
end
()
&&
i
->
second
->
fun
)
{
if
(
!
i
->
second
->
fun
(
arg2
))
{
std
::
cerr
<<
"invalid value for option "
<<
i
->
second
->
name
<<
": "
<<
arg2
<<
std
::
endl
;
return
none
;
}
insert_opt_name
(
i
->
second
);
return
none
;
}
std
::
cerr
<<
"unknown command line option: "
<<
arg1
<<
std
::
endl
;
return
none
;
}
});
size_t
name_width
=
0
;
for
(
auto
&
ca
:
cliargs
)
{
// name field contains either only "--<long_name>" or
// "-<short name> [--<long name>]" depending on whether or not
// a ',' appears in the name
auto
nw
=
ca
.
name
.
find
(
','
)
==
std
::
string
::
npos
?
ca
.
name
.
size
()
+
2
// "--<name>"
:
ca
.
name
.
size
()
+
5
;
// "-X [--<name>]" (minus trailing ",X")
if
(
ca
.
fun
)
{
nw
+=
4
;
// trailing " arg"
}
name_width
=
std
::
max
(
name_width
,
nw
);
}
std
::
ostringstream
oss
;
oss
<<
std
::
left
;
oss
<<
"Allowed options:"
<<
std
::
endl
;
for
(
auto
&
ca
:
cliargs
)
{
std
::
string
lhs
;
auto
separator
=
ca
.
name
.
find
(
','
);
if
(
separator
==
std
::
string
::
npos
)
{
lhs
+=
"--"
;
lhs
+=
ca
.
name
;
}
else
{
lhs
+=
"-"
;
lhs
+=
ca
.
name
.
back
();
lhs
+=
" [--"
;
lhs
+=
ca
.
name
.
substr
(
0
,
separator
);
lhs
+=
"]"
;
}
if
(
ca
.
fun
)
{
lhs
+=
" arg"
;
}
oss
<<
" "
;
oss
.
width
(
static_cast
<
std
::
streamsize
>
(
name_width
));
oss
<<
lhs
<<
" : "
<<
ca
.
text
<<
std
::
endl
;
}
auto
helptext
=
oss
.
str
();
if
(
opts
.
count
(
"help"
)
==
1
)
{
std
::
cout
<<
helptext
<<
std
::
endl
;
}
return
{
res
,
std
::
move
(
opts
),
std
::
move
(
helptext
)};
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/message_builder.cpp
View file @
89115514
...
@@ -90,10 +90,6 @@ class message_builder::dynamic_msg_data : public detail::message_data {
...
@@ -90,10 +90,6 @@ class message_builder::dynamic_msg_data : public detail::message_data {
return
m_type_token
;
return
m_type_token
;
}
}
const
std
::
string
*
tuple_type_names
()
const
override
{
return
nullptr
;
// get_tuple_type_names(*this);
}
std
::
vector
<
uniform_value
>
m_elements
;
std
::
vector
<
uniform_value
>
m_elements
;
uint32_t
m_type_token
;
uint32_t
m_type_token
;
};
};
...
...
unit_testing/CMakeLists.txt
View file @
89115514
...
@@ -21,6 +21,7 @@ add_unit_test(atom)
...
@@ -21,6 +21,7 @@ add_unit_test(atom)
add_unit_test
(
metaprogramming
)
add_unit_test
(
metaprogramming
)
add_unit_test
(
intrusive_containers
)
add_unit_test
(
intrusive_containers
)
add_unit_test
(
match
)
add_unit_test
(
match
)
add_unit_test
(
message
)
add_unit_test
(
serialization
)
add_unit_test
(
serialization
)
add_unit_test
(
uniform_type
)
add_unit_test
(
uniform_type
)
add_unit_test
(
fixed_vector
)
add_unit_test
(
fixed_vector
)
...
...
unit_testing/test_message.cpp
0 → 100644
View file @
89115514
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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. *
******************************************************************************/
#include "test.hpp"
#include "caf/message.hpp"
using
std
::
cout
;
using
std
::
endl
;
using
namespace
caf
;
void
test_drop
()
{
auto
m1
=
make_message
(
1
,
2
,
3
,
4
,
5
);
std
::
vector
<
message
>
messages
{
m1
,
make_message
(
2
,
3
,
4
,
5
),
make_message
(
3
,
4
,
5
),
make_message
(
4
,
5
),
make_message
(
5
),
message
{}
};
for
(
size_t
i
=
0
;
i
<
messages
.
size
();
++
i
)
{
CAF_CHECK_EQUAL
(
to_string
(
m1
.
drop
(
i
)),
to_string
(
messages
[
i
]));
}
}
void
test_slice
()
{
auto
m1
=
make_message
(
1
,
2
,
3
,
4
,
5
);
auto
m2
=
m1
.
slice
(
2
,
2
);
CAF_CHECK_EQUAL
(
to_string
(
m2
),
to_string
(
make_message
(
3
,
4
)));
}
void
test_filter1
(
int
lhs1
,
int
lhs2
,
int
lhs3
,
int
rhs1
,
int
rhs2
,
int
val
)
{
auto
m1
=
make_message
(
lhs1
,
lhs2
,
lhs3
);
auto
m2
=
make_message
(
rhs1
,
rhs2
);
auto
m3
=
m1
.
filter
(
on
(
val
)
>>
[]
{});
CAF_CHECK_EQUAL
(
to_string
(
m2
),
to_string
(
m3
));
}
void
test_filter2
()
{
auto
m1
=
make_message
(
1.0
,
2.0
,
3.0
);
auto
m2
=
make_message
(
1
,
2
,
1.0
,
2.0
,
3.0
);
auto
m3
=
make_message
(
1.0
,
1
,
2
,
2.0
,
3.0
);
auto
m4
=
make_message
(
1.0
,
2.0
,
1
,
2
,
3.0
);
auto
m5
=
make_message
(
1.0
,
2.0
,
3.0
,
1
,
2
);
auto
m6
=
make_message
(
1
,
2
,
1.0
,
2.0
,
3.0
,
1
,
2
);
auto
m7
=
make_message
(
1.0
,
1
,
2
,
3
,
4
,
2.0
,
3.0
);
message_handler
f
{
[](
int
,
int
)
{
},
[](
float
,
float
)
{
}
};
CAF_CHECK_EQUAL
(
to_string
(
m2
.
filter
(
f
)),
to_string
(
m1
));
CAF_CHECK_EQUAL
(
to_string
(
m3
.
filter
(
f
)),
to_string
(
m1
));
CAF_CHECK_EQUAL
(
to_string
(
m4
.
filter
(
f
)),
to_string
(
m1
));
CAF_CHECK_EQUAL
(
to_string
(
m5
.
filter
(
f
)),
to_string
(
m1
));
CAF_CHECK_EQUAL
(
to_string
(
m6
.
filter
(
f
)),
to_string
(
m1
));
CAF_CHECK_EQUAL
(
to_string
(
m7
.
filter
(
f
)),
to_string
(
m1
));
}
void
test_filter3
()
{
auto
m1
=
make_message
(
1
);
CAF_CHECK_EQUAL
(
to_string
(
m1
.
filter
([](
int
)
{})),
to_string
(
message
{}));
auto
m2
=
make_message
(
1.0
,
2
,
3
,
4.0
);
auto
m3
=
m2
.
filter
({
[](
int
,
int
)
{
},
[](
double
,
double
)
{
}
});
// check for false positives through collapsing
CAF_CHECK_EQUAL
(
to_string
(
m3
),
to_string
(
make_message
(
1.0
,
4.0
)));
}
void
test_filter_cli
()
{
auto
f
=
[](
std
::
vector
<
std
::
string
>
args
)
{
std
::
string
filename
;
auto
res
=
message_builder
(
args
.
begin
(),
args
.
end
()).
filter_cli
({
{
"version,v"
,
"print version"
},
{
"file,f"
,
"set output file"
,
filename
},
{
"whatever"
,
"do whatever"
}
});
CAF_CHECK_EQUAL
(
res
.
opts
.
count
(
"file"
),
1
);
CAF_CHECK_EQUAL
(
to_string
(
res
.
remainder
),
to_string
(
message
{}));
CAF_CHECK_EQUAL
(
filename
,
"hello.txt"
);
};
f
({
"--file=hello.txt"
});
f
({
"-f"
,
"hello.txt"
});
}
void
test_type_token
()
{
auto
m1
=
make_message
(
get_atom
::
value
);
CAF_CHECK_EQUAL
(
m1
.
type_token
(),
detail
::
make_type_token
<
get_atom
>
());
}
int
main
()
{
CAF_TEST
(
message
);
test_drop
();
test_slice
();
test_filter1
(
1
,
2
,
3
,
2
,
3
,
1
);
test_filter1
(
1
,
2
,
3
,
1
,
3
,
2
);
test_filter1
(
1
,
2
,
3
,
1
,
2
,
3
);
test_filter2
();
test_filter3
();
test_filter_cli
();
test_type_token
();
return
CAF_TEST_RESULT
();
}
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