Jump to content

Recommended Posts

http://trac.wildfiregames.com/ticket/495

I wrote a function that I think takes care of the basic problem, but I'm probably doing a number of things incorrectly, at least style-wise if not logic-wise.

For instance I'm not sure that I should be sending all the output to std::cout, and whether I should be calling the exit() function rather than throwing an exception or something.

Also, setenv isn't thread safe, but maybe that's not a concern in the init code? I just don't know enough yet to know.

So, I'm going to try and take a look at some of the source code and hopefully I'll learn some more, but in the mean time, if anyone would like to look at my code here, and feel free to offer any suggestions whatsoever, I'd appreciate it.


void SetDefaultIfLocaleInvalid()
{
// I don't believe $LANGUAGE needs to be included because it isn't checked
// by setlocale() nor std::locale::locale(const chr*).
// LC_ALL is checked first, and LANG last.
const char* const LocaleEnvVars[] = {"LC_ALL", "LC_COLLATE",
"LC_CTYPE", "LC_MONETARY",
"LC_NUMERIC", "LC_TIME",
"LC_MESSAGES", "LANG"};
const size_t SZ = sizeof LocaleEnvVars / sizeof *LocaleEnvVars;

try
{
// this constructor is similar to setlocale(LC_ALL, ""),
// but instead of returning NULL, it throws runtime_error
// when the first locale env variable found contains an invalid value
std::locale::locale("");
}
catch (std::runtime_error& e)
{
std::cout << "Warning: Invalid Locale Settings:\n";
for (size_t i = 0; i < SZ; i++)
{
std::cout << "\t\t" << LocaleEnvVars[i] << "=";

if (char* envval = getenv(LocaleEnvVars[i]))
{
std::cout << "\"" << envval << "\"";
}
else
{
std::cout << "(unset)";
}

std::cout << std::endl;
}//end for i

// The Boost filesystem library uses std::locale::locale("")
// so I believe we should set the LC_ALL env variable to something
// appropriate, std::locale::classic().name() (should be "C")
// seems best to me.
// We should set LC_ALL since it overrides LANG
if (setenv("LC_ALL", std::locale::classic().name().c_str(), 1))
{
std::cout << "Error: Unable to set LC_ALL env variable." << std::endl;
exit(EXIT_FAILURE);
}

std::cout << "\tSetting LC_ALL env variable to: "
<< std::locale::classic().name() << std::endl;

} // end catch

return;
}

Link to comment
Share on other sites

The logic looks sensible to me ;)

For serious errors, use debug_warn(L"Unable to set LC_ALL env variable"); - that currently prints to stdout, but in the future we'll have to make it do a GUI dialog box (for people who don't run from a terminal), so that's the best thing to use for unexpected errors that the user needs to be told about.

For warnings, use LOGWARNING (which writes to stdout and the log file and the in-game console). For constructing a complex message, it might be easiest to use a std::stringstream in place of std::cout and then do a single LOGWARNING(L"%hs", stream.str().c_str()).

Instead of computing SZ, use ARRAY_SIZE(LocaleEnvVars).

We don't use threads much (I can only remember the one for file monitoring) and we can do this locale check before starting any of them, so that'll be fine.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...