Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[15212] hotfix of BasicConfigurationExample cli #2951

Merged
merged 8 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ bool HelloWorldPublisher::init(
if (transient)
{
wqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
wqos.reliability().kind = RELIABLE_RELIABILITY_QOS;
wqos.history().kind = KEEP_ALL_HISTORY_QOS; // store previously sent samples so they can be resent to newly
// matched DataReaders
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ bool HelloWorldSubscriber::init(
if (reliable)
{
rqos.reliability().kind = RELIABLE_RELIABILITY_QOS;
// mimic publisher behaviour. Assure the user see all samples are received
rqos.history().kind = KEEP_ALL_HISTORY_QOS;
}
else
{
Expand All @@ -182,6 +184,9 @@ bool HelloWorldSubscriber::init(
if (transient)
{
rqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
// mimic publisher behaviour. Assure the user see all samples are received
rqos.reliability().kind = RELIABLE_RELIABILITY_QOS;
rqos.history().kind = KEEP_ALL_HISTORY_QOS;
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ int main(

const char* type_name = parse.nonOption(0);

// make sure is the first option
if (parse.optionsCount() && type_name >= buffer[0].arg)
// make sure is the first option.
// type_name and buffer[0].name reference the original command line char array
// type_name must precede any other arguments in the array.
// Note buffer[0].arg may be null for non-valued options and is not reliable for
// testing purposes.
if (parse.optionsCount() && type_name >= buffer[0].name)
{
throw 1;
}
Expand Down
56 changes: 44 additions & 12 deletions examples/cpp/dds/BasicConfigurationExample/arg_configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#define _EPROSIMA_FASTDDS_EXAMPLES_CPP_DDS_BASICCONFIGURATIONEXAMPLE_ARG_CONFIGURATION_H_

#include <iostream>
#include <limits>
#include <sstream>
#include <string>

#include <optionparser.hpp>
Expand Down Expand Up @@ -71,18 +73,48 @@ struct Arg : public option::Arg
bool msg)
{
char* endptr = 0;
if (option.arg != 0 && strtol(option.arg, &endptr, 10))
if ( option.arg != nullptr)
{
strtol(option.arg, &endptr, 10);
if (endptr != option.arg && *endptr == 0)
{
return option::ARG_OK;
}
}
if (endptr != option.arg && *endptr == 0)

if (msg)
{
return option::ARG_OK;
print_error("Option '", option, "' requires a numeric argument\n");
}
return option::ARG_ILLEGAL;
}

template<long min = 0, long max = std::numeric_limits<long>::max()>
static option::ArgStatus NumericRange(
const option::Option& option,
bool msg)
{
static_assert(min <= max, "NumericRange: invalid range provided.");

char* endptr = 0;
if ( option.arg != nullptr )
{
long value = strtol(option.arg, &endptr, 10);
if ( endptr != option.arg && *endptr == 0 &&
value >= min && value <= max)
{
return option::ARG_OK;
}
}

if (msg)
{
print_error("Option '", option, "' requires a numeric argument\n");
std::ostringstream os;
os << "' requires a numeric argument in range ["
<< min << ", " << max << "]" << std::endl;
print_error("Option '", option, os.str().c_str());
}

return option::ARG_ILLEGAL;
}

Expand Down Expand Up @@ -151,14 +183,14 @@ const option::Descriptor usage[] = {
{ UNKNOWN_OPT, 0, "", "", Arg::None, "\nPublisher options:"},
{ TOPIC, 0, "t", "topic", Arg::String,
" -t <topic_name> \t--topic=<topic_name> \tTopic name (Default: HelloWorldTopic)." },
{ DOMAIN_ID, 0, "d", "domain", Arg::Numeric,
{ DOMAIN_ID, 0, "d", "domain", Arg::NumericRange<0, 230>,
" -d <id> \t--domain=<id> \tDDS domain ID (Default: 0)." },
{ WAIT, 0, "w", "wait", Arg::Numeric,
{ WAIT, 0, "w", "wait", Arg::NumericRange<0, 100>,
" -w <num> \t--wait=<num> \tNumber of matched subscribers required to publish"
" (Default: 0 => does not wait)." },
{ SAMPLES, 0, "s", "samples", Arg::Numeric,
{ SAMPLES, 0, "s", "samples", Arg::NumericRange<>,
" -s <num> \t--samples=<num> \tNumber of samples to send (Default: 0 => infinite samples)." },
{ INTERVAL, 0, "i", "interval", Arg::Numeric,
{ INTERVAL, 0, "i", "interval", Arg::NumericRange<>,
" -i <num> \t--interval=<num> \tTime between samples in milliseconds (Default: 100)." },
{ ASYNC, 0, "a", "async", Arg::None,
" -a \t--async \tAsynchronous publish mode (synchronous by default)." },
Expand All @@ -170,10 +202,10 @@ const option::Descriptor usage[] = {
{ UNKNOWN_OPT, 0, "", "", Arg::None, "\nSubscriber options:"},
{ TOPIC, 0, "t", "topic", Arg::String,
" -t <topic_name> \t--topic=<topic_name> \tTopic name (Default: HelloWorldTopic)." },
{ DOMAIN_ID, 0, "d", "domain", Arg::Numeric,
{ DOMAIN_ID, 0, "d", "domain", Arg::NumericRange<0, 230>,
" -d <id> \t--domain=<id> \tDDS domain ID (Default: 0)." },
{ SAMPLES, 0, "s", "samples", Arg::Numeric,
" -s <num> \t--samples=<num> \tNumber of samples to wait for (Default: 0 => infinite samples)." },
{ SAMPLES, 0, "s", "samples", Arg::NumericRange<>,
" -s <num> \t--samples=<num> \tNumber of samples to send (Default: 0 => infinite samples)." },
{ TRANSPORT, 0, "", "transport", Arg::Transport,
" \t--transport=<shm|udp|udpv6> \tUse only shared-memory, UDPv4, or UDPv6 transport."
"If not set, use Fast DDS default transports (depending on the scenario it will use the most efficient one:"
Expand All @@ -186,7 +218,7 @@ const option::Descriptor usage[] = {
" \t--transient \tSet durability to transient local (volatile by default, ineffective when not reliable)." },

{ UNKNOWN_OPT, 0, "", "", Arg::None, "\nDiscovery options:"},
{ TTL, 0, "", "ttl", Arg::Numeric,
{ TTL, 0, "", "ttl", Arg::NumericRange<1, 255>,
"\t--ttl \tSet multicast discovery Time To Live on IPv4 or Hop Limit for IPv6."
" If not set, uses Fast-DDS default (1 hop). Increase it to avoid discovery issues"
" on scenarios with several routers. Maximum: 255."},
Expand Down
99 changes: 75 additions & 24 deletions examples/cpp/dds/HelloWorldExample/HelloWorld_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*
*/

#include <limits>
#include <sstream>

#include "HelloWorldPublisher.h"
#include "HelloWorldSubscriber.h"

Expand Down Expand Up @@ -73,18 +76,48 @@ struct Arg : public option::Arg
bool msg)
{
char* endptr = 0;
if (option.arg != 0 && strtol(option.arg, &endptr, 10))
if ( option.arg != nullptr)
{
strtol(option.arg, &endptr, 10);
if (endptr != option.arg && *endptr == 0)
{
return option::ARG_OK;
}
}
if (endptr != option.arg && *endptr == 0)

if (msg)
{
return option::ARG_OK;
print_error("Option '", option, "' requires a numeric argument\n");
}
return option::ARG_ILLEGAL;
}

template<long min = 0, long max = std::numeric_limits<long>::max()>
static option::ArgStatus NumericRange(
const option::Option& option,
bool msg)
{
static_assert(min <= max, "NumericRange: invalid range provided.");

char* endptr = 0;
if ( option.arg != nullptr )
{
long value = strtol(option.arg, &endptr, 10);
if ( endptr != option.arg && *endptr == 0 &&
value >= min && value <= max)
{
return option::ARG_OK;
}
}

if (msg)
{
print_error("Option '", option, "' requires a numeric argument\n");
std::ostringstream os;
os << "' requires a numeric argument in range ["
<< min << ", " << max << "]" << std::endl;
print_error("Option '", option, os.str().c_str());
}

return option::ARG_ILLEGAL;
}

Expand Down Expand Up @@ -119,9 +152,9 @@ const option::Descriptor usage[] = {
"Usage: HelloWorldExample <publisher|subscriber>\n\nGeneral options:" },
{ HELP, 0, "h", "help", Arg::None, " -h \t--help \tProduce help message." },
{ UNKNOWN_OPT, 0, "", "", Arg::None, "\nPublisher options:"},
{ SAMPLES, 0, "s", "samples", Arg::Numeric,
{ SAMPLES, 0, "s", "samples", Arg::NumericRange<>,
" -s <num>, \t--samples=<num> \tNumber of samples (0, default, infinite)." },
{ INTERVAL, 0, "i", "interval", Arg::Numeric,
{ INTERVAL, 0, "i", "interval", Arg::NumericRange<>,
" -i <num>, \t--interval=<num> \tTime between samples in milliseconds (Default: 100)." },
{ ENVIRONMENT, 0, "e", "env", Arg::None, " -e \t--env \tLoad QoS from environment." },
{ 0, 0, 0, 0, 0, 0 }
Expand Down Expand Up @@ -163,28 +196,37 @@ int main(
std::vector<option::Option> buffer(stats.buffer_max);
option::Parser parse(true, usage, argc, argv, &options[0], &buffer[0]);

if (parse.error())
try
{
return 1;
}
if (parse.error())
{
throw 1;
}

if (options[HELP] || options[UNKNOWN_OPT])
{
option::printUsage(fwrite, stdout, usage, columns);
return 0;
}
if (options[HELP] || options[UNKNOWN_OPT])
{
throw 1;
}

// For backward compatibility count and sleep may be given positionally
if (parse.nonOptionsCount() > 3 || parse.nonOptionsCount() == 0)
{
option::printUsage(fwrite, stdout, usage, columns);
return 1;
}
// For backward compatibility count and sleep may be given positionally
if (parse.nonOptionsCount() > 3 || parse.nonOptionsCount() == 0)
{
throw 2;
}

// Decide between publisher or subscriber
{
// Decide between publisher or subscriber
const char* type_name = parse.nonOption(0);

// make sure is the first option.
// type_name and buffer[0].name reference the original command line char array
// type_name must precede any other arguments in the array.
// Note buffer[0].arg may be null for non-valued options and is not reliable for
// testing purposes.
if (parse.optionsCount() && type_name >= buffer[0].name)
{
throw 2;
}

if (strcmp(type_name, "publisher") == 0)
{
type = 1;
Expand All @@ -195,10 +237,19 @@ int main(
}
else
{
option::printUsage(fwrite, stdout, usage, columns);
return 1;
throw 2;
}
}
catch (int error)
{
if ( error == 2 )
{
std::cerr << "ERROR: first argument must be <publisher|subscriber> followed by - or -- options"
<< std::endl;
}
option::printUsage(fwrite, stdout, usage, columns);
return error;
}

// Decide between the old and new syntax
if (parse.nonOptionsCount() > 1)
Expand Down