24#include <boost/lexical_cast.hpp>
25#include <boost/algorithm/string.hpp>
144template<
typename Value>
165 explicit Scoped_setter(Value* target, Value&& val_src_moved);
206template<
typename Value>
208 m_target_or_null(target),
209 m_saved_value(std::move(*m_target_or_null))
214template<
typename Value>
216 m_target_or_null(src_moved.m_target_or_null),
217 m_saved_value(std::move(src_moved.m_saved_value))
219 assert(
m_target_or_null &&
"Should not be moving-from a thing that has already been moved-from.");
221 src_moved.m_target_or_null =
nullptr;
225template<
typename Value>
228 if (m_target_or_null)
230 *m_target_or_null = std::move(m_saved_value);
237template<
typename Time_unit,
typename N_items>
254 double(items_per_time) * double(bits_per_item) * double(Time_unit::period::den)
255 / (double(Time_unit::period::num) * double(1000 * 1000));
258template<
typename Integer,
typename Integer2>
259constexpr Integer
ceil_div(Integer dividend, Integer2 divisor)
262 static_assert(std::is_integral_v<Integer>,
"ceil_div<T, T2>: T must be an integer type.");
263 static_assert(std::is_integral_v<Integer2>,
"ceil_div<T, T2>: T2 must be an integer type.");
268 return (dividend +
static_cast<Integer
>(divisor) -
static_cast<Integer
>(1)) /
static_cast<Integer
>(divisor);
273template<
typename Integer,
typename Integer2>
276 return static_cast<Integer
>(unit) *
ceil_div(dividend, unit);
283 return ((min_val < val) || (!(val < min_val))) &&
284 ((val < max_val) || (!(max_val < val)));
291 return (min_val < val) &&
292 ((val < max_val) || (!(max_val < val)));
299 return (val < max_val) &&
300 ((min_val < val) || (!(val < min_val)));
306 return (min_val < val) && (val < max_val);
309template<
typename Container>
310bool key_exists(
const Container& container,
const typename Container::key_type& key)
312 return container.find(key) != container.end();
315template<
typename Cleanup_func>
329 [func](
void*) { func(); }};
332template<
typename Minuend,
typename Subtrahend>
341 const Minuend converted_subtrahend = Minuend{subtrahend};
344 if ((*minuend - floor) <= converted_subtrahend)
350 *minuend -= converted_subtrahend;
354template<
typename From,
typename To>
357 return ((num_froms *
sizeof(From)) +
sizeof(To) - 1) /
sizeof(To);
360template<
typename... T>
363 (*os << ... << std::forward<T>(ostream_args));
366template<
typename... T>
380template<
typename... T>
390template<
typename Map,
typename Sequence>
392 (Sequence
const & src_seq, Map* target_map,
393 const Function<
typename Map::mapped_type (
size_t)>& idx_to_map_val_func)
396 for (
const auto& src_element : src_seq)
398 (*target_map)[src_element] = idx_to_map_val_func(idx);
403template<
typename Map,
typename Sequence>
412template<
typename Const_buffer_sequence>
414 const Const_buffer_sequence& data,
415 const std::string& indentation,
416 size_t bytes_per_line)
418 using boost::io::ios_fill_saver;
419 using boost::io::ios_flags_saver;
420 using boost::io::ios_width_saver;
421 using boost::asio::buffers_iterator;
426 using Bufs_iter = buffers_iterator<Const_buffer_sequence, uint8_t>;
428 constexpr size_t BYTES_PER_LINE_DEFAULT = 16;
429 bool single_line_mode =
false;
430 if (bytes_per_line == 0)
432 bytes_per_line = BYTES_PER_LINE_DEFAULT;
434 else if (bytes_per_line ==
size_t(-1))
438 bytes_per_line = buffer_size(data);
442 single_line_mode =
true;
446 ios_flags_saver flags_saver{os};
447 ios_fill_saver fill_saver{os};
448 ios_width_saver width_saver{os};
452 os.setf(std::ios::right | std::ios::hex, std::ios::adjustfield | std::ios::basefield);
453 os << std::setfill(
'0');
455 const Bufs_iter end_byte_it = Bufs_iter::end(data);
456 for (Bufs_iter cur_byte_it = Bufs_iter::begin(data);
457 cur_byte_it != end_byte_it;
461 os << indentation <<
'['
462 << std::setw(2) << int(*cur_byte_it);
465 size_t n_bytes_printed;
466 for ((n_bytes_printed = 1), ++cur_byte_it;
467 (n_bytes_printed != bytes_per_line) && (cur_byte_it != end_byte_it);
468 ++cur_byte_it, ++n_bytes_printed)
470 os <<
' ' << std::setw(2) << int(*cur_byte_it);
474 for (
size_t n_bytes_printed_including_padding = n_bytes_printed;
475 n_bytes_printed_including_padding != bytes_per_line;
476 ++n_bytes_printed_including_padding)
482 cur_byte_it -= n_bytes_printed;
485 for (
size_t n_chars_printed = 0;
486 n_chars_printed != n_bytes_printed;
487 ++cur_byte_it, ++n_chars_printed)
489 char c = *cur_byte_it;
490 os << (isprint(c) ? c :
'.');
493 if (!single_line_mode)
504template<
typename Const_buffer_sequence>
506 size_t bytes_per_line)
521template<
typename Enum>
523 bool accept_num_encoding,
bool case_sensitive,
526 using boost::lexical_cast;
527 using boost::bad_lexical_cast;
528 using boost::algorithm::equals;
529 using boost::algorithm::is_iequal;
534 using Traits = std::char_traits<char>;
535 using enum_t = std::underlying_type_t<Enum>;
539 assert(enum_t(enum_lowest) >= 0);
541 const is_iequal i_equal_func{locale::classic()};
546 while (((ch = is.peek()) != Traits::eof()) && (isalnum(ch) || (ch ==
'_')))
552 Enum val = enum_default;
556 if (accept_num_encoding && isdigit(token.front()))
561 num_enum = lexical_cast<enum_t>(token);
563 if ((num_enum >= enum_t(enum_sentinel) || (num_enum < enum_t(enum_lowest))))
565 num_enum = enum_t(enum_default);
567 val = Enum{num_enum};
569 catch (
const bad_lexical_cast&)
571 assert(val == enum_default);
578 for (idx = enum_t(enum_lowest); idx != enum_t(enum_sentinel); ++idx)
580 const auto candidate = Enum{idx};
584 if (case_sensitive ? equals(token, lexical_cast<string>(candidate))
585 : equals(token, lexical_cast<string>(candidate), i_equal_func))
591 assert((idx != enum_t(enum_sentinel)) || (val == enum_default));
An empty interface, consisting of nothing but a default virtual destructor, intended as a boiler-plat...
virtual ~Null_interface()=0
Boring virtual destructor.
A simple RAII-pattern class template that, at construction, sets the specified location in memory to ...
~Scoped_setter()
Restores *target (from main ctor) to its value at entry to said ctor; or does nothing if *this has be...
Value m_saved_value
If and only if m_target_or_null is non-null, this saves *m_target_or_null. Otherwise meaningless.
Scoped_setter(const Scoped_setter &)=delete
Prohibit copying: for each explicit ctor invocation, there shall be exactly 1 non-no-op dtor invocati...
Scoped_setter & operator=(const Scoped_setter &)=delete
Prohibit copying (see deleted copy ctor).
Value * m_target_or_null
Target object location; see ctors; if null then this is a moved-from Scoped_setter that intentionally...
Scoped_setter(Value *target, Value &&val_src_moved)
Post-condition: *target contains was val_src_moved contained at ctor entry; and the destructor invoca...
Scoped_setter & operator=(Scoped_setter &&)=delete
Prohibit modifying existing *this; except that moving-from is enabled via the move ctor.
Similar to ostringstream but allows fast read-only access directly into the std::string being written...
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
bool in_closed_open_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a [low,...
bool key_exists(const Container &container, const typename Container::key_type &key)
Returns true if and only if the given key is present at least once in the given associative container...
Auto_cleanup setup_auto_cleanup(const Cleanup_func &func)
Provides a way to execute arbitrary (cleanup) code at the exit of the current block.
void sequence_to_inverted_lookup_map(Sequence const &src_seq, Map *target_map, const Function< typename Map::mapped_type(size_t)> &idx_to_map_val_func)
Similar to the 2-arg overload of sequence_to_inverted_lookup_map() but with the ability to store a va...
double to_mbit_per_sec(N_items items_per_time, size_t bits_per_item)
Utility that converts a bandwidth in arbitrary units in both numerator and denominator to the same ba...
std::string buffers_dump_string(const Const_buffer_sequence &data, const std::string &indentation, size_t bytes_per_line)
Identical to buffers_to_ostream() but returns an std::string instead of writing to a given ostream.
Enum istream_to_enum(std::istream *is_ptr, Enum enum_default, Enum enum_sentinel, bool accept_num_encoding, bool case_sensitive, Enum enum_lowest)
Deserializes an enum class value from a standard input stream.
void feed_args_to_ostream(std::ostream *os, T &&... ostream_args)
Function template that simply outputs arguments 2+ via << to the given ostream, in the order given.
bool subtract_with_floor(Minuend *minuend, const Subtrahend &subtrahend, const Minuend &floor)
Performs *minuend -= subtrahend, subject to a floor of floor.
constexpr Integer round_to_multiple(Integer dividend, Integer2 unit)
Returns the smallest integer >= the given integer dividend such that it is a multiple of the given in...
size_t size_unit_convert(From num_froms)
Answers the question what's the smallest integer number of Tos sufficient to verbatim store the given...
bool in_open_open_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a (low,...
bool in_open_closed_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a (low,...
void ostream_op_to_string(std::string *target_str, T &&... ostream_args)
Writes to the specified string, as if the given arguments were each passed, via << in sequence,...
std::ostream & buffers_to_ostream(std::ostream &os, const Const_buffer_sequence &data, const std::string &indentation, size_t bytes_per_line)
Writes a multi- or single-line string representation of the provided binary data to an output stream,...
bool in_closed_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, inclusive.
boost::shared_ptr< void > Auto_cleanup
Helper type for setup_auto_cleanup().
std::string ostream_op_string(T &&... ostream_args)
Equivalent to ostream_op_to_string() but returns a new string by value instead of writing to the call...
constexpr Integer ceil_div(Integer dividend, Integer2 divisor)
Returns the result of the given non-negative integer divided by a positive integer,...
Useful as a no-unique-address private member to make a type noncopyable while keeping that type an ag...
Noncopyable(const Noncopyable &)=delete
Forbid copying.
void operator=(const Noncopyable &)=delete
Forbid copying.
Noncopyable()=default
Makes it possible to instantiate.