Commit 9ff3b977 authored by Victor Zverovich's avatar Victor Zverovich

Move more code from header to source.

parent a47e7ac0
...@@ -34,6 +34,81 @@ ...@@ -34,6 +34,81 @@
#include "format.h" #include "format.h"
#include <cctype> #include <cctype>
#include <cmath>
namespace {
#ifndef _MSC_VER
inline int SignBit(double value) {
// When compiled in C++11 mode signbit is no longer a macro but a function
// defined in namespace std and the macro is undefined.
using namespace std;
return signbit(value);
}
inline int IsInf(double x) {
#ifdef isinf
return isinf(x);
#else
return std::isinf(x);
#endif
}
#define FMT_SNPRINTF snprintf
#else
inline int SignBit(double value) {
if (value < 0) return 1;
if (value == value) return 0;
int dec = 0, sign = 0;
char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
_ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
return sign;
}
inline int IsInf(double x) { return !_finite(x); }
#define FMT_SNPRINTF sprintf_s
#endif // _MSC_VER
template <typename Char>
struct CharTraits;
template <>
struct CharTraits<char> {
template <typename T>
static int FormatFloat(char *buffer, std::size_t size,
const char *format, unsigned width, int precision, T value) {
if (width == 0) {
return precision < 0 ?
FMT_SNPRINTF(buffer, size, format, value) :
FMT_SNPRINTF(buffer, size, format, precision, value);
}
return precision < 0 ?
FMT_SNPRINTF(buffer, size, format, width, value) :
FMT_SNPRINTF(buffer, size, format, width, precision, value);
}
};
template <>
struct CharTraits<wchar_t> {
template <typename T>
static int FormatFloat(wchar_t *buffer, std::size_t size,
const wchar_t *format, unsigned width, int precision, T value) {
if (width == 0) {
return precision < 0 ?
swprintf(buffer, size, format, value) :
swprintf(buffer, size, format, precision, value);
}
return precision < 0 ?
swprintf(buffer, size, format, width, value) :
swprintf(buffer, size, format, width, precision, value);
}
};
}
const char fmt::internal::DIGITS[] = const char fmt::internal::DIGITS[] =
"0001020304050607080910111213141516171819" "0001020304050607080910111213141516171819"
...@@ -156,7 +231,7 @@ void fmt::BasicWriter<Char>::FormatDouble( ...@@ -156,7 +231,7 @@ void fmt::BasicWriter<Char>::FormatDouble(
char sign = 0; char sign = 0;
// Use SignBit instead of value < 0 because the latter is always // Use SignBit instead of value < 0 because the latter is always
// false for NaN. // false for NaN.
if (internal::SignBit(value)) { if (SignBit(value)) {
sign = '-'; sign = '-';
value = -value; value = -value;
} else if (spec.sign_flag()) { } else if (spec.sign_flag()) {
...@@ -178,7 +253,7 @@ void fmt::BasicWriter<Char>::FormatDouble( ...@@ -178,7 +253,7 @@ void fmt::BasicWriter<Char>::FormatDouble(
return; return;
} }
if (internal::IsInf(value)) { if (IsInf(value)) {
// Format infinity ourselves because sprintf's output is not consistent // Format infinity ourselves because sprintf's output is not consistent
// across platforms. // across platforms.
std::size_t size = 4; std::size_t size = 4;
...@@ -231,7 +306,7 @@ void fmt::BasicWriter<Char>::FormatDouble( ...@@ -231,7 +306,7 @@ void fmt::BasicWriter<Char>::FormatDouble(
for (;;) { for (;;) {
std::size_t size = buffer_.capacity() - offset; std::size_t size = buffer_.capacity() - offset;
Char *start = &buffer_[offset]; Char *start = &buffer_[offset];
int n = internal::CharTraits<Char>::FormatFloat( int n = CharTraits<Char>::FormatFloat(
start, size, format, width_for_sprintf, precision, value); start, size, format, width_for_sprintf, precision, value);
if (n >= 0 && offset + n < buffer_.capacity()) { if (n >= 0 && offset + n < buffer_.capacity()) {
if (sign) { if (sign) {
...@@ -568,44 +643,66 @@ void fmt::BasicFormatter<Char>::DoFormat() { ...@@ -568,44 +643,66 @@ void fmt::BasicFormatter<Char>::DoFormat() {
writer.buffer_.append(start, s); writer.buffer_.append(start, s);
} }
// Explicit instantiations for char.
template void fmt::BasicWriter<char>::FormatDouble<double>( template void fmt::BasicWriter<char>::FormatDouble<double>(
double value, const FormatSpec &spec, int precision); double value, const FormatSpec &spec, int precision);
template void fmt::BasicWriter<char>::FormatDouble<long double>( template void fmt::BasicWriter<char>::FormatDouble<long double>(
long double value, const FormatSpec &spec, int precision); long double value, const FormatSpec &spec, int precision);
template fmt::BasicWriter<char>::CharPtr fmt::BasicWriter<char>::FillPadding( template fmt::BasicWriter<char>::CharPtr fmt::BasicWriter<char>::FillPadding(
CharPtr buffer, unsigned total_size, std::size_t content_size, char fill); CharPtr buffer, unsigned total_size, std::size_t content_size, char fill);
template void fmt::BasicWriter<char>::FormatDecimal( template void fmt::BasicWriter<char>::FormatDecimal(
CharPtr buffer, uint64_t value, unsigned num_digits); CharPtr buffer, uint64_t value, unsigned num_digits);
template fmt::BasicWriter<char>::CharPtr template fmt::BasicWriter<char>::CharPtr
fmt::BasicWriter<char>::PrepareFilledBuffer( fmt::BasicWriter<char>::PrepareFilledBuffer(
unsigned size, const AlignSpec &spec, char sign); unsigned size, const AlignSpec &spec, char sign);
template void fmt::BasicFormatter<char>::ReportError( template void fmt::BasicFormatter<char>::ReportError(
const char *s, StringRef message) const; const char *s, StringRef message) const;
template unsigned fmt::BasicFormatter<char>::ParseUInt(const char *&s) const; template unsigned fmt::BasicFormatter<char>::ParseUInt(const char *&s) const;
template const fmt::BasicFormatter<char>::Arg template const fmt::BasicFormatter<char>::Arg
&fmt::BasicFormatter<char>::ParseArgIndex(const char *&s); &fmt::BasicFormatter<char>::ParseArgIndex(const char *&s);
template void fmt::BasicFormatter<char>::CheckSign( template void fmt::BasicFormatter<char>::CheckSign(
const char *&s, const Arg &arg); const char *&s, const Arg &arg);
template void fmt::BasicFormatter<char>::DoFormat(); template void fmt::BasicFormatter<char>::DoFormat();
// Explicit instantiations for wchar_t.
template void fmt::BasicWriter<wchar_t>::FormatDouble<double>( template void fmt::BasicWriter<wchar_t>::FormatDouble<double>(
double value, const FormatSpec &spec, int precision); double value, const FormatSpec &spec, int precision);
template void fmt::BasicWriter<wchar_t>::FormatDouble<long double>( template void fmt::BasicWriter<wchar_t>::FormatDouble<long double>(
long double value, const FormatSpec &spec, int precision); long double value, const FormatSpec &spec, int precision);
template fmt::BasicWriter<wchar_t>::CharPtr template fmt::BasicWriter<wchar_t>::CharPtr
fmt::BasicWriter<wchar_t>::FillPadding( fmt::BasicWriter<wchar_t>::FillPadding(
CharPtr buffer, unsigned total_size, std::size_t content_size, char fill); CharPtr buffer, unsigned total_size, std::size_t content_size, char fill);
template void fmt::BasicWriter<wchar_t>::FormatDecimal( template void fmt::BasicWriter<wchar_t>::FormatDecimal(
CharPtr buffer, uint64_t value, unsigned num_digits); CharPtr buffer, uint64_t value, unsigned num_digits);
template fmt::BasicWriter<wchar_t>::CharPtr template fmt::BasicWriter<wchar_t>::CharPtr
fmt::BasicWriter<wchar_t>::PrepareFilledBuffer( fmt::BasicWriter<wchar_t>::PrepareFilledBuffer(
unsigned size, const AlignSpec &spec, char sign); unsigned size, const AlignSpec &spec, char sign);
template void fmt::BasicFormatter<wchar_t>::ReportError( template void fmt::BasicFormatter<wchar_t>::ReportError(
const wchar_t *s, StringRef message) const; const wchar_t *s, StringRef message) const;
template unsigned fmt::BasicFormatter<wchar_t>::ParseUInt( template unsigned fmt::BasicFormatter<wchar_t>::ParseUInt(
const wchar_t *&s) const; const wchar_t *&s) const;
template const fmt::BasicFormatter<wchar_t>::Arg template const fmt::BasicFormatter<wchar_t>::Arg
&fmt::BasicFormatter<wchar_t>::ParseArgIndex(const wchar_t *&s); &fmt::BasicFormatter<wchar_t>::ParseArgIndex(const wchar_t *&s);
template void fmt::BasicFormatter<wchar_t>::CheckSign( template void fmt::BasicFormatter<wchar_t>::CheckSign(
const wchar_t *&s, const Arg &arg); const wchar_t *&s, const Arg &arg);
template void fmt::BasicFormatter<wchar_t>::DoFormat(); template void fmt::BasicFormatter<wchar_t>::DoFormat();
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include <cmath>
#include <cstddef> #include <cstddef>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
...@@ -69,77 +68,6 @@ template <typename T> ...@@ -69,77 +68,6 @@ template <typename T>
inline T *CheckPtr(T *ptr, std::size_t) { return ptr; } inline T *CheckPtr(T *ptr, std::size_t) { return ptr; }
#endif #endif
#ifndef _MSC_VER
inline int SignBit(double value) {
// When compiled in C++11 mode signbit is no longer a macro but a function
// defined in namespace std and the macro is undefined.
using namespace std;
return signbit(value);
}
inline int IsInf(double x) {
#ifdef isinf
return isinf(x);
#else
return std::isinf(x);
#endif
}
#define FMT_SNPRINTF snprintf
#else
inline int SignBit(double value) {
if (value < 0) return 1;
if (value == value) return 0;
int dec = 0, sign = 0;
char buffer[2]; // The buffer size must be >= 2 or _ecvt_s will fail.
_ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign);
return sign;
}
inline int IsInf(double x) { return !_finite(x); }
#define FMT_SNPRINTF sprintf_s
#endif // _MSC_VER
template <typename Char>
struct CharTraits;
template <>
struct CharTraits<char> {
template <typename T>
static int FormatFloat(char *buffer, std::size_t size,
const char *format, unsigned width, int precision, T value) {
if (width == 0) {
return precision < 0 ?
FMT_SNPRINTF(buffer, size, format, value) :
FMT_SNPRINTF(buffer, size, format, precision, value);
}
return precision < 0 ?
FMT_SNPRINTF(buffer, size, format, width, value) :
FMT_SNPRINTF(buffer, size, format, width, precision, value);
}
};
template <>
struct CharTraits<wchar_t> {
template <typename T>
static int FormatFloat(wchar_t *buffer, std::size_t size,
const wchar_t *format, unsigned width, int precision, T value) {
if (width == 0) {
return precision < 0 ?
swprintf(buffer, size, format, value) :
swprintf(buffer, size, format, precision, value);
}
return precision < 0 ?
swprintf(buffer, size, format, width, value) :
swprintf(buffer, size, format, width, precision, value);
}
};
// A simple array for POD types with the first SIZE elements stored in // A simple array for POD types with the first SIZE elements stored in
// the object itself. It supports a subset of std::vector's operations. // the object itself. It supports a subset of std::vector's operations.
template <typename T, std::size_t SIZE> template <typename T, std::size_t SIZE>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment