77#include < stdarg.h>
88#include < limits.h>
99#include < locale.h>
10+
11+ #if __unix__
12+ # include < unistd.h> // For _POSIX_VERSION
13+ #endif
14+
1015#include " svm.h"
16+
1117int libsvm_version = LIBSVM_VERSION;
1218typedef float Qfloat;
1319typedef signed char schar;
@@ -2638,16 +2644,55 @@ static const char *kernel_type_table[]=
26382644 " linear" ," polynomial" ," rbf" ," sigmoid" ," precomputed" ,NULL
26392645};
26402646
2641- int svm_save_model (const char *model_file_name, const svm_model *model)
2647+ #if _POSIX_VERSION >= 200809L
2648+
2649+ // If possible, use the thread-safe uselocale() function
2650+ typedef locale_t locale_handle;
2651+
2652+ static locale_handle set_c_locale ()
26422653{
2643- FILE *fp = fopen (model_file_name," w" );
2644- if (fp==NULL ) return -1 ;
2654+ locale_handle c_locale = newlocale (LC_ALL_MASK, " C" , 0 );
2655+ locale_handle old_locale = uselocale (c_locale);
2656+ return old_locale;
2657+ }
2658+
2659+ static void restore_locale (locale_handle locale)
2660+ {
2661+ locale_handle c_locale = uselocale (locale);
2662+ if (c_locale && c_locale != LC_GLOBAL_LOCALE) {
2663+ freelocale (c_locale);
2664+ }
2665+ }
2666+
2667+ #else
2668+
2669+ // But fall back to setlocale() if uselocale() is not available
2670+ typedef char *locale_handle;
26452671
2646- char *old_locale = setlocale (LC_ALL, NULL );
2672+ static locale_handle set_c_locale ()
2673+ {
2674+ locale_handle old_locale = setlocale (LC_ALL, NULL );
26472675 if (old_locale) {
26482676 old_locale = strdup (old_locale);
26492677 }
26502678 setlocale (LC_ALL, " C" );
2679+ return old_locale;
2680+ }
2681+
2682+ static void restore_locale (locale_handle locale)
2683+ {
2684+ setlocale (LC_ALL, locale);
2685+ free (locale);
2686+ }
2687+
2688+ #endif
2689+
2690+ int svm_save_model (const char *model_file_name, const svm_model *model)
2691+ {
2692+ FILE *fp = fopen (model_file_name," w" );
2693+ if (fp==NULL ) return -1 ;
2694+
2695+ locale_handle old_locale = set_c_locale ();
26512696
26522697 const svm_parameter& param = model->param ;
26532698
@@ -2728,8 +2773,7 @@ int svm_save_model(const char *model_file_name, const svm_model *model)
27282773 fprintf (fp, " \n " );
27292774 }
27302775
2731- setlocale (LC_ALL, old_locale);
2732- free (old_locale);
2776+ restore_locale (old_locale);
27332777
27342778 if (ferror (fp) != 0 || fclose (fp) != 0 ) return -1 ;
27352779 else return 0 ;
@@ -2878,11 +2922,7 @@ svm_model *svm_load_model(const char *model_file_name)
28782922 FILE *fp = fopen (model_file_name," rb" );
28792923 if (fp==NULL ) return NULL ;
28802924
2881- char *old_locale = setlocale (LC_ALL, NULL );
2882- if (old_locale) {
2883- old_locale = strdup (old_locale);
2884- }
2885- setlocale (LC_ALL, " C" );
2925+ locale_handle old_locale = set_c_locale ();
28862926
28872927 // read parameters
28882928
@@ -2898,8 +2938,7 @@ svm_model *svm_load_model(const char *model_file_name)
28982938 if (!read_model_header (fp, model))
28992939 {
29002940 fprintf (stderr, " ERROR: fscanf failed to read model\n " );
2901- setlocale (LC_ALL, old_locale);
2902- free (old_locale);
2941+ restore_locale (old_locale);
29032942 free (model->rho );
29042943 free (model->label );
29052944 free (model->nSV );
@@ -2971,8 +3010,7 @@ svm_model *svm_load_model(const char *model_file_name)
29713010 }
29723011 free (line);
29733012
2974- setlocale (LC_ALL, old_locale);
2975- free (old_locale);
3013+ restore_locale (old_locale);
29763014
29773015 if (ferror (fp) != 0 || fclose (fp) != 0 )
29783016 return NULL ;
0 commit comments