mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-05 23:41:44 +00:00
ifcparse: replace std::to_chars to fix mac build (ee2b357d7)
This commit is contained in:
@@ -39,7 +39,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <charconv>
|
|
||||||
|
|
||||||
#ifdef USE_MMAP
|
#ifdef USE_MMAP
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
@@ -733,6 +732,41 @@ void IfcParse::impl::rocks_db_file_storage::remove_type_ref(IfcUtil::IfcBaseClas
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
// Shortest decimal representation of 'd' that round-trips back to the
|
||||||
|
// exact same double (like std::to_chars, or Python's repr).
|
||||||
|
// Using actual `std::to_chars` requires macOS 13.3+, so we implement this manually,
|
||||||
|
// until we drop support for older targets.
|
||||||
|
//
|
||||||
|
// Mirrors libstdc++'s notation-choice bounds (floating_to_chars.cc,
|
||||||
|
// __floating_to_chars_shortest) to pick whichever of fixed/scientific is
|
||||||
|
// shorter for a given digit count and exponent.
|
||||||
|
static inline void format_double_shortest(char (&buf)[64], double d) {
|
||||||
|
char sci[64];
|
||||||
|
int mantissa_length = 17;
|
||||||
|
for (int prec = 1; prec <= 17; ++prec) {
|
||||||
|
snprintf(sci, sizeof(sci), "%.*e", prec - 1, d);
|
||||||
|
if (strtod(sci, nullptr) == d) {
|
||||||
|
mantissa_length = prec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const char* exp_str = strchr(sci, 'e');
|
||||||
|
const int scientific_exponent = exp_str ? atoi(exp_str + 1) : 0;
|
||||||
|
const int fd_exponent = scientific_exponent - (mantissa_length - 1);
|
||||||
|
int lower_bound = -(mantissa_length + 3);
|
||||||
|
int upper_bound = 5;
|
||||||
|
if (mantissa_length == 1) {
|
||||||
|
++lower_bound;
|
||||||
|
--upper_bound;
|
||||||
|
}
|
||||||
|
if (fd_exponent >= lower_bound && fd_exponent <= upper_bound) {
|
||||||
|
const int fixed_precision = fd_exponent < 0 ? -fd_exponent : 0;
|
||||||
|
snprintf(buf, 64, "%.*f", fixed_precision, d);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, 64, "%.*e", mantissa_length - 1, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class StringBuilderVisitor : public boost::static_visitor<void> {
|
class StringBuilderVisitor : public boost::static_visitor<void> {
|
||||||
private:
|
private:
|
||||||
StringBuilderVisitor(const StringBuilderVisitor&); //N/A
|
StringBuilderVisitor(const StringBuilderVisitor&); //N/A
|
||||||
@@ -759,11 +793,9 @@ namespace {
|
|||||||
// values with noise digits (0.0174532925199433 -> 0.017453292519943299),
|
// values with noise digits (0.0174532925199433 -> 0.017453292519943299),
|
||||||
// which rewrote every REAL and produced huge diffs when a file was
|
// which rewrote every REAL and produced huge diffs when a file was
|
||||||
// re-saved. See #7696.
|
// re-saved. See #7696.
|
||||||
// std::to_chars is locale-independent, so no ostringstream/imbue is
|
|
||||||
// needed here.
|
|
||||||
char buf[64];
|
char buf[64];
|
||||||
const auto res = std::to_chars(buf, buf + sizeof(buf), d);
|
format_double_shortest(buf, d);
|
||||||
const std::string str(buf, res.ptr);
|
const std::string str(buf);
|
||||||
std::string::size_type e = str.find('e');
|
std::string::size_type e = str.find('e');
|
||||||
if (e == std::string::npos) {
|
if (e == std::string::npos) {
|
||||||
e = str.find('E');
|
e = str.find('E');
|
||||||
|
|||||||
Reference in New Issue
Block a user