From aec6b3361b3de8391177261469da6edafd39a080 Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Fri, 13 Feb 2015 12:56:43 +0100
Subject: Fix locale sensitive float parsing/printing.

---
 src/Makefile.am         |  1 +
 src/drumgizmo.cc        |  6 ++--
 src/instrumentparser.cc |  8 +++--
 src/nolocale.h          | 85 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 95 insertions(+), 5 deletions(-)
 create mode 100644 src/nolocale.h

(limited to 'src')

diff --git a/src/Makefile.am b/src/Makefile.am
index b9b0aae..df9f4ca 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ EXTRA_DIST = \
 	midimapparser.h \
 	midimapper.h \
 	mutex.h \
+	nolocale.h \
 	path.h \
 	powerlist.h \
 	rangemap.h \
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc
index 6b48cda..5d7de70 100644
--- a/src/drumgizmo.cc
+++ b/src/drumgizmo.cc
@@ -43,6 +43,8 @@
 #include "configuration.h"
 #include "configparser.h"
 
+#include "nolocale.h"
+
 DrumGizmo::DrumGizmo(AudioOutputEngine *o, AudioInputEngine *i)
   : MessageReceiver(MSGRCV_ENGINE),
     loader(), oe(o), ie(i)
@@ -451,7 +453,7 @@ void DrumGizmo::setSamplerate(int samplerate)
 std::string float2str(float a)
 {
   char buf[256];
-  sprintf(buf, "%f", a);
+  snprintf_nol(buf, sizeof(buf) - 1, "%f", a);
   return buf;
 }
 
@@ -463,7 +465,7 @@ std::string bool2str(bool a)
 float str2float(std::string a)
 {
   if(a == "") return 0.0;
-  return atof(a.c_str());
+  return atof_nol(a.c_str());
 }
 
 std::string DrumGizmo::configString()
diff --git a/src/instrumentparser.cc b/src/instrumentparser.cc
index 0889d74..1f25bc7 100644
--- a/src/instrumentparser.cc
+++ b/src/instrumentparser.cc
@@ -33,6 +33,8 @@
 
 #include "path.h"
 
+#include "nolocale.h"
+
 InstrumentParser::InstrumentParser(const std::string &file, Instrument &i)
   : instrument(i)
 {
@@ -84,7 +86,7 @@ void InstrumentParser::startTag(std::string name,
     if(attr.find("power") == attr.end()) {
       power = -1; 
     } else {
-      power = atof(attr["power"].c_str());  
+      power = atof_nol(attr["power"].c_str());
       DEBUG(instrparser, "Instrument power set to %f\n", power);
     }
     
@@ -136,8 +138,8 @@ void InstrumentParser::startTag(std::string name,
       return;
     }
 
-    lower = atof(attr["lower"].c_str());
-    upper = atof(attr["upper"].c_str());
+    lower = atof_nol(attr["lower"].c_str());
+    upper = atof_nol(attr["upper"].c_str());
   }
 
   if(name == "sampleref") {
diff --git a/src/nolocale.h b/src/nolocale.h
new file mode 100644
index 0000000..ac83dda
--- /dev/null
+++ b/src/nolocale.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ *            nolocale.h
+ *
+ *  Fri Feb 13 12:48:10 CET 2015
+ *  Copyright 2015 Bent Bisballe Nyeng
+ *  deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ *  This file is part of DrumGizmo.
+ *
+ *  DrumGizmo is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  DrumGizmo is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with DrumGizmo; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
+ */
+#ifndef __DRUMGIZMO_NOLOCALE_H__
+#define __DRUMGIZMO_NOLOCALE_H__
+
+#include <locale.h>
+#include <stdarg.h>
+
+static inline double atof_nol(const char *nptr)
+{
+	double res;
+	locale_t new_locale, prev_locale;
+
+	new_locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
+	prev_locale = uselocale(new_locale);
+
+	res = atof(nptr);
+
+	uselocale(prev_locale);
+	freelocale(new_locale);
+
+	return res;
+}
+
+static inline int sprintf_nol(char *str, const char *format, ...)
+{
+	locale_t new_locale, prev_locale;
+
+	new_locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
+	prev_locale = uselocale(new_locale);
+
+  va_list vl;
+  va_start(vl, format);
+  int ret = vsprintf(str, format, vl);
+  va_end(vl);
+
+	uselocale(prev_locale);
+	freelocale(new_locale);
+
+  return ret;
+}
+
+static inline int snprintf_nol(char *str, size_t size, const char *format, ...)
+{
+	locale_t new_locale, prev_locale;
+
+	new_locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
+	prev_locale = uselocale(new_locale);
+
+  va_list vl;
+  va_start(vl, format);
+  int ret = vsnprintf(str, size, format, vl);
+  va_end(vl);
+
+	uselocale(prev_locale);
+	freelocale(new_locale);
+
+  return ret;
+}
+
+#endif/*__DRUMGIZMO_NOLOCALE_H__*/
-- 
cgit v1.2.3