C++ string Formatter Again Part-4

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
Previously asked here.
The code is now available on GitHub.
Since the previous review I have added unit tests.
Since it is big it will come in a couple of parts.
Part 1 | Part 2 | Part 3 | Part 4
Part 4
Printing strings and integers did not work the same way on streams as they did in printf(). So I had to write some special handling code to deal with these types to get the unit tests to all work.
printToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#include "FormatInfo.h"
#include "printIntToStream.h"
#include "printStringToStream.h"
#include <ostream>
namespace ThorsAnvil::IOUtil
template<typename T>
inline void printToStreamDefault(std::ostream& s, T const& arg, FormatInfo const&)
s << arg;
/* Template method for everything apart from integers */
template<typename T>
inline
typename std::enable_if<!std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
// Just use the standard stream printing methods.
// Below we special case Int and string handling (floats work as expected).
printToStreamDefault(s, arg, info);
/*
* As a char is an integer we need to detect this case
* and call the standard printing functions for Type::Char
*
* But we can also print an integer using a char in which case we need to convert the char to an integer
* before we can print it. Below are helper functions to convert Char to Int when printing a char as an
* an integer.
*/
template<typename T>
struct CharIntConverter
using Integer = T;
;
template<>
struct CharIntConverter<char>
using Integer = int;
;
template<>
struct CharIntConverter<unsigned char>
using Integer = unsigned int;
;
template<typename T>
inline
typename std::enable_if<std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
if (info.type == Type::Char)
printToStreamDefault(s, static_cast<char>(arg), info);
else
printIntToStream(s, static_cast<typename CharIntConverter<T>::Integer>(arg), info);
// C-String
inline void printToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
printStringToStream(s, arg, info);
#endif
PrintStringToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
namespace ThorsAnvil::IOUtil
inline void printStringToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
if (info.precision == -1)
s << arg;
else
s.width(0);
std::size_t padding = (info.precision >= info.width) ? 0 : (info.width - info.precision);
if (!info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
for (std::size_t loop = 0; arg[loop] != '' && loop < info.precision; ++loop)
s.put(arg[loop]);
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
PrintIntToStream
#ifndef THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
#include <ostream>
#include <cmath>
namespace ThorsAnvil::IOUtil
inline long long absm(long long arg) return std::abs(arg);
inline long absm(long arg) return std::abs(arg);
inline int absm(int arg) return std::abs(arg);
inline unsigned long long absm(unsigned long long arg) return arg;
inline unsigned long absm(unsigned long arg) return arg;
inline unsigned int absm(unsigned int arg) return arg;
template<typename T>
inline void printIntToStream(std::ostream& s, T arg, FormatInfo const& info)
static long double const logFor16 = std::log10(16.0L);
static long double const logFor10 = std::log10(10.0L);
static long double const logFor08 = std::log10(8.0L);
double const& logBase = s.flags() & std::ios_base::oct ? logFor08 : s.flags() & std::ios_base::hex ? logFor16 : logFor10;
if (info.width == 0 && info.precision == -1)
s << arg;
else
arg != 0)
s << absm(arg);
// Add spaces after number to make it fit in width.
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
#endif
c++ formatting serialization stream
add a comment |Â
up vote
3
down vote
favorite
Previously asked here.
The code is now available on GitHub.
Since the previous review I have added unit tests.
Since it is big it will come in a couple of parts.
Part 1 | Part 2 | Part 3 | Part 4
Part 4
Printing strings and integers did not work the same way on streams as they did in printf(). So I had to write some special handling code to deal with these types to get the unit tests to all work.
printToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#include "FormatInfo.h"
#include "printIntToStream.h"
#include "printStringToStream.h"
#include <ostream>
namespace ThorsAnvil::IOUtil
template<typename T>
inline void printToStreamDefault(std::ostream& s, T const& arg, FormatInfo const&)
s << arg;
/* Template method for everything apart from integers */
template<typename T>
inline
typename std::enable_if<!std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
// Just use the standard stream printing methods.
// Below we special case Int and string handling (floats work as expected).
printToStreamDefault(s, arg, info);
/*
* As a char is an integer we need to detect this case
* and call the standard printing functions for Type::Char
*
* But we can also print an integer using a char in which case we need to convert the char to an integer
* before we can print it. Below are helper functions to convert Char to Int when printing a char as an
* an integer.
*/
template<typename T>
struct CharIntConverter
using Integer = T;
;
template<>
struct CharIntConverter<char>
using Integer = int;
;
template<>
struct CharIntConverter<unsigned char>
using Integer = unsigned int;
;
template<typename T>
inline
typename std::enable_if<std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
if (info.type == Type::Char)
printToStreamDefault(s, static_cast<char>(arg), info);
else
printIntToStream(s, static_cast<typename CharIntConverter<T>::Integer>(arg), info);
// C-String
inline void printToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
printStringToStream(s, arg, info);
#endif
PrintStringToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
namespace ThorsAnvil::IOUtil
inline void printStringToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
if (info.precision == -1)
s << arg;
else
s.width(0);
std::size_t padding = (info.precision >= info.width) ? 0 : (info.width - info.precision);
if (!info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
for (std::size_t loop = 0; arg[loop] != '' && loop < info.precision; ++loop)
s.put(arg[loop]);
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
PrintIntToStream
#ifndef THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
#include <ostream>
#include <cmath>
namespace ThorsAnvil::IOUtil
inline long long absm(long long arg) return std::abs(arg);
inline long absm(long arg) return std::abs(arg);
inline int absm(int arg) return std::abs(arg);
inline unsigned long long absm(unsigned long long arg) return arg;
inline unsigned long absm(unsigned long arg) return arg;
inline unsigned int absm(unsigned int arg) return arg;
template<typename T>
inline void printIntToStream(std::ostream& s, T arg, FormatInfo const& info)
static long double const logFor16 = std::log10(16.0L);
static long double const logFor10 = std::log10(10.0L);
static long double const logFor08 = std::log10(8.0L);
double const& logBase = s.flags() & std::ios_base::oct ? logFor08 : s.flags() & std::ios_base::hex ? logFor16 : logFor10;
if (info.width == 0 && info.precision == -1)
s << arg;
else
arg != 0)
s << absm(arg);
// Add spaces after number to make it fit in width.
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
#endif
c++ formatting serialization stream
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
Previously asked here.
The code is now available on GitHub.
Since the previous review I have added unit tests.
Since it is big it will come in a couple of parts.
Part 1 | Part 2 | Part 3 | Part 4
Part 4
Printing strings and integers did not work the same way on streams as they did in printf(). So I had to write some special handling code to deal with these types to get the unit tests to all work.
printToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#include "FormatInfo.h"
#include "printIntToStream.h"
#include "printStringToStream.h"
#include <ostream>
namespace ThorsAnvil::IOUtil
template<typename T>
inline void printToStreamDefault(std::ostream& s, T const& arg, FormatInfo const&)
s << arg;
/* Template method for everything apart from integers */
template<typename T>
inline
typename std::enable_if<!std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
// Just use the standard stream printing methods.
// Below we special case Int and string handling (floats work as expected).
printToStreamDefault(s, arg, info);
/*
* As a char is an integer we need to detect this case
* and call the standard printing functions for Type::Char
*
* But we can also print an integer using a char in which case we need to convert the char to an integer
* before we can print it. Below are helper functions to convert Char to Int when printing a char as an
* an integer.
*/
template<typename T>
struct CharIntConverter
using Integer = T;
;
template<>
struct CharIntConverter<char>
using Integer = int;
;
template<>
struct CharIntConverter<unsigned char>
using Integer = unsigned int;
;
template<typename T>
inline
typename std::enable_if<std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
if (info.type == Type::Char)
printToStreamDefault(s, static_cast<char>(arg), info);
else
printIntToStream(s, static_cast<typename CharIntConverter<T>::Integer>(arg), info);
// C-String
inline void printToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
printStringToStream(s, arg, info);
#endif
PrintStringToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
namespace ThorsAnvil::IOUtil
inline void printStringToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
if (info.precision == -1)
s << arg;
else
s.width(0);
std::size_t padding = (info.precision >= info.width) ? 0 : (info.width - info.precision);
if (!info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
for (std::size_t loop = 0; arg[loop] != '' && loop < info.precision; ++loop)
s.put(arg[loop]);
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
PrintIntToStream
#ifndef THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
#include <ostream>
#include <cmath>
namespace ThorsAnvil::IOUtil
inline long long absm(long long arg) return std::abs(arg);
inline long absm(long arg) return std::abs(arg);
inline int absm(int arg) return std::abs(arg);
inline unsigned long long absm(unsigned long long arg) return arg;
inline unsigned long absm(unsigned long arg) return arg;
inline unsigned int absm(unsigned int arg) return arg;
template<typename T>
inline void printIntToStream(std::ostream& s, T arg, FormatInfo const& info)
static long double const logFor16 = std::log10(16.0L);
static long double const logFor10 = std::log10(10.0L);
static long double const logFor08 = std::log10(8.0L);
double const& logBase = s.flags() & std::ios_base::oct ? logFor08 : s.flags() & std::ios_base::hex ? logFor16 : logFor10;
if (info.width == 0 && info.precision == -1)
s << arg;
else
arg != 0)
s << absm(arg);
// Add spaces after number to make it fit in width.
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
#endif
c++ formatting serialization stream
Previously asked here.
The code is now available on GitHub.
Since the previous review I have added unit tests.
Since it is big it will come in a couple of parts.
Part 1 | Part 2 | Part 3 | Part 4
Part 4
Printing strings and integers did not work the same way on streams as they did in printf(). So I had to write some special handling code to deal with these types to get the unit tests to all work.
printToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_TO_STREAM_H
#include "FormatInfo.h"
#include "printIntToStream.h"
#include "printStringToStream.h"
#include <ostream>
namespace ThorsAnvil::IOUtil
template<typename T>
inline void printToStreamDefault(std::ostream& s, T const& arg, FormatInfo const&)
s << arg;
/* Template method for everything apart from integers */
template<typename T>
inline
typename std::enable_if<!std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
// Just use the standard stream printing methods.
// Below we special case Int and string handling (floats work as expected).
printToStreamDefault(s, arg, info);
/*
* As a char is an integer we need to detect this case
* and call the standard printing functions for Type::Char
*
* But we can also print an integer using a char in which case we need to convert the char to an integer
* before we can print it. Below are helper functions to convert Char to Int when printing a char as an
* an integer.
*/
template<typename T>
struct CharIntConverter
using Integer = T;
;
template<>
struct CharIntConverter<char>
using Integer = int;
;
template<>
struct CharIntConverter<unsigned char>
using Integer = unsigned int;
;
template<typename T>
inline
typename std::enable_if<std::is_integral<T>::value>::type
printToStream(std::ostream& s, T const& arg, FormatInfo const& info)
if (info.type == Type::Char)
printToStreamDefault(s, static_cast<char>(arg), info);
else
printIntToStream(s, static_cast<typename CharIntConverter<T>::Integer>(arg), info);
// C-String
inline void printToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
printStringToStream(s, arg, info);
#endif
PrintStringToStream.h
#ifndef THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_STRING_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
namespace ThorsAnvil::IOUtil
inline void printStringToStream(std::ostream& s, char const* const& arg, FormatInfo const& info)
if (info.precision == -1)
s << arg;
else
s.width(0);
std::size_t padding = (info.precision >= info.width) ? 0 : (info.width - info.precision);
if (!info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
for (std::size_t loop = 0; arg[loop] != '' && loop < info.precision; ++loop)
s.put(arg[loop]);
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
PrintIntToStream
#ifndef THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#define THORSANVIL_IOUTIL_PRINT_INT_TO_STREAM_H
#include "FormatInfo.h"
#include "printToStream.h"
#include <ostream>
#include <cmath>
namespace ThorsAnvil::IOUtil
inline long long absm(long long arg) return std::abs(arg);
inline long absm(long arg) return std::abs(arg);
inline int absm(int arg) return std::abs(arg);
inline unsigned long long absm(unsigned long long arg) return arg;
inline unsigned long absm(unsigned long arg) return arg;
inline unsigned int absm(unsigned int arg) return arg;
template<typename T>
inline void printIntToStream(std::ostream& s, T arg, FormatInfo const& info)
static long double const logFor16 = std::log10(16.0L);
static long double const logFor10 = std::log10(10.0L);
static long double const logFor08 = std::log10(8.0L);
double const& logBase = s.flags() & std::ios_base::oct ? logFor08 : s.flags() & std::ios_base::hex ? logFor16 : logFor10;
if (info.width == 0 && info.precision == -1)
s << arg;
else
arg != 0)
s << absm(arg);
// Add spaces after number to make it fit in width.
if (info.leftJustify)
for (std::size_t loop = 0; loop < padding; ++loop)
s.put(' ');
#endif
c++ formatting serialization stream
edited Mar 4 at 19:52
Phrancis
14.6k645137
14.6k645137
asked Mar 4 at 19:22
Martin York
70.9k481244
70.9k481244
add a comment |Â
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188812%2fc-string-formatter-again-part-4%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password