darrenhoffman Posted June 9, 2010 Report Share Posted June 9, 2010 http://trac.wildfiregames.com/ticket/495I 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;} Quote Link to comment Share on other sites More sharing options...
Ykkrosh Posted June 10, 2010 Report Share Posted June 10, 2010 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.