Bug #1358 ยป floatrendering.patch
| src/web/WebUtils.C | ||
|---|---|---|
|
#include <stdlib.h>
|
||
|
#endif // WIN32
|
||
|
#ifndef WT_NO_SPIRIT
|
||
|
#include <boost/config/warning_disable.hpp>
|
||
|
#include <boost/spirit/include/karma.hpp>
|
||
|
#endif // WT_NO_SPIRIT
|
||
|
namespace Wt {
|
||
|
namespace Utils {
|
||
| ... | ... | |
|
return result;
|
||
|
}
|
||
|
char *round_str(double d, int digits, char *buf) {
|
||
|
static const int exp[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
|
||
|
long long i = static_cast<long long>(d * exp[digits] + (d > 0 ? 0.49 : -0.49));
|
||
|
lltoa(i, buf);
|
||
|
char *num = buf;
|
||
|
if (num[0] == '-')
|
||
|
++num;
|
||
|
int len = std::strlen(num);
|
||
|
if (len <= digits) {
|
||
|
int shift = digits + 1 - len;
|
||
|
for (int i = digits + 1; i >= 0; --i) {
|
||
|
if (i >= shift)
|
||
|
num[i] = num[i - shift];
|
||
|
else
|
||
|
num[i] = '0';
|
||
|
#ifndef WT_NO_SPIRIT
|
||
|
namespace {
|
||
|
using namespace boost::spirit;
|
||
|
using namespace boost::spirit::karma;
|
||
|
// adjust rendering of nan and infinity: nan -> NaN; inf -> Infinity
|
||
|
template <typename T>
|
||
|
struct JavaScriptPolicy : karma::real_policies<T>
|
||
|
{
|
||
|
template <typename CharEncoding, typename Tag, typename OutputIterator>
|
||
|
static bool nan (OutputIterator& sink, T n, bool force_sign)
|
||
|
{
|
||
|
return sign_inserter::call(
|
||
|
sink, false, traits::test_negative(n), force_sign) &&
|
||
|
string_inserter<CharEncoding, Tag>::call(sink, "NaN");
|
||
|
}
|
||
|
len = digits + 1;
|
||
|
}
|
||
|
int dotPos = (std::max)(len - digits, 0);
|
||
|
for (int i = digits + 1; i >= 0; --i)
|
||
|
num[dotPos + i + 1] = num[dotPos + i];
|
||
|
num[dotPos] = '.';
|
||
|
template <typename CharEncoding, typename Tag, typename OutputIterator>
|
||
|
static bool inf (OutputIterator& sink, T n, bool force_sign)
|
||
|
{
|
||
|
return sign_inserter::call(
|
||
|
sink, false, traits::test_negative(n), force_sign) &&
|
||
|
string_inserter<CharEncoding, Tag>::call(sink, "Infinity");
|
||
|
}
|
||
|
};
|
||
|
typedef real_generator<double, JavaScriptPolicy<double> > KarmaJavaScriptDouble;
|
||
|
}
|
||
|
static inline char *generic_double_to_str(double d, char *buf)
|
||
|
{
|
||
|
using namespace boost::spirit;
|
||
|
using namespace boost::spirit::karma;
|
||
|
char *p = buf;
|
||
|
generate(p, KarmaJavaScriptDouble(), d);
|
||
|
*p = '\0';
|
||
|
return buf;
|
||
|
}
|
||
|
#else
|
||
|
static inline char *generic_double_to_str(double d, char *buf)
|
||
|
{
|
||
|
sprintf(buf, "%f", (float)d);
|
||
|
return buf;
|
||
|
}
|
||
|
#endif
|
||
|
char *round_str(double d, int digits, char *buf) {
|
||
|
#ifndef WT_NO_SPIRIT
|
||
|
return generic_double_to_str(d, buf);
|
||
|
#else
|
||
|
if (((d > 1 && d < 1000000) || (d < -1 && d > -1000000)) && digits < 7) {
|
||
|
// range where a very fast float->string converter works
|
||
|
// mainly intended to render floats for 2D drawing canvas
|
||
|
static const int exp[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
|
||
|
long long i = static_cast<long long>(d * exp[digits] + (d > 0 ? 0.49 : -0.49));
|
||
|
lltoa(i, buf);
|
||
|
char *num = buf;
|
||
|
if (num[0] == '-')
|
||
|
++num;
|
||
|
int len = std::strlen(num);
|
||
|
if (len <= digits) {
|
||
|
int shift = digits + 1 - len;
|
||
|
for (int i = digits + 1; i >= 0; --i) {
|
||
|
if (i >= shift)
|
||
|
num[i] = num[i - shift];
|
||
|
else
|
||
|
num[i] = '0';
|
||
|
}
|
||
|
len = digits + 1;
|
||
|
}
|
||
|
int dotPos = (std::max)(len - digits, 0);
|
||
|
for (int i = digits + 1; i >= 0; --i)
|
||
|
num[dotPos + i + 1] = num[dotPos + i];
|
||
|
num[dotPos] = '.';
|
||
|
return buf;
|
||
|
} else {
|
||
|
// an implementation that covers everything
|
||
|
return generic_double_to_str(d, buf);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
std::string urlEncode(const std::string& url, const std::string& allowed)
|
||
|
{
|
||