[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master e8d7f191 05/11: Use low-level functions for l
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master e8d7f191 05/11: Use low-level functions for low-level work |
Date: |
Fri, 29 Apr 2022 11:59:33 -0400 (EDT) |
branch: master
commit e8d7f191de0432d2e00ea984bace0c3767ebfc70
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Use low-level functions for low-level work
Sometimes std::string lacks idoneity.
---
duff_fmt.hpp | 72 ++++++++++++++++++++++++++++++++----------------------------
1 file changed, 38 insertions(+), 34 deletions(-)
diff --git a/duff_fmt.hpp b/duff_fmt.hpp
index 5b9a516f..4e9c04b1 100644
--- a/duff_fmt.hpp
+++ b/duff_fmt.hpp
@@ -28,61 +28,65 @@
#include "config.hpp"
-#include <iomanip>
-#include <ios>
-#include <sstream>
-#include <stdexcept>
+#include "assert_lmi.hpp"
+#include "ssize_lmi.hpp" // sstrlen()
+
+#include <cstdio> // snprintf()
+#include <cstring> // strchr()
#include <string>
-// Reference:
-// http://groups.google.com/groups?selm=38C9B681.B8A036DF%40flash.net
+/// Format a double using thousands separators. Reference:
+/// https://groups.google.com/groups?selm=38C9B681.B8A036DF%40flash.net
+
inline std::string duff_fmt(double value)
{
+ constexpr int decimals {2}; // This will become an argument.
+
if(value < 0.0)
{
return '-' + duff_fmt(-value);
}
- std::stringstream stream;
- stream << std::setiosflags(std::ios_base::fixed) << std::setprecision(2);
- std::string s_in;
+ constexpr int buffer_size {1000};
+ char in_buf [buffer_size];
+ char out_buf[buffer_size];
- if
- ( !(stream << value)
- || !(stream >> s_in)
- || !(stream >> std::ws).eof()
- )
- {
- throw std::runtime_error("Stream error in duff_fmt.hpp .");
- }
+ char* p = in_buf;
+ char* q = out_buf;
- std::string::const_iterator sin_it(s_in.begin());
- std::string s_out;
+ // Use '#' to force a decimal point unless infinite or NaN.
+ int const length = std::snprintf(p, buffer_size, "%#.*f", decimals, value);
+ LMI_ASSERT(0 < length && length < buffer_size);
+ LMI_ASSERT(lmi::sstrlen(p) == length);
- std::string::size_type const z(s_in.find('.'));
- if(std::string::npos == z)
+ char const*const r = std::strchr(p, '.');
+ if(nullptr == r)
{
- // Infinities and NaNs have no decimal point, and need no commas.
- return s_in;
+ // Infinities and NaNs need no commas.
+ return out_buf;
}
- switch(z % 3)
+ switch((r - p) % 3)
{
do
{
- if('.' == *sin_it) break;
- s_out += ','; // fall through
- case 0: s_out += *sin_it++; // fall through
- case 2: s_out += *sin_it++; // fall through
- case 1: s_out += *sin_it++;
- } while(*sin_it);
+ if('.' == *p) break;
+ *q++ = ','; // fall through
+ case 0: *q++ = *p++; // fall through
+ case 2: *q++ = *p++; // fall through
+ case 1: *q++ = *p++;
+ }
+ while(*p);
}
- s_out += s_in.at( z); // decimal point
- s_out += s_in.at(1 + z); // tenths
- s_out += s_in.at(2 + z); // hundredths
+// Obviously this won't do for 2 <> decimals:
+LMI_ASSERT('.' == *p);
+ *q++ = *p++; // decimal point
+ *q++ = *p++; // tenths
+ *q++ = *p++; // hundredths
- return s_out;
+ *q = '\0';
+ return out_buf;
}
#endif // duff_fmt_hpp
- [lmi-commits] [lmi] master updated (a2c3a37c -> 92d90368), Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master 17f6042e 01/11: Test nonstandard "'" printf flag, Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master 5e493f40 02/11: Rename ncnnnpnn, Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master a87f01b0 03/11: Rename a function, Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master 51c6865b 04/11: Use non-long double for duff_fmt(), Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master e8d7f191 05/11: Use low-level functions for low-level work,
Greg Chicares <=
- [lmi-commits] [lmi] master 2202d220 09/11: Reimplement ledger_format() in terms of duff_fmt(), Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master d46e3440 07/11: Modernize duff_fmt(), Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master d838ad1f 06/11: Make number of decimals a duff_fmt() argument, Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master e8d4b982 08/11: Measure ledger_format() speed, Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master 92d90368 11/11: Designate release candidate 20220429T1437Z, Greg Chicares, 2022/04/29
- [lmi-commits] [lmi] master 542c0473 10/11: Augment unit test, Greg Chicares, 2022/04/29