-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add custom decimal and thousands separarators
- Loading branch information
1 parent
10df6a7
commit 1bd1ec1
Showing
2 changed files
with
78 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,14 @@ | |
* Built-in "|number_format" modifier | ||
* | ||
* @author David van Erkelens <[email protected]> | ||
* @copyright 2019 Copernica BV | ||
* @copyright 2019 - 2020 Copernica BV | ||
*/ | ||
|
||
/** | ||
* Dependencies | ||
*/ | ||
#include <locale> | ||
|
||
/** | ||
* Namespace | ||
*/ | ||
|
@@ -17,6 +22,25 @@ namespace SmartTpl { namespace Internal { | |
*/ | ||
class NumberFormatModifier : public Modifier | ||
{ | ||
private: | ||
/** | ||
* Struct that works with the std::numpunct facet and can be | ||
* constructed with a char for the decimal and thousands separators | ||
*/ | ||
struct formatter : std::numpunct<char> | ||
{ | ||
// chars for the separators | ||
char decimal; char thousand; | ||
|
||
// constructor | ||
formatter(char decimal, char thousand) : decimal(decimal), thousand(thousand) {} | ||
|
||
// build in functions for separator formatting | ||
char do_thousands_sep() const { return thousand; } // thousands separator | ||
std::string do_grouping() const { return (int) thousand == 0 ? "" : "\3"; } // separate every 3 digits, if we have a separator | ||
char do_decimal_point() const { return decimal; } // decimal separator | ||
}; | ||
|
||
public: | ||
/** | ||
* Destructor | ||
|
@@ -31,32 +55,50 @@ class NumberFormatModifier : public Modifier | |
*/ | ||
VariantValue modify(const Value &input, const SmartTpl::Parameters ¶ms) override | ||
{ | ||
// Convert input to double | ||
double original(input.toDouble()); | ||
|
||
// make sure we have a parameter containing the format | ||
// make sure we have a parameter containing the number of decimals | ||
if (params.size() < 1) throw NoModification(); | ||
|
||
// get the amound of decimals to output | ||
// get the amount of decimals to output | ||
int decimals = params[0].toInteger(); | ||
|
||
// buffer to create the printf format | ||
char format[10]; | ||
// get separator variables for decimals and thousands | ||
char decimal_separator = '.'; char thousand_separator = (char) 0; | ||
|
||
// if we have a valid parameter, overwrite decimal separator | ||
if (params.size() > 1) | ||
{ | ||
// convert to string | ||
auto param = params[1].toString(); | ||
|
||
// make sure that we have a character (we could throw if the param is too long?) | ||
if (param.size() > 0) decimal_separator = param[0]; | ||
} | ||
|
||
// if we have a valid parameter, overwrite thousands separator | ||
if (params.size() > 2) | ||
{ | ||
// convert to string | ||
auto param = params[2].toString(); | ||
|
||
// make sure that we have a character (we could throw if the param is too long?) | ||
if (param.size() > 0) thousand_separator = param[0]; | ||
} | ||
|
||
// format the format | ||
sprintf(format, "%%.%if", decimals); | ||
// create stringstream to store formatted number | ||
std::stringstream stream; | ||
|
||
// calculate size of new string | ||
size_t size = snprintf(nullptr, 0, format, original); | ||
// create custom locale for our formatting options | ||
std::locale formatting_locale(stream.getloc(), new NumberFormatModifier::formatter(decimal_separator, thousand_separator)); | ||
|
||
// create buffer | ||
char buffer[size + 1]; | ||
// set formatting options | ||
stream.precision(decimals); | ||
stream.imbue(formatting_locale); | ||
|
||
// create new string | ||
sprintf(buffer, format, original); | ||
// stream the value (never in scientific format) | ||
stream << std::fixed << input.toDouble(); | ||
|
||
// create object | ||
return VariantValue(buffer); | ||
return VariantValue(stream.str()); | ||
} | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters