diff --git a/vna_qt/mainwindow.C b/vna_qt/mainwindow.C index 4c11b53..825682f 100644 --- a/vna_qt/mainwindow.C +++ b/vna_qt/mainwindow.C @@ -403,22 +403,23 @@ void MainWindow::updatePortExtension() { static string calFileVer = "calFileVersion 1"; string MainWindow::serializeCalibration(const CalibrationInfo &cal) { + scopedCLocale _locale; // use standard number formatting string tmp; tmp.append(calFileVer); tmp += '\n'; tmp.append(cal.calName + "\n"); - tmp.append(to_string(cal.nPoints)+" "+to_string(cal.startFreqHz)+" "+to_string(cal.stepFreqHz)); - tmp.append(" "+to_string(cal.attenuation1)+" "+to_string(cal.attenuation2)); + saprintf(tmp, "%d %f %f ", cal.nPoints, cal.startFreqHz, cal.stepFreqHz); + saprintf(tmp, "%d %d", cal.attenuation1, cal.attenuation2); tmp += '\n'; for(auto& calstd:cal.measurements) { + if(calstd.first.length() == 0) + continue; tmp.append(calstd.first); tmp += '\n'; for(const VNARawValue& val:calstd.second) { int sz=val.rows()*val.cols(); for(int i=0;i=0 && len <= bytesToAllocate) { - dst.resize(originalLen+len); - return len; - } - if(len<=0) bytesToAllocate*=2; - else bytesToAllocate = len; - } -} - string serializeTouchstone(vector > data, double startFreqHz, double stepFreqHz) { + scopedCLocale _locale; // use standard number formatting string res; res += "# MHz S MA R 50\n"; saprintf(res,"! freq S11 \n"); @@ -52,6 +28,7 @@ string serializeTouchstone(vector > data, double startFreqHz, do } string serializeTouchstone(vector data, double startFreqHz, double stepFreqHz) { + scopedCLocale _locale; // use standard number formatting string res; res += "# MHz S MA R 50\n"; saprintf(res,"! freq S11 S21 S12 S22 \n"); @@ -72,6 +49,7 @@ string serializeTouchstone(vector data, double startFreqHz, double st void parseTouchstone(string data, int& nPorts, map &results) { + scopedCLocale _locale; // use standard number formatting istringstream iss(data); string line; diff --git a/vna_qt/utility.H b/vna_qt/utility.H index 174d320..77a1272 100644 --- a/vna_qt/utility.H +++ b/vna_qt/utility.H @@ -9,9 +9,31 @@ #include #include #include +#include + + +#if __cplusplus < 201103L + #error This library needs at least a C++11 compliant compiler +#endif using namespace std; +// when this class is instantiated, the program locale is set to C +class scopedCLocale { +public: + bool _shouldRevert = true; + scopedCLocale() { + if(strcmp("C", setlocale(LC_ALL, NULL)) == 0) + _shouldRevert = false; + setlocale(LC_ALL, "C"); + } + ~scopedCLocale() { + if(_shouldRevert) + setlocale(LC_ALL, ""); + } +}; + + inline QString qs(const string& s) { return QString::fromStdString(s); } @@ -74,6 +96,28 @@ inline string ssprintf(int maxLen, const char* fmt, ...) { tmp.resize(len); return tmp; } + +// append to dst +inline int saprintf(string& dst, const char* fmt, ...) { + int bytesToAllocate=32; + int originalLen=dst.length(); + while(true) { + dst.resize(originalLen+bytesToAllocate); + va_list args; + va_start(args, fmt); + // ONLY WORKS WITH C++11!!!!!!!! + // .data() does not guarantee enough space for the null byte before c++11 + int len = vsnprintf((char*)dst.data()+originalLen, bytesToAllocate+1, fmt, args); + va_end(args); + if(len>=0 && len <= bytesToAllocate) { + dst.resize(originalLen+len); + return len; + } + if(len<=0) bytesToAllocate*=2; + else bytesToAllocate = len; + } +} + inline string sstrftime(const char *format, const struct tm &tm) { char buf[256] = {0}; strftime(buf, 256, format, &tm);