microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
boost_values.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
9#include "../microfmt.hpp"
10#include <boost/dynamic_bitset.hpp>
11#include <boost/logic/tribool.hpp>
12#include <boost/rational.hpp>
13#include <cstddef>
14#include <limits>
15#include <type_traits>
16
17namespace microfmt {
18
19template <typename Block, typename Allocator> struct formatter<boost::dynamic_bitset<Block, Allocator>> {
20 unsigned base{2};
21 bool uppercase{false};
22 bool prefix{false};
23
24 constexpr void parse(format_parse_context &ctx) noexcept {
25 for (const char character : ctx.spec()) {
26 if (character == 'x' || character == 'X') {
27 base = 16;
28 uppercase = character == 'X';
29 } else if (character == 'b') {
30 base = 2;
31 } else if (character == '#') {
32 prefix = true;
33 }
34 }
35 }
36
37 void format(const boost::dynamic_bitset<Block, Allocator> &bits, const sink &out) const noexcept {
38 if (prefix) {
39 out.write(base == 16 ? (uppercase ? "0X" : "0x") : "0b");
40 }
41 if (bits.empty()) {
42 out.put('0');
43 return;
44 }
45
46 if (base == 2) {
47 for (std::size_t index = bits.size(); index != 0; --index) {
48 out.put(bits.test(index - 1) ? '1' : '0');
49 }
50 return;
51 }
52
53 const auto &digits = uppercase ? detail::hex_digits_upper : detail::hex_digits_lower;
54 const std::size_t nibble_count = (bits.size() + 3) / 4;
55 for (std::size_t nibble = nibble_count; nibble != 0; --nibble) {
56 unsigned value = 0;
57 for (unsigned bit = 0; bit < 4; ++bit) {
58 const std::size_t index = (nibble - 1) * 4 + bit;
59 if (index < bits.size() && bits.test(index)) {
60 value |= 1U << bit;
61 }
62 }
63 out.put(digits[value]);
64 }
65 }
66};
67
68template <typename IntType> struct formatter<boost::rational<IntType>> {
69 microfmt::string_view forwarded_spec{};
70
71 constexpr void parse(format_parse_context &ctx) noexcept { forwarded_spec = ctx.spec(); }
72
73 void format(const boost::rational<IntType> &value, const sink &out) const noexcept {
74 formatter<IntType> integer_formatter;
75 format_parse_context integer_context(forwarded_spec);
76 integer_formatter.parse(integer_context);
77 integer_formatter.format(value.numerator(), out);
78 out.put('/');
79 integer_formatter.format(value.denominator(), out);
80 }
81};
82
83template <> struct formatter<boost::logic::tribool> {
84 constexpr void parse(format_parse_context &) noexcept {}
85
86 void format(boost::logic::tribool value, const sink &out) const noexcept {
87 if (boost::logic::indeterminate(value)) {
88 out.write("indeterminate");
89 } else {
90 out.write(value ? "true" : "false");
91 }
92 }
93};
94
95} // namespace microfmt
Definition microfmt.hpp:881
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
constexpr bitfield_view bits(uint32_t raw_val, span< const bit_field > fields, bool show_raw_hex=true, microfmt::string_view sep=" | ") noexcept
Definition bitfield.hpp:36
void format(const boost::dynamic_bitset< Block, Allocator > &bits, const sink &out) const noexcept
Definition boost_values.hpp:37
constexpr void parse(format_parse_context &ctx) noexcept
Definition boost_values.hpp:24
void format(boost::logic::tribool value, const sink &out) const noexcept
Definition boost_values.hpp:86
constexpr void parse(format_parse_context &) noexcept
Definition boost_values.hpp:84
constexpr void parse(format_parse_context &ctx) noexcept
Definition boost_values.hpp:71
void format(const boost::rational< IntType > &value, const sink &out) const noexcept
Definition boost_values.hpp:73
Definition microfmt.hpp:985