23#include <boost/lexical_cast.hpp>
24#include <boost/algorithm/string.hpp>
118template<
typename Value>
139 explicit Scoped_setter(Value* target, Value&& val_src_moved);
180template<
typename Value>
182 m_target_or_null(target),
183 m_saved_value(std::move(*m_target_or_null))
188template<
typename Value>
190 m_target_or_null(src_moved.m_target_or_null),
191 m_saved_value(std::move(src_moved.m_saved_value))
193 assert(
m_target_or_null &&
"Should not be moving-from a thing that has already been moved-from.");
195 src_moved.m_target_or_null =
nullptr;
199template<
typename Value>
202 if (m_target_or_null)
204 *m_target_or_null = std::move(m_saved_value);
211template<
typename Time_unit,
typename N_items>
228 double(items_per_time) * double(bits_per_item) * double(Time_unit::period::den)
229 / (double(Time_unit::period::num) * double(1000 * 1000));
232template<
typename Integer>
236 static_assert(std::is_integral_v<Integer>,
"ceil_div<T>: T must be an integer type.");
237 assert(dividend >= 0);
240 return (dividend + divisor - 1) / divisor;
249 return ((min_val < val) || (!(val < min_val))) &&
250 ((val < max_val) || (!(max_val < val)));
257 return (min_val < val) &&
258 ((val < max_val) || (!(max_val < val)));
265 return (val < max_val) &&
266 ((min_val < val) || (!(val < min_val)));
272 return (min_val < val) && (val < max_val);
275template<
typename Container>
276bool key_exists(
const Container& container,
const typename Container::key_type& key)
278 return container.find(key) != container.end();
281template<
typename Cleanup_func>
295 [func](
void*) { func(); });
298template<
typename Minuend,
typename Subtrahend>
307 const Minuend converted_subtrahend = Minuend(subtrahend);
310 if ((*minuend - floor) <= converted_subtrahend)
316 *minuend -= converted_subtrahend;
320template<
typename From,
typename To>
323 return ((num_froms *
sizeof(From)) +
sizeof(To) - 1) /
sizeof(To);
326template<
typename T1,
typename ...T_rest>
338 *os << only_ostream_arg;
341template<
typename ...T>
355template<
typename ...T>
365template<
typename Map,
typename Sequence>
367 (Sequence
const & src_seq, Map* target_map,
368 const Function<
typename Map::mapped_type (
size_t)>& idx_to_map_val_func)
371 for (
const auto& src_element : src_seq)
373 (*target_map)[src_element] = idx_to_map_val_func(idx);
378template<
typename Map,
typename Sequence>
387template<
typename Const_buffer_sequence>
389 const Const_buffer_sequence& data,
390 const std::string& indentation,
391 size_t bytes_per_line)
393 using boost::io::ios_fill_saver;
394 using boost::io::ios_flags_saver;
395 using boost::io::ios_width_saver;
396 using boost::asio::buffers_iterator;
401 using Bufs_iter = buffers_iterator<Const_buffer_sequence, uint8_t>;
403 constexpr size_t BYTES_PER_LINE_DEFAULT = 16;
404 bool single_line_mode =
false;
405 if (bytes_per_line == 0)
407 bytes_per_line = BYTES_PER_LINE_DEFAULT;
409 else if (bytes_per_line ==
size_t(-1))
413 bytes_per_line = buffer_size(data);
417 single_line_mode =
true;
421 ios_flags_saver flags_saver(os);
422 ios_fill_saver fill_saver(os);
423 ios_width_saver width_saver(os);
427 os.setf(std::ios::right | std::ios::hex, std::ios::adjustfield | std::ios::basefield);
428 os << std::setfill(
'0');
430 const Bufs_iter end_byte_it = Bufs_iter::end(data);
432 for (Bufs_iter cur_byte_it = Bufs_iter::begin(data);
433 cur_byte_it != end_byte_it;
437 os << indentation <<
'['
438 << std::setw(2) << int(*cur_byte_it);
441 size_t n_bytes_printed;
442 for ((n_bytes_printed = 1), ++cur_byte_it;
443 (n_bytes_printed != bytes_per_line) && (cur_byte_it != end_byte_it);
444 ++cur_byte_it, ++n_bytes_printed)
446 os <<
' ' << std::setw(2) << int(*cur_byte_it);
450 for (
size_t n_bytes_printed_including_padding = n_bytes_printed;
451 n_bytes_printed_including_padding != bytes_per_line;
452 ++n_bytes_printed_including_padding)
458 cur_byte_it -= n_bytes_printed;
461 for (
size_t n_chars_printed = 0;
462 n_chars_printed != n_bytes_printed;
463 ++cur_byte_it, ++n_chars_printed)
465 char c = *cur_byte_it;
466 os << (isprint(c) ? c :
'.');
469 if (!single_line_mode)
480template<
typename Const_buffer_sequence>
482 size_t bytes_per_line)
497template<
typename Enum>
499 bool accept_num_encoding,
bool case_sensitive,
502 using boost::lexical_cast;
503 using boost::bad_lexical_cast;
504 using boost::algorithm::equals;
505 using boost::algorithm::is_iequal;
510 using Traits = std::char_traits<char>;
511 using enum_t = std::underlying_type_t<Enum>;
515 assert(enum_t(enum_lowest) >= 0);
517 const is_iequal i_equal_func(locale::classic());
522 while (((ch = is.peek()) != Traits::eof()) && (isalnum(ch) || (ch ==
'_')))
528 Enum val = enum_default;
532 if (accept_num_encoding && isdigit(token.front()))
537 num_enum = lexical_cast<enum_t>(token);
539 if ((num_enum >= enum_t(enum_sentinel) || (num_enum < enum_t(enum_lowest))))
541 num_enum = enum_t(enum_default);
543 val = Enum(num_enum);
545 catch (
const bad_lexical_cast& exc)
547 assert(val == enum_default);
554 for (idx = enum_t(enum_lowest); idx != enum_t(enum_sentinel); ++idx)
556 const auto candidate = Enum(idx);
560 if (case_sensitive ? equals(token, lexical_cast<string>(candidate))
561 : equals(token, lexical_cast<string>(candidate), i_equal_func))
567 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...
std::ostream & os()
Access to stream that will write to owned string.
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.
bool subtract_with_floor(Minuend *minuend, const Subtrahend &subtrahend, const Minuend &floor)
Performs *minuend -= subtrahend, subject to a floor of floor.
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...
std::string ostream_op_string(T const &... ostream_args)
Equivalent to ostream_op_to_string() but returns a new string by value instead of writing to the call...
Integer ceil_div(Integer dividend, Integer divisor)
Returns the result of the given non-negative integer divided by a positive integer,...
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 const &... 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().
void feed_args_to_ostream(std::ostream *os, T1 const &ostream_arg1, T_rest const &... remaining_ostream_args)
"Induction step" version of variadic function template that simply outputs arguments 2+ via << to the...