Replace strtod with strtof_l in C4ScriptGuiWindow::SetPositionStringProperties to avoid locale problems

(That function could still use some more love, though: Error messages and not accepting ridiculous things when parsing.)
shapetextures
Julius Michaelis 2015-10-01 19:50:05 +02:00
parent 5a2bfe40a6
commit 139dee9874
3 changed files with 18 additions and 2 deletions

View File

@ -85,6 +85,12 @@ REQUIRE_CXX_SOURCE_COMPILES("int main() { static_assert(true, \"\"); }" HAVE_STA
CHECK_CXX_SOURCE_COMPILES("#include <memory>\nint main() { auto a = std::make_unique<int>(0); }" HAVE_MAKE_UNIQUE)
REQUIRE_CXX_SOURCE_COMPILES("template<class... T> class C; int main() { return 0; }" HAVE_VARIADIC_TEMPLATES)
CHECK_CXX_SOURCE_COMPILES("#include<stdlib.h>\n#include<locale.h>\nint main() { locale_t l = newlocale(LC_ALL_MASK, \"C\", (locale_t)0); char *c; float f = strtof_l(c, &c, l);}" HAVE_STRTOF_L)
CHECK_CXX_SOURCE_COMPILES("#include<stdlib.h>\n#include<locale.h>\nint main() { locale_t l = newlocale(LC_ALL_MASK, \"C\", (locale_t)0); char *c; float f = _strtof_l(c, &c, l);}" HAVE__STRTOF_L)
if(NOT(HAVE_STRTOF_L OR HAVE__STRTOF_L))
message(SEND_ERROR "newlocale and either strtof_l or _strtof_l is required. Or a rewrite of C4ScriptGuiWindow::SetPositionStringProperties")
endif()
# g++'s libstdc++ doesn't properly support <regex> until 4.9.
# They ship a header that declares functions, but they don't ship an
# implementation for some things (like std::regex_iterator).

View File

@ -194,3 +194,7 @@
/* Include OpenAL extensions (alext.h) for sound modifiers */
#cmakedefine HAVE_ALEXT 1
/* strtof_l is defined and usable */
#cmakedefine HAVE_STRTOF_L 1
#cmakedefine HAVE__STRTOF_L 2

View File

@ -42,6 +42,11 @@
#include <C4Viewport.h>
#include <cmath>
#include <locale.h>
#include <stdlib.h>
#ifndef HAVE_STRTOF_L
#define strtof_l _strtof_l
#endif
// Adds some helpful logs for hunting control & menu based desyncs.
//#define MenuDebugLogF(...) DebugLogF(__VA_ARGS__)
@ -801,12 +806,13 @@ void C4ScriptGuiWindow::SetPositionStringProperties(const C4Value &property, C4S
const char *currentPosition = trimmedString.data();
char *nextPosition;
const char *lastPosition = trimmedString.data() + trimmedString.size();
locale_t c_loc = newlocale(LC_ALL_MASK, "C", nullptr);
while (currentPosition < lastPosition)
{
// look for next float
nextPosition = 0;
float value = static_cast<float>(strtod(currentPosition, &nextPosition));
float value = strtof_l(currentPosition, &nextPosition, c_loc);
// fail? exit right here (there must be some space left in the string for a unit, too)
if (currentPosition == nextPosition || nextPosition == 0 || nextPosition >= lastPosition) break;
@ -1557,7 +1563,7 @@ void C4ScriptGuiWindow::RequestLayoutUpdate()
return;
}
else // we are one of the multiple windows.. the root better do a full refresh
;
{}
}
// propagate to parent window
static_cast<C4ScriptGuiWindow*>(GetParent())->RequestLayoutUpdate();