Commit e3060212 authored by Dominik Charousset's avatar Dominik Charousset

Use string_view in config_option and config_value

parent 435cfae4
......@@ -18,9 +18,11 @@
#pragma once
#include <memory>
#include <string>
#include "caf/fwd.hpp"
#include "caf/string_view.hpp"
namespace caf {
......@@ -49,8 +51,8 @@ public:
// -- constructors, destructors, and assignment operators --------------------
/// Constructs a config option.
config_option(std::string category, const char* name, std::string description,
const meta_state* meta, void* storage = nullptr);
config_option(string_view category, string_view name, string_view description,
const meta_state* meta, void* value = nullptr);
config_option(config_option&&) = default;
......@@ -58,25 +60,20 @@ public:
// -- properties -------------------------------------------------------------
inline const std::string& category() const noexcept {
return category_;
}
/// Returns the category of the option.
string_view category() const noexcept;
/// Returns the
inline const std::string& long_name() const noexcept {
return long_name_;
}
/// Returns the name of the option.
string_view long_name() const noexcept;
inline const std::string& short_names() const noexcept {
return short_names_;
}
/// Returns (optional) one-letter short names of the option.
string_view short_names() const noexcept;
inline const std::string& description() const noexcept {
return description_;
}
/// Returns a human-readable description of the option.
string_view description() const noexcept;
/// Returns the full name for this config option as "<category>.<long name>".
std::string full_name() const;
string_view full_name() const noexcept;
/// Checks whether `x` holds a legal value for this option.
error check(const config_value& x) const;
......@@ -86,7 +83,7 @@ public:
void store(const config_value& x) const;
/// Returns a human-readable representation of this option's expected type.
const std::string& type_name() const noexcept;
string_view type_name() const noexcept;
/// Returns whether this config option stores a boolean flag.
bool is_flag() const noexcept;
......@@ -96,10 +93,13 @@ public:
optional<config_value> get() const;
private:
std::string category_;
std::string long_name_;
std::string short_names_;
std::string description_;
string_view buf_slice(size_t from, size_t to) const noexcept;
std::unique_ptr<char[]> buf_;
uint16_t category_separator_;
uint16_t long_name_separator_;
uint16_t short_names_separator_;
uint16_t buf_size_;
const meta_state* meta_;
mutable void* value_;
};
......
......@@ -30,36 +30,36 @@ class config_option_adder {
public:
// -- constructors, destructors, and assignment operators --------------------
config_option_adder(config_option_set& target, const char* category);
config_option_adder(config_option_set& target, string_view category);
// -- properties -------------------------------------------------------------
/// Adds a config option to the category that synchronizes with `ref`.
template <class T>
config_option_adder& add(T& ref, const char* name, const char* description) {
config_option_adder& add(T& ref, string_view name, string_view description) {
return add_impl(make_config_option(ref, category_, name, description));
}
/// Adds a config option to the category.
template <class T>
config_option_adder& add(const char* name, const char* description) {
config_option_adder& add(string_view name, string_view description) {
return add_impl(make_config_option<T>(category_, name, description));
}
/// For backward compatibility only. Do not use for new code!
/// @private
config_option_adder& add_neg(bool& ref, const char* name,
const char* description);
config_option_adder& add_neg(bool& ref, string_view name,
string_view description);
/// For backward compatibility only. Do not use for new code!
/// @private
config_option_adder& add_us(size_t& ref, const char* name,
const char* description);
config_option_adder& add_us(size_t& ref, string_view name,
string_view description);
/// For backward compatibility only. Do not use for new code!
/// @private
config_option_adder& add_ms(size_t& ref, const char* name,
const char* description);
config_option_adder& add_ms(size_t& ref, string_view name,
string_view description);
private:
// -- properties -------------------------------------------------------------
......@@ -72,7 +72,7 @@ private:
config_option_set& xs_;
/// Category for all options generated by this adder.
const char* category_;
string_view category_;
};
} // namespace caf
......@@ -100,15 +100,15 @@ public:
/// Adds a config option to the set.
template <class T>
config_option_set& add(const char* category, const char* name,
const char* description = "") {
config_option_set& add(string_view category, string_view name,
string_view description = "") {
return add(make_config_option<T>(category, name, description));
}
/// Adds a config option to the set that synchronizes its value with `ref`.
template <class T>
config_option_set& add(T& ref, const char* category, const char* name,
const char* description = "") {
config_option_set& add(T& ref, string_view category, string_view name,
string_view description = "") {
return add(make_config_option<T>(ref, category, name, description));
}
......
......@@ -97,11 +97,11 @@ public:
// -- parsing ----------------------------------------------------------------
/// Tries to parse a value from `str`.
static expected<config_value> parse(std::string::const_iterator first,
std::string::const_iterator last);
static expected<config_value> parse(string_view::iterator first,
string_view::iterator last);
/// Tries to parse a value from `str`.
static expected<config_value> parse(const std::string& str);
static expected<config_value> parse(string_view str);
// -- properties -------------------------------------------------------------
......
......@@ -120,6 +120,7 @@ class scheduled_actor;
class scoped_actor;
class serializer;
class stream_manager;
class string_view;
class type_erased_tuple;
class type_erased_value;
class uniform_type_info_map;
......@@ -143,12 +144,12 @@ struct prohibit_top_level_spawn_marker;
// -- free template functions --------------------------------------------------
template <class T>
config_option make_config_option(const char* category, const char* name,
const char* description);
config_option make_config_option(string_view category, string_view name,
string_view description);
template <class T>
config_option make_config_option(T& storage, const char* category,
const char* name, const char* description);
config_option make_config_option(T& storage, string_view category,
string_view name, string_view description);
// -- enums --------------------------------------------------------------------
......
......@@ -54,15 +54,15 @@ config_option::meta_state option_meta_state<T>::instance{
/// Creates a config option that synchronizes with `storage`.
template <class T>
config_option make_config_option(const char* category, const char* name,
const char* description) {
config_option make_config_option(string_view category, string_view name,
string_view description) {
return {category, name, description, &detail::option_meta_state<T>::instance};
}
/// Creates a config option that synchronizes with `storage`.
template <class T>
config_option make_config_option(T& storage, const char* category,
const char* name, const char* description) {
config_option make_config_option(T& storage, string_view category,
string_view name, string_view description) {
return {category, name, description, &detail::option_meta_state<T>::instance,
std::addressof(storage)};
}
......@@ -70,32 +70,32 @@ config_option make_config_option(T& storage, const char* category,
// -- backward compatbility, do not use for new code ! -------------------------
// Inverts the value when writing to `storage`.
config_option make_negated_config_option(bool& storage, const char* category,
const char* name,
const char* description);
config_option make_negated_config_option(bool& storage, string_view category,
string_view name,
string_view description);
// Reads timespans, but stores an integer representing microsecond resolution.
config_option make_us_resolution_config_option(size_t& storage,
const char* category,
const char* name,
const char* description);
string_view category,
string_view name,
string_view description);
// Reads timespans, but stores an integer representing millisecond resolution.
config_option make_ms_resolution_config_option(size_t& storage,
const char* category,
const char* name,
const char* description);
string_view category,
string_view name,
string_view description);
// -- specializations for common types -----------------------------------------
#define CAF_SPECIALIZE_MAKE_CONFIG_OPTION(type) \
template <> \
config_option make_config_option<std::string>( \
std::string & storage, const char* category, const char* name, \
const char* description); \
std::string & storage, string_view category, string_view name, \
string_view description); \
template <> \
config_option make_config_option<std::string>( \
const char* category, const char* name, const char* description)
string_view category, string_view name, string_view description)
CAF_SPECIALIZE_MAKE_CONFIG_OPTION(atom_value);
......
......@@ -19,6 +19,7 @@
#pragma once
#include <cstddef>
#include <iosfwd>
#include <iterator>
#include <limits>
#include <type_traits>
......@@ -286,3 +287,9 @@ private:
};
} // namespace caf
namespace std {
std::ostream& operator<<(std::ostream& out, caf::string_view);
} // namespace std
......@@ -18,8 +18,9 @@
#include "caf/config_option.hpp"
#include <cstring>
#include <iostream>
#include <algorithm>
#include <limits>
#include <numeric>
#include "caf/config.hpp"
#include "caf/config_value.hpp"
......@@ -29,41 +30,73 @@
using std::move;
using std::string;
namespace {
namespace caf {
// -- constructors, destructors, and assignment operators ----------------------
string get_long_name(const char* name) {
auto i= strchr(name, ',');
return i != nullptr ? string{name, i} : string{name};
config_option::config_option(string_view category, string_view name,
string_view description, const meta_state* meta,
void* value)
: meta_(meta),
value_(value) {
using std::copy;
using std::accumulate;
auto comma = name.find(',');
auto long_name = name.substr(0, comma);
auto short_names = comma == string_view::npos ? string_view{}
: name.substr(comma + 1);
auto total_size = [](std::initializer_list<string_view> xs) {
return (xs.size() - 1) // one separator between all fields
+ accumulate(xs.begin(), xs.end(), size_t{0},
[](size_t x, string_view sv) { return x + sv.size(); });
};
auto ts = total_size({category, long_name, short_names, description});
CAF_ASSERT(ts <= std::numeric_limits<uint16_t>::max());
buf_size_ = static_cast<uint16_t>(ts);
buf_.reset(new char[ts]);
// fille the buffer with "<category>.<long-name>,<short-name>,<descriptions>"
auto first = buf_.get();
auto i = first;
auto pos = [&] {
return static_cast<uint16_t>(std::distance(first, i));
};
// <category>.
i = copy(category.begin(), category.end(), i);
category_separator_ = pos();
*i++ = '.';
// <long-name>,
i = copy(long_name.begin(), long_name.end(), i);
long_name_separator_ = pos();
*i++ = ',';
// <short-names>,
i = copy(short_names.begin(), short_names.end(), i);
short_names_separator_ = pos();
*i++ = ',';
// <description>
copy(description.begin(), description.end(), i);
CAF_ASSERT(pos() == buf_size_);
}
string get_short_names(const char* name) {
auto substr = strchr(name, ',');
if (substr != nullptr)
return ++substr;
return string{};
// -- properties ---------------------------------------------------------------
string_view config_option::category() const noexcept {
return buf_slice(0, category_separator_);
}
} // namespace <anonymous>
string_view config_option::long_name() const noexcept {
return buf_slice(category_separator_ + 1, long_name_separator_);
}
namespace caf {
string_view config_option::short_names() const noexcept {
return buf_slice(long_name_separator_ + 1, short_names_separator_);
}
config_option::config_option(string category, const char* name,
string description, const meta_state* meta,
void* value)
: category_(move(category)),
long_name_(get_long_name(name)),
short_names_(get_short_names(name)),
description_(move(description)),
meta_(meta),
value_(value) {
CAF_ASSERT(meta_ != nullptr);
string_view config_option::description() const noexcept {
return buf_slice(short_names_separator_ + 1, buf_size_);
}
string config_option::full_name() const {
std::string result = category();
result += '.';
result += long_name_;
return result;
string_view config_option::full_name() const noexcept {
return buf_slice(0, long_name_separator_);
}
error config_option::check(const config_value& x) const {
......@@ -78,7 +111,7 @@ void config_option::store(const config_value& x) const {
}
}
const std::string& config_option::type_name() const noexcept {
string_view config_option::type_name() const noexcept {
return meta_->type_name;
}
......@@ -92,4 +125,9 @@ optional<config_value> config_option::get() const {
return none;
}
string_view config_option::buf_slice(size_t from, size_t to) const noexcept {
CAF_ASSERT(from <= to);
return {buf_.get() + from, to - from};
}
} // namespace caf
......@@ -23,26 +23,26 @@
namespace caf {
config_option_adder::config_option_adder(config_option_set& target,
const char* category)
string_view category)
: xs_(target),
category_(category) {
// nop
}
config_option_adder& config_option_adder::add_neg(bool& ref, const char* name,
const char* description) {
config_option_adder& config_option_adder::add_neg(bool& ref, string_view name,
string_view description) {
return add_impl(make_negated_config_option(ref, category_,
name, description));
}
config_option_adder& config_option_adder::add_us(size_t& ref, const char* name,
const char* description) {
config_option_adder& config_option_adder::add_us(size_t& ref, string_view name,
string_view description) {
return add_impl(make_us_resolution_config_option(ref, category_,
name, description));
}
config_option_adder& config_option_adder::add_ms(size_t& ref, const char* name,
const char* description) {
config_option_adder& config_option_adder::add_ms(size_t& ref, string_view name,
string_view description) {
return add_impl(make_ms_resolution_config_option(ref, category_,
name, description));
}
......
......@@ -34,19 +34,13 @@ struct string_builder {
std::string result;
};
template <size_t N>
string_builder& operator<<(string_builder& builder, const char (&cstr)[N]) {
builder.result.append(cstr, N - 1);
string_builder& operator<<(string_builder& builder, char ch) {
builder.result += ch;
return builder;
}
string_builder& operator<<(string_builder& builder, char c) {
builder.result += c;
return builder;
}
string_builder& operator<<(string_builder& builder, const std::string& str) {
builder.result += str;
string_builder& operator<<(string_builder& builder, caf::string_view str) {
builder.result.append(str.data(), str.size());
return builder;
}
......@@ -94,8 +88,8 @@ std::string config_option_set::help_text(bool global_only) const {
};
// Sort argument + description by category.
using pair = std::pair<std::string, option_pointer>;
std::set<std::string> categories;
std::multimap<std::string, pair> args;
std::set<string_view> categories;
std::multimap<string_view, pair> args;
size_t max_arg_size = 0;
for (auto& opt : opts_) {
if (!global_only || opt.category() == "global") {
......@@ -132,7 +126,7 @@ auto config_option_set::parse(config_map& config, argument_iterator first,
auto consume = [&](const config_option& opt, iter arg_begin, iter arg_end) {
// Extract option name and category.
auto opt_name = opt.long_name();
string opt_ctg = opt.category();
auto opt_ctg = opt.category();
// Try inserting a new submap into the config or fill existing one.
auto& submap = config[opt_ctg];
// Flags only consume the current element.
......@@ -145,7 +139,9 @@ auto config_option_set::parse(config_map& config, argument_iterator first,
} else {
if (arg_begin == arg_end)
return pec::missing_argument;
auto val = config_value::parse(arg_begin, arg_end);
auto slice_size = static_cast<size_t>(std::distance(arg_begin, arg_end));
string_view slice{&*arg_begin, slice_size};
auto val = config_value::parse(slice);
if (!val)
return pec::illegal_argument;
if (opt.check(*val) != none)
......
......@@ -50,8 +50,8 @@ config_value::~config_value() {
// -- parsing ------------------------------------------------------------------
expected<config_value> config_value::parse(std::string::const_iterator first,
std::string::const_iterator last) {
expected<config_value> config_value::parse(string_view::iterator first,
string_view::iterator last) {
using namespace detail;
auto i = first;
// Sanity check.
......@@ -62,7 +62,7 @@ expected<config_value> config_value::parse(std::string::const_iterator first,
if (++i == last)
return make_error(pec::unexpected_eof);
// Dispatch to parser.
parser::state<std::string::const_iterator> res;
parser::state<string_view::iterator> res;
detail::ini_value_consumer f;
res.i = i;
res.e = last;
......@@ -84,7 +84,7 @@ expected<config_value> config_value::parse(std::string::const_iterator first,
}
}
expected<config_value> config_value::parse(const std::string& str) {
expected<config_value> config_value::parse(string_view str) {
return parse(str.begin(), str.end());
}
......
......@@ -54,15 +54,15 @@ config_value get_impl(const void* ptr) {
#define DEFAULT_MAKE_IMPL(type) \
template <> \
config_option make_config_option<type>(type & storage, const char* category, \
const char* name, \
const char* description) { \
config_option make_config_option<type>(type & storage, string_view category, \
string_view name, \
string_view description) { \
return {category, name, description, &type##_meta, &storage}; \
} \
template <> \
config_option make_config_option<type>(const char* category, \
const char* name, \
const char* description) { \
config_option make_config_option<type>(string_view category, \
string_view name, \
string_view description) { \
return {category, name, description, &type##_meta, nullptr}; \
}
......@@ -136,23 +136,23 @@ DEFAULT_META(string);
} // namespace anonymous
config_option make_negated_config_option(bool& storage, const char* category,
const char* name,
const char* description) {
config_option make_negated_config_option(bool& storage, string_view category,
string_view name,
string_view description) {
return {category, name, description, &bool_neg_meta, &storage};
}
config_option make_us_resolution_config_option(size_t& storage,
const char* category,
const char* name,
const char* description) {
string_view category,
string_view name,
string_view description) {
return {category, name, description, &us_res_meta, &storage};
}
config_option make_ms_resolution_config_option(size_t& storage,
const char* category,
const char* name,
const char* description) {
string_view category,
string_view name,
string_view description) {
return {category, name, description, &ms_res_meta, &storage};
}
......
......@@ -20,7 +20,7 @@
#include <algorithm>
#include <cstring>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include "caf/config.hpp"
......@@ -306,3 +306,13 @@ size_type string_view::find_last_not_of(const_pointer str,
}
} // namespace caf
namespace std {
std::ostream& operator<<(std::ostream& out, caf::string_view str) {
for (auto ch : str)
out.put(ch);
return out;
}
} // namespace std
......@@ -30,9 +30,9 @@ using std::string;
namespace {
constexpr const char* category = "category";
constexpr const char* name = "name";
constexpr const char* explanation = "explanation";
constexpr string_view category = "category";
constexpr string_view name = "name";
constexpr string_view explanation = "explanation";
template<class T>
constexpr int64_t overflow() {
......@@ -45,7 +45,7 @@ constexpr int64_t underflow() {
}
template <class T>
optional<T> read(const std::string& arg) {
optional<T> read(string_view arg) {
auto co = make_config_option<T>(category, name, explanation);
auto res = config_value::parse(arg);
if (res && holds_alternative<T>(*res)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment