- Refactored fennec::format to use to_chars for ints. floats TODO but will also use to_chars.
This commit is contained in:
@@ -247,9 +247,13 @@ add_library(fennec STATIC
|
||||
|
||||
# format ===============================================================================================================
|
||||
include/fennec/format/format.h
|
||||
include/fennec/format/detail/_format.h
|
||||
include/fennec/format/format_arg.h
|
||||
include/fennec/format/formatter.h
|
||||
include/fennec/format/charconv.h
|
||||
|
||||
include/fennec/format/detail/_format.h
|
||||
|
||||
source/format/charconv.cpp
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -49,9 +49,11 @@ Some main areas where the engine strays from the GNU standard includes the follo
|
||||
|
||||
* [Section 4.7, Standards for Graphical Interfaces](https://www.gnu.org/prep/standards/html_node/Graphical-Interfaces.html).
|
||||
fennec provides an implementation for X11, however it does not use the GTK toolkit.
|
||||
- [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html)
|
||||
- [Section 5.1, Formatting Your Source Code](https://www.gnu.org/prep/standards/html_node/index.html).
|
||||
fennec uses Allman (BSD) for namespaces, otherwise K&R.
|
||||
* [Section 6.1, GNU Manuals](https://www.gnu.org/prep/standards/html_node/GNU-Manuals.html)
|
||||
fennec does not use Texinfo and instead uses Doxygen. Otherwise, it follows the other standards of this section.
|
||||
* [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html)
|
||||
- [Section 7, The Release Process](https://www.gnu.org/prep/standards/html_node/Managing-Releases.html)
|
||||
fennec follows most of the conventions in this section, however the build system used is CMake and not
|
||||
Makefile. CMake, although overwhelming at first, is much more friendly to those who are learning build systems for the first time.
|
||||
|
||||
|
||||
@@ -27,4 +27,5 @@ fennec_add_definitions(
|
||||
FENNEC_COMPILER_GCC=1
|
||||
FENNEC_NO_INLINE=[[gnu::noinline]]
|
||||
FENNEC_FUNCTION_NAME=__PRETTY_FUNCTION__
|
||||
RYU_ONLY_64_BIT_OPS
|
||||
)
|
||||
|
||||
67
include/fennec/format/charconv.h
Normal file
67
include/fennec/format/charconv.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file charconv.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_FORMAT_CHARCONV_H
|
||||
#define FENNEC_FORMAT_CHARCONV_H
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
char* to_chars(char* first, char* last, char x, int base);
|
||||
char* to_chars(char* first, char* last, signed char x, int base);
|
||||
char* to_chars(char* first, char* last, unsigned char x, int base);
|
||||
|
||||
char* to_chars(char* first, char* last, signed short x, int base);
|
||||
char* to_chars(char* first, char* last, unsigned short x, int base);
|
||||
|
||||
char* to_chars(char* first, char* last, signed int x, int base);
|
||||
char* to_chars(char* first, char* last, unsigned int x, int base);
|
||||
|
||||
char* to_chars(char* first, char* last, signed long x, int base);
|
||||
char* to_chars(char* first, char* last, unsigned long x, int base);
|
||||
|
||||
char* to_chars(char* first, char* last, signed long long x, int base);
|
||||
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
||||
|
||||
char* to_chars(char* first, char* last, signed long long x, int base);
|
||||
char* to_chars(char* first, char* last, unsigned long long x, int base);
|
||||
|
||||
char* to_chars(char* first, char* last, float x);
|
||||
char* to_chars(char* first, char* last, float x, char fmt);
|
||||
char* to_chars(char* first, char* last, float x, char fmt, int precision);
|
||||
|
||||
char* to_chars(char* first, char* last, double x);
|
||||
char* to_chars(char* first, char* last, double x, char fmt);
|
||||
char* to_chars(char* first, char* last, double x, char fmt, int precision);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_FORMAT_CHARCONV_H
|
||||
@@ -45,10 +45,12 @@ string format(const cstring& str, ArgsT&&...args) {
|
||||
static constexpr format_arg default_fmt = {
|
||||
.fill = ' ',
|
||||
.align = '\0', // default to locale
|
||||
.sign = '\0', // default to sign only for negative numbers
|
||||
.sign = '\0', // default to sign only for negative numbers, gets handled later in code
|
||||
.alt = false, // default no prefix
|
||||
.upper = false,
|
||||
.width = 0,
|
||||
.precision = 6, // default to 6 sigfigs
|
||||
.base = 10,
|
||||
.type = '\0',
|
||||
};
|
||||
|
||||
@@ -119,6 +121,7 @@ string format(const cstring& str, ArgsT&&...args) {
|
||||
|
||||
// early return case for no colon
|
||||
if (colon > end) {
|
||||
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||
res += argarray.format(arg, fmt);
|
||||
i = end + 1;
|
||||
continue;
|
||||
@@ -146,12 +149,72 @@ string format(const cstring& str, ArgsT&&...args) {
|
||||
assert(spec < str.length() - 1 and str[spec+1] == '}', "fennec::format syntax error, mismatched '{}'");
|
||||
|
||||
// check type
|
||||
if (detail::_isfmt_t(str[spec])) {
|
||||
switch (str[spec]) {
|
||||
default: break;
|
||||
|
||||
case 's': case '?': // strings
|
||||
case 'c': // char
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
|
||||
case 'd': // decimal
|
||||
fmt.base = 10;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
case 'B': // binary
|
||||
fmt.upper = true; [[fallthrough]];
|
||||
case 'b':
|
||||
fmt.base = 2;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
case 'o': // octal
|
||||
fmt.base = 8;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
case 'X': // hex
|
||||
fmt.upper = true; [[fallthrough]];
|
||||
case 'x':
|
||||
fmt.base = 16;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
|
||||
case 'A':
|
||||
fmt.upper = true; [[fallthrough]];
|
||||
case 'a': // float hex
|
||||
fmt.base = 16;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
case 'E': // scientific notation
|
||||
fmt.upper = true; [[fallthrough]];
|
||||
case 'e':
|
||||
fmt.base = 16;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
case 'F': // fixed precision
|
||||
fmt.upper = true; [[fallthrough]];
|
||||
case 'f':
|
||||
fmt.base = 10;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
|
||||
case 'G': // general precision
|
||||
fmt.upper = true; [[fallthrough]];
|
||||
case 'g':
|
||||
fmt.base = 10;
|
||||
fmt.type = str[spec--];
|
||||
break;
|
||||
}
|
||||
|
||||
// early return
|
||||
if (spec == colon) {
|
||||
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||
res += argarray.format(arg, fmt);
|
||||
i = end + 1;
|
||||
continue;
|
||||
@@ -218,6 +281,7 @@ string format(const cstring& str, ArgsT&&...args) {
|
||||
|
||||
// early return
|
||||
if (spec == colon) {
|
||||
fmt.sign = fmt.sign == '\0' ? '-' : fmt.sign;
|
||||
res += argarray.format(arg, fmt);
|
||||
i = end + 1;
|
||||
continue;
|
||||
|
||||
@@ -39,8 +39,9 @@ namespace fennec
|
||||
struct format_arg {
|
||||
char fill;
|
||||
char align, sign;
|
||||
bool alt;
|
||||
bool alt, upper;
|
||||
size_t width, precision;
|
||||
size_t base;
|
||||
char type;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#ifndef FENNEC_FORMAT_FORMATTER_H
|
||||
#define FENNEC_FORMAT_FORMATTER_H
|
||||
|
||||
#include <fennec/format/charconv.h>
|
||||
#include <fennec/string/string.h>
|
||||
#include <fennec/format/format_arg.h>
|
||||
|
||||
@@ -80,115 +81,66 @@ struct formatter<string> {
|
||||
template<typename IntT> requires(is_integral_v<IntT> and not is_bool_v<IntT>)
|
||||
struct formatter<IntT> {
|
||||
string operator()(const format_arg& fmt, IntT x) {
|
||||
static constexpr char lowdigits[] = "0123456789abcdef";
|
||||
static constexpr char highdigits[] = "0123456789ABCDEF";
|
||||
bool neg = x < 0; x = fennec::abs(x);
|
||||
const char* digits = lowdigits;
|
||||
string res;
|
||||
string pre;
|
||||
char digits[128] = {};
|
||||
auto chk = fennec::to_chars(digits, digits + sizeof(digits), fennec::abs(x), fmt.base);
|
||||
assertf(chk != nullptr, "fennec::format error, to_chars error");
|
||||
size_t len = chk - digits;
|
||||
|
||||
size_t base;
|
||||
switch (fmt.type) {
|
||||
// decimal
|
||||
default:
|
||||
assertf(false, "invalid format type for integral value");
|
||||
[[fallthrough]];
|
||||
case '\0': case 'd':
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
// binary
|
||||
case 'B':
|
||||
pre = "0B";
|
||||
base = 2;
|
||||
break;
|
||||
case 'b':
|
||||
pre = "0b";
|
||||
base = 2;
|
||||
break;
|
||||
|
||||
// octal
|
||||
case 'o':
|
||||
pre = "0";
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
// hex
|
||||
case 'X':
|
||||
digits = highdigits;
|
||||
pre = "0X";
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
pre = "0x";
|
||||
base = 16;
|
||||
// handle uppercase
|
||||
if (fmt.upper) {
|
||||
for (auto& digit : digits) {
|
||||
if (digit == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// parse int
|
||||
while (x != 0) {
|
||||
res = digits[x % base] + res;
|
||||
x /= base;
|
||||
digit = toupper(digit);
|
||||
}
|
||||
}
|
||||
|
||||
// handle 0
|
||||
if (res.empty()) {
|
||||
res = '0' + res;
|
||||
}
|
||||
const bool has_sign = (x < 0 or fmt.sign != '-');
|
||||
const bool zero = fmt.fill == '0';
|
||||
const size_t prefix = fmt.alt ? (fmt.type == 'd' ? 0 : 2 - (fmt.type == 'o')) : 0;
|
||||
const size_t sgnlen = len + (zero ? has_sign + prefix : 0);
|
||||
const size_t explen = fennec::max(sgnlen, fmt.width) + (zero ? 0 : has_sign + prefix);
|
||||
const size_t fill = fmt.width > sgnlen ? fmt.width - sgnlen : 0;
|
||||
size_t sign = 0;
|
||||
|
||||
// add prefix unless fill is '0'
|
||||
if (fmt.alt and fmt.fill != '0' and (base != 8 or res[0] != '0')) {
|
||||
res = pre + res;
|
||||
}
|
||||
string res = string(explen);
|
||||
|
||||
// fill
|
||||
size_t fill = fmt.alt ? fmt.width - pre.length() : fmt.width;
|
||||
if (fill > 0) {
|
||||
switch (fmt.align) {
|
||||
// align left
|
||||
case '<':
|
||||
while (res.size() < fill) {
|
||||
res += fmt.fill == '0' ? ' ' : fmt.fill;
|
||||
}
|
||||
memcpy(res.data() + has_sign + prefix, digits, len);
|
||||
memset(res.data() + has_sign + prefix + len, fmt.fill == '0' ? ' ' : fmt.fill, fill);
|
||||
break;
|
||||
|
||||
// align right
|
||||
case '>': default:
|
||||
while (res.size() < fill) {
|
||||
res = fmt.fill + res;
|
||||
}
|
||||
case '>': case '\0':
|
||||
memcpy(res.data() + explen - len, digits, len);
|
||||
sign = fmt.fill == '0' ? 0 : explen - len - 1 - prefix;
|
||||
memset(res.data(), fmt.fill, explen - len);
|
||||
break;
|
||||
|
||||
// align
|
||||
case '^':
|
||||
bool rr = true;
|
||||
while (res.size() < fill) {
|
||||
if (rr) {
|
||||
res += fmt.fill == '0' ? ' ' : fmt.fill;
|
||||
size_t bef = fill / 2 + has_sign + prefix;
|
||||
size_t aft = explen - bef;
|
||||
memcpy(res.data() + bef, digits, len);
|
||||
sign = fmt.fill == '0' ? 0 : bef - 1 - prefix;
|
||||
memset(res.data(), fmt.fill, bef);
|
||||
memset(res.data() + bef + len, fmt.fill == '0' ? ' ' : fmt.fill, aft);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
res = fmt.fill + res;
|
||||
}
|
||||
rr = !rr;
|
||||
}
|
||||
break;
|
||||
memcpy(res.data() + has_sign + prefix, digits, len);
|
||||
}
|
||||
|
||||
// add prefix after filled 0s
|
||||
if (fmt.alt and fmt.fill == '0') {
|
||||
res = pre + res;
|
||||
if (has_sign) {
|
||||
res[sign] = (x < 0) ? '-' : fmt.sign;
|
||||
}
|
||||
|
||||
// add sign
|
||||
switch (fmt.sign) {
|
||||
case '+':
|
||||
res = (neg ? '-' : '+') + res;
|
||||
break;
|
||||
case ' ':
|
||||
res = (neg ? '-' : ' ') + res;
|
||||
break;
|
||||
case '-': default:
|
||||
if (neg) res = '-' + res;
|
||||
break;
|
||||
if (prefix) {
|
||||
res[sign + has_sign] = '0';
|
||||
if (fmt.type != 'o') {
|
||||
res[sign + has_sign + 1] = fmt.type;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -206,6 +158,22 @@ struct formatter<BoolT> {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename FloatT> requires(is_floating_point_v<FloatT>)
|
||||
struct formatter<FloatT> {
|
||||
string operator()(const format_arg& fmt, FloatT x) {
|
||||
|
||||
// nan & inf cases
|
||||
if (isnan(x)) {
|
||||
return string("nan");
|
||||
}
|
||||
if (isinf(x)) {
|
||||
return string("inf");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_FORMAT_FORMATTER_H
|
||||
@@ -440,7 +440,10 @@ public:
|
||||
///
|
||||
/// \brief Default Destructor, releases the memory block if still present
|
||||
constexpr ~allocation() noexcept {
|
||||
if (_data) _alloc.deallocate(_data);
|
||||
if (_data) {
|
||||
_alloc.deallocate(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
147
source/format/charconv.cpp
Normal file
147
source/format/charconv.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file charconv.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#define __cpp_lib_to_chars
|
||||
#include <charconv>
|
||||
#include <system_error>
|
||||
#include <fennec/format/charconv.h>
|
||||
#include <fennec/lang/assert.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
char* to_chars(char* first, char* last, char x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
char* to_chars(char* first, char* last, signed char x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
char* to_chars(char* first, char* last, unsigned char x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, signed short x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
char* to_chars(char* first, char* last, unsigned short x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, signed int x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
char* to_chars(char* first, char* last, unsigned int x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, signed long x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
char* to_chars(char* first, char* last, unsigned long x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, signed long long x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
char* to_chars(char* first, char* last, unsigned long long x, int base) {
|
||||
auto res = std::to_chars(first, last, x, base);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
|
||||
std::chars_format ctofmt(char c) {
|
||||
switch (c) {
|
||||
default: return std::chars_format::general;
|
||||
case 'a': case 'A': return std::chars_format::hex;
|
||||
case 'f': case 'F': return std::chars_format::fixed;
|
||||
case 'e': case 'E': return std::chars_format::scientific;
|
||||
}
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, float x) {
|
||||
auto res = std::to_chars(first, last, x);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, float x, char fmt) {
|
||||
auto res = std::to_chars(first, last, x, ctofmt(fmt));
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, float x, char fmt, int precision) {
|
||||
auto res = std::to_chars(first, last, x, ctofmt(fmt), precision);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
|
||||
char* to_chars(char* first, char* last, double x) {
|
||||
auto res = std::to_chars(first, last, x);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, double x, char fmt) {
|
||||
auto res = std::to_chars(first, last, x, ctofmt(fmt));
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
char* to_chars(char* first, char* last, double x, char fmt, int precision) {
|
||||
auto res = std::to_chars(first, last, x, ctofmt(fmt), precision);
|
||||
assertf(res.ec == std::errc(), std::make_error_code(res.ec).message().c_str());
|
||||
return res.ptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -72,6 +72,15 @@ inline void fennec_test_format() {
|
||||
|
||||
fennec_test_spacer(1);
|
||||
|
||||
fennec_test_run(fennec::format("{:#06d}", -15), string("-00015"));
|
||||
fennec_test_run(fennec::format("{:#06x}", -15), string("-0x00f"));
|
||||
fennec_test_run(fennec::format("{:#06X}", -15), string("-0X00F"));
|
||||
fennec_test_run(fennec::format("{:#06o}", -15), string("-00017"));
|
||||
fennec_test_run(fennec::format("{:#06b}", -15), string("-0b1111"));
|
||||
fennec_test_run(fennec::format("{:#06B}", -15), string("-0B1111"));
|
||||
|
||||
fennec_test_spacer(1);
|
||||
|
||||
fennec_test_run(fennec::format("{},{}", true, false), string("true,false"));
|
||||
fennec_test_run(fennec::format("{:#06b},{:#06b}", true, false), string("0b0001,0b0000"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user