Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Booster read/write locale dependency #2891

Merged
merged 3 commits into from
Mar 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions include/LightGBM/utils/locale_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*!
* Copyright (c) 2020 Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE file in the project root for license information.
*/
#ifndef LIGHTGBM_LOCALE_CONTEXT_H_
#define LIGHTGBM_LOCALE_CONTEXT_H_

#include <clocale>
#include <locale>

/*!
* Class to override the program global locale during this object lifetime.
* After the object is destroyed, the locale is returned to its original state.
*
* @warn This is not thread-safe.
*/
class LocaleContext {
public:
/*!
* Override the current program global locale during this object lifetime.
*
* @param target_locale override the locale to this locale setting.
* @warn This is not thread-safe.
* @note This doesn't override cout, cerr, etc.
*/
explicit LocaleContext(const char* target_locale = "C") {
std::locale::global(std::locale(target_locale));
}

/*!
* Restores the old global locale.
*/
~LocaleContext() {
std::locale::global(_saved_global_locale);
}
private:
std::locale _saved_global_locale; //!< Stores global locale at initialization.
};

#endif // LIGHTGBM_LOCALE_CONTEXT_H_
6 changes: 6 additions & 0 deletions src/c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <LightGBM/objective_function.h>
#include <LightGBM/prediction_early_stop.h>
#include <LightGBM/utils/common.h>
#include <LightGBM/utils/locale_context.h>
#include <LightGBM/utils/log.h>
#include <LightGBM/utils/openmp_wrapper.h>
#include <LightGBM/utils/random.h>
Expand Down Expand Up @@ -1208,6 +1209,7 @@ int LGBM_BoosterCreateFromModelfile(
int* out_num_iterations,
BoosterHandle* out) {
API_BEGIN();
LocaleContext withLocaleContext("C");
auto ret = std::unique_ptr<Booster>(new Booster(filename));
*out_num_iterations = ret->GetBoosting()->GetCurrentIteration();
*out = ret.release();
Expand All @@ -1219,6 +1221,7 @@ int LGBM_BoosterLoadModelFromString(
int* out_num_iterations,
BoosterHandle* out) {
API_BEGIN();
LocaleContext withLocaleContext("C");
auto ret = std::unique_ptr<Booster>(new Booster(nullptr));
ret->LoadModelFromString(model_str);
*out_num_iterations = ret->GetBoosting()->GetCurrentIteration();
Expand Down Expand Up @@ -1631,6 +1634,7 @@ int LGBM_BoosterSaveModel(BoosterHandle handle,
int num_iteration,
const char* filename) {
API_BEGIN();
LocaleContext withLocaleContext("C");
Booster* ref_booster = reinterpret_cast<Booster*>(handle);
ref_booster->SaveModelToFile(start_iteration, num_iteration, filename);
API_END();
Expand All @@ -1643,6 +1647,7 @@ int LGBM_BoosterSaveModelToString(BoosterHandle handle,
int64_t* out_len,
char* out_str) {
API_BEGIN();
LocaleContext withLocaleContext("C");
Booster* ref_booster = reinterpret_cast<Booster*>(handle);
std::string model = ref_booster->SaveModelToString(start_iteration, num_iteration);
*out_len = static_cast<int64_t>(model.size()) + 1;
Expand All @@ -1659,6 +1664,7 @@ int LGBM_BoosterDumpModel(BoosterHandle handle,
int64_t* out_len,
char* out_str) {
API_BEGIN();
LocaleContext withLocaleContext("C");
Booster* ref_booster = reinterpret_cast<Booster*>(handle);
std::string model = ref_booster->DumpModel(start_iteration, num_iteration);
*out_len = static_cast<int64_t>(model.size()) + 1;
Expand Down