// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCL__ARGUMENTS_H_
#define RCL__ARGUMENTS_H_
#include "rcl/allocator.h"
#include "rcl/macros.h"
#include "rcl/types.h"
#include "rcl/visibility_control.h"
#include "rcl_yaml_param_parser/types.h"
#ifdef __cplusplus
extern "C"
{
#endif
struct rcl_arguments_impl_t;
/// Hold output of parsing command line arguments.
typedef struct rcl_arguments_t
{
/// Private implementation pointer.
struct rcl_arguments_impl_t * impl;
} rcl_arguments_t;
#define RCL_ROS_ARGS_FLAG "--ros-args"
#define RCL_ROS_ARGS_EXPLICIT_END_TOKEN "--"
#define RCL_PARAM_FLAG "--param"
#define RCL_SHORT_PARAM_FLAG "-p"
#define RCL_PARAM_FILE_FLAG "--params-file"
#define RCL_REMAP_FLAG "--remap"
#define RCL_SHORT_REMAP_FLAG "-r"
#define RCL_ENCLAVE_FLAG "--enclave"
#define RCL_SHORT_ENCLAVE_FLAG "-e"
#define RCL_LOG_LEVEL_FLAG "--log-level"
#define RCL_EXTERNAL_LOG_CONFIG_FLAG "--log-config-file"
// To be prefixed with --enable- or --disable-
#define RCL_LOG_STDOUT_FLAG_SUFFIX "stdout-logs"
#define RCL_LOG_ROSOUT_FLAG_SUFFIX "rosout-logs"
#define RCL_LOG_EXT_LIB_FLAG_SUFFIX "external-lib-logs"
/// Return a rcl_arguments_t struct with members initialized to `NULL`.
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_arguments_t
rcl_get_zero_initialized_arguments(void);
/// Parse command line arguments into a structure usable by code.
/**
* \sa rcl_get_zero_initialized_arguments()
*
* ROS arguments are expected to be scoped by a leading `--ros-args` flag and a trailing double
* dash token `--` which may be elided if no non-ROS arguments follow after the last `--ros-args`.
*
* Remap rule parsing is supported via `-r/--remap` flags e.g. `--remap from:=to` or `-r from:=to`.
* Successfully parsed remap rules are stored in the order they were given in `argv`.
* If given arguments `{"__ns:=/foo", "__ns:=/bar"}` then the namespace used by nodes in this
* process will be `/foo` and not `/bar`.
*
* \sa rcl_remap_topic_name()
* \sa rcl_remap_service_name()
* \sa rcl_remap_node_name()
* \sa rcl_remap_node_namespace()
*
* Parameter override rule parsing is supported via `-p/--param` flags e.g. `--param name:=value`
* or `-p name:=value`.
*
* The default log level will be parsed as `--log-level level`, where `level` is a name
* representing one of the log levels in the `RCUTILS_LOG_SEVERITY` enum, e.g. `info`, `debug`,
* `warn`, not case sensitive.
* If multiple of these rules are found, the last one parsed will be used.
*
* If an argument does not appear to be a valid ROS argument e.g. a `-r/--remap` flag followed by
* anything but a valid remap rule, parsing will fail immediately.
*
* If an argument does not appear to be a known ROS argument, then it is skipped and left unparsed.
*
* \sa rcl_arguments_get_count_unparsed_ros()
* \sa rcl_arguments_get_unparsed_ros()
*
* All arguments found outside a `--ros-args ... --` scope are skipped and left unparsed.
*
* \sa rcl_arguments_get_count_unparsed()
* \sa rcl_arguments_get_unparsed()
*
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] argc The number of arguments in argv.
* \param[in] argv The values of the arguments.
* \param[in] allocator A valid allocator.
* \param[out] args_output A structure that will contain the result of parsing.
* Must be zero initialized before use.
* \return `RCL_RET_OK` if the arguments were parsed successfully, or
* \return `RCL_RET_INVALID_ROS_ARGS` if an invalid ROS argument is found, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_parse_arguments(
int argc,
const char * const argv[],
rcl_allocator_t allocator,
rcl_arguments_t * args_output);
/// Return the number of arguments that were not ROS specific arguments.
/**
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | No
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args An arguments structure that has been parsed.
* \return number of unparsed arguments, or
* \return -1 if args is `NULL` or zero initialized.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
int
rcl_arguments_get_count_unparsed(
const rcl_arguments_t * args);
/// Return a list of indices to non ROS specific arguments.
/**
* Non ROS specific arguments may have been provided i.e. arguments outside a '--ros-args' scope.
* This function populates an array of indices to these arguments in the original argv array.
* Since the first argument is always assumed to be a process name, the list will always contain
* the index 0.
*
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args An arguments structure that has been parsed.
* \param[in] allocator A valid allocator.
* \param[out] output_unparsed_indices An allocated array of indices into the original argv array.
* This array must be deallocated by the caller using the given allocator.
* If there are no unparsed args then the output will be set to NULL.
* \return `RCL_RET_OK` if everything goes correctly, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_get_unparsed(
const rcl_arguments_t * args,
rcl_allocator_t allocator,
int ** output_unparsed_indices);
/// Return the number of ROS specific arguments that were not successfully parsed.
/**
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | No
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args An arguments structure that has been parsed.
* \return number of unparsed ROS specific arguments, or
* \return -1 if args is `NULL` or zero initialized.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
int
rcl_arguments_get_count_unparsed_ros(
const rcl_arguments_t * args);
/// Return a list of indices to unknown ROS specific arguments that were left unparsed.
/**
* Some ROS specific arguments may not have been recognized, or were not intended to be
* parsed by rcl.
* This function populates an array of indices to these arguments in the original argv array.
*
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args An arguments structure that has been parsed.
* \param[in] allocator A valid allocator.
* \param[out] output_unparsed_ros_indices An allocated array of indices into the original argv array.
* This array must be deallocated by the caller using the given allocator.
* If there are no unparsed ROS specific arguments then the output will be set to NULL.
* \return `RCL_RET_OK` if everything goes correctly, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_get_unparsed_ros(
const rcl_arguments_t * args,
rcl_allocator_t allocator,
int ** output_unparsed_ros_indices);
/// Return the number of parameter yaml files given in the arguments.
/**
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | No
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args An arguments structure that has been parsed.
* \return number of yaml files, or
* \return -1 if args is `NULL` or zero initialized.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
int
rcl_arguments_get_param_files_count(
const rcl_arguments_t * args);
/// Return a list of yaml parameter file paths specified on the command line.
/**
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] arguments An arguments structure that has been parsed.
* \param[in] allocator A valid allocator.
* \param[out] parameter_files An allocated array of paramter file names.
* This array must be deallocated by the caller using the given allocator.
* The output is NULL if there were no paramter files.
* \return `RCL_RET_OK` if everything goes correctly, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_get_param_files(
const rcl_arguments_t * arguments,
rcl_allocator_t allocator,
char *** parameter_files);
/// Return all parameter overrides parsed from the command line.
/**
* Parameter overrides are parsed directly from command line arguments and
* parameter files provided in the command line.
*
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] arguments An arguments structure that has been parsed.
* \param[out] parameter_overrides Parameter overrides as parsed from command line arguments.
* This structure must be finalized by the caller.
* The output is NULL if no parameter overrides were parsed.
* \return `RCL_RET_OK` if everything goes correctly, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_get_param_overrides(
const rcl_arguments_t * arguments,
rcl_params_t ** parameter_overrides);
/// Return a list of arguments with ROS-specific arguments removed.
/**
* Some arguments may not have been intended as ROS arguments.
* This function populates an array of the aruments in a new argv array.
* Since the first argument is always assumed to be a process name, the list
* will always contain the first value from the argument vector.
*
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] argv The argument vector
* \param[in] args An arguments structure that has been parsed.
* \param[in] allocator A valid allocator.
* \param[out] nonros_argc The count of arguments that aren't ROS-specific
* \param[out] nonros_argv An allocated array of arguments that aren't ROS-specific
* This array must be deallocated by the caller using the given allocator.
* If there are no non-ROS args, then the output will be set to NULL.
* \return `RCL_RET_OK` if everything goes correctly, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_remove_ros_arguments(
char const * const argv[],
const rcl_arguments_t * args,
rcl_allocator_t allocator,
int * nonros_argc,
const char ** nonros_argv[]);
/// Copy one arguments structure into another.
/**
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | Yes
* Thread-Safe | No
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args The structure to be copied.
* Its allocator is used to copy memory into the new structure.
* \param[out] args_out A zero-initialized arguments structure to be copied into.
* \return `RCL_RET_OK` if the structure was copied successfully, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_copy(
const rcl_arguments_t * args,
rcl_arguments_t * args_out);
/// Reclaim resources held inside rcl_arguments_t structure.
/**
*
* Attribute | Adherence
* ------------------ | -------------
* Allocates Memory | No
* Thread-Safe | Yes
* Uses Atomics | No
* Lock-Free | Yes
*
* \param[in] args The structure to be deallocated.
* \return `RCL_RET_OK` if the memory was successfully freed, or
* \return `RCL_RET_INVALID_ARGUMENT` if any function arguments are invalid, or
* \return `RCL_RET_ERROR` if an unspecified error occurs.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_fini(
rcl_arguments_t * args);
#ifdef __cplusplus
}
#endif
#endif // RCL__ARGUMENTS_H_