Fix issues with OBJ loading on macOS Sonoma

This commit is contained in:
Lukas Matena 2023-10-16 16:28:29 +02:00
parent 306374129d
commit 623e9d5cb4

View File

@ -11,9 +11,24 @@
#include "objparser.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include "fast_float/fast_float.h"
namespace ObjParser {
// To fix issues with obj loading on macOS Sonoma, we use the following function instead of strtod that
// was used before. Apparently the locales are not handled as they should. We already saw this before in
// https://github.com/prusa3d/PrusaSlicer/issues/10380.
static double strtod_clocale(const char* str, char const** str_end)
{
double val = 0.;
auto [pend, ec] = fast_float::from_chars(str, *str_end, val);
if (pend != str && ec != std::errc::result_out_of_range)
*str_end = pend; // success
else
*str_end = str;
return val;
}
static bool obj_parseline(const char *line, ObjData &data)
{
#define EATWS() while (*line == ' ' || *line == '\t') ++ line
@ -45,15 +60,15 @@ static bool obj_parseline(const char *line, ObjData &data)
if (c2 != ' ' && c2 != '\t')
return false;
EATWS();
char *endptr = 0;
double u = strtod(line, &endptr);
const char *endptr = 0;
double u = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t'))
return false;
line = endptr;
EATWS();
double v = 0;
if (*line != 0) {
v = strtod(line, &endptr);
v = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
@ -61,7 +76,7 @@ static bool obj_parseline(const char *line, ObjData &data)
}
double w = 0;
if (*line != 0) {
w = strtod(line, &endptr);
w = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
@ -82,18 +97,18 @@ static bool obj_parseline(const char *line, ObjData &data)
if (c2 != ' ' && c2 != '\t')
return false;
EATWS();
char *endptr = 0;
double x = strtod(line, &endptr);
const char *endptr = 0;
double x = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t'))
return false;
line = endptr;
EATWS();
double y = strtod(line, &endptr);
double y = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t'))
return false;
line = endptr;
EATWS();
double z = strtod(line, &endptr);
double z = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
@ -112,20 +127,20 @@ static bool obj_parseline(const char *line, ObjData &data)
if (c2 != ' ' && c2 != '\t')
return false;
EATWS();
char *endptr = 0;
double u = strtod(line, &endptr);
const char *endptr = 0;
double u = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
EATWS();
double v = strtod(line, &endptr);
double v = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
EATWS();
double w = 0;
if (*line != 0) {
w = strtod(line, &endptr);
w = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
@ -144,25 +159,25 @@ static bool obj_parseline(const char *line, ObjData &data)
if (c2 != ' ' && c2 != '\t')
return false;
EATWS();
char *endptr = 0;
double x = strtod(line, &endptr);
const char *endptr = 0;
double x = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t'))
return false;
line = endptr;
EATWS();
double y = strtod(line, &endptr);
double y = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t'))
return false;
line = endptr;
EATWS();
double z = strtod(line, &endptr);
double z = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;
EATWS();
double w = 1.0;
if (*line != 0) {
w = strtod(line, &endptr);
w = strtod_clocale(line, &endptr);
if (endptr == 0 || (*endptr != ' ' && *endptr != '\t' && *endptr != 0))
return false;
line = endptr;