471 lines
25 KiB
C++
471 lines
25 KiB
C++
// ------------------------------------------------------------------------------
|
|
// format_matrix.cpp : tool to check for regressions between boost format
|
|
// releases and compare format specification handling
|
|
// ------------------------------------------------------------------------------
|
|
|
|
// Copyright 2017 - 2019 James E. King, III. Use, modification, and distribution
|
|
// are subject to the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// See http://www.boost.org/libs/format for library home page
|
|
|
|
// ------------------------------------------------------------------------------
|
|
// reference (ISO C99) : http://en.cppreference.com/w/cpp/io/c/fprintf
|
|
// reference (Java) : http://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html
|
|
// reference (Microsoft) : https://docs.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions
|
|
// reference (POSIX 2008): http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
|
|
|
|
#include <boost/array.hpp>
|
|
#include <boost/config.hpp>
|
|
#include <boost/cstdint.hpp>
|
|
#include <boost/filesystem/path.hpp>
|
|
#include <boost/format.hpp>
|
|
#include <boost/io/ios_state.hpp>
|
|
#include <boost/predef.h>
|
|
#include <boost/program_options.hpp>
|
|
#include <cerrno>
|
|
#include <climits>
|
|
#include <clocale>
|
|
#if BOOST_COMP_MSVC && BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) >= 19
|
|
#include <corecrt.h> // wint_t
|
|
#endif
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <cwchar>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <math.h>
|
|
|
|
#define SNPRINTF snprintf
|
|
#if BOOST_COMP_MSVC && BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) < 19
|
|
#undef SNPRINTF
|
|
#define SNPRINTF _snprintf
|
|
#endif
|
|
|
|
namespace fs = boost::filesystem;
|
|
namespace po = boost::program_options;
|
|
using namespace std;
|
|
|
|
namespace matrix
|
|
{
|
|
|
|
enum interop_datatype
|
|
{
|
|
// special types:
|
|
ID_UNDEF, // undefined behavior according to the spec, so combination is not tested
|
|
ID_NOTSUP, // behavior is not supported and therefore not tested currently
|
|
|
|
// boolean type values:
|
|
ID_BOOLF, // false
|
|
ID_BOOLT, // true
|
|
|
|
// string type values:
|
|
ID_CHAR, // single signed character
|
|
ID_UCHAR, // single unsigned character
|
|
ID_WCHAR, // single wide character
|
|
ID_STR, // C style string
|
|
ID_WSTR, // C style wide string
|
|
|
|
// integer type values:
|
|
ID_ZERO, // zero value
|
|
ID_BYTE, // int8_t
|
|
ID_UBYTE, // uint8_t
|
|
ID_SHORT, // signed short
|
|
ID_USHORT, // unsigned short
|
|
ID_INT, // signed integer
|
|
ID_UINT, // unsigned integer
|
|
ID_LONG, // signed long
|
|
ID_ULONG, // unsigned long
|
|
ID_LLONG, // signed long long
|
|
ID_ULLONG, // unsigned long long
|
|
ID_INTMAX, // intmax_t
|
|
ID_SSIZET, // ssize_t
|
|
ID_SIZET, // size_t
|
|
ID_SPTRDF, // signed ptrdiff_t
|
|
ID_PTRDIF, // ptrdiff_t
|
|
|
|
// floating type values:
|
|
ID_INF, // infinity
|
|
ID_NAN, // not a number
|
|
ID_DOUBLE, // double
|
|
ID_NEGDBL, // negative double
|
|
ID_LNGDBL, // long double
|
|
ID_NEGLNG // negative long double
|
|
};
|
|
|
|
BOOST_CONSTEXPR const bool g_bf = false;
|
|
BOOST_CONSTEXPR const bool g_bt = true;
|
|
BOOST_CONSTEXPR const uint64_t g_z = 0;
|
|
BOOST_CONSTEXPR const char g_by = 0x60;
|
|
BOOST_CONSTEXPR const unsigned char g_uby = 0xA0;
|
|
BOOST_CONSTEXPR const char g_c = 0x58;
|
|
BOOST_CONSTEXPR const wint_t g_wc = L'X'; // 'X', but wide
|
|
BOOST_CONSTEXPR const char * g_s = " string";
|
|
BOOST_CONSTEXPR const wchar_t * g_ws = L"widestr";
|
|
BOOST_CONSTEXPR const short g_h = numeric_limits<short>::min() + 12345;
|
|
BOOST_CONSTEXPR const unsigned short g_uh = numeric_limits<unsigned short>::max() - 12345;
|
|
BOOST_CONSTEXPR const int g_i = numeric_limits<int>::max() - 12345;
|
|
BOOST_CONSTEXPR const unsigned int g_ui = numeric_limits<unsigned int>::max() - 12345;
|
|
BOOST_CONSTEXPR const long g_l = numeric_limits<long>::max() - 12345;
|
|
BOOST_CONSTEXPR const unsigned long g_ul = numeric_limits<unsigned long>::max() - 12345;
|
|
BOOST_CONSTEXPR const int64_t g_ll = numeric_limits<int64_t>::max() - 12345;
|
|
BOOST_CONSTEXPR const uint64_t g_ull = numeric_limits<uint64_t>::max() - 12345;
|
|
BOOST_CONSTEXPR const intmax_t g_max = numeric_limits<intmax_t>::max() - 12345;
|
|
BOOST_CONSTEXPR const size_t g_sst = numeric_limits<size_t>::min() - 12345;
|
|
BOOST_CONSTEXPR const size_t g_st = numeric_limits<size_t>::max() - 12345;
|
|
BOOST_CONSTEXPR const ptrdiff_t g_pt = numeric_limits<ptrdiff_t>::max() - 12345;
|
|
BOOST_CONSTEXPR const double g_db = 1234567.891234f;
|
|
BOOST_CONSTEXPR const double g_ndb = -1234567.891234f;
|
|
BOOST_CONSTEXPR const long double g_ldb = 6543211234567.891234l;
|
|
BOOST_CONSTEXPR const long double g_nld = -6543211234567.891234l;
|
|
|
|
boost::array<const char *, 12> length_modifier = { { "hh", "h", "", "l", "ll", "j", "z", "L", "w", "I", "I32", "I64" } };
|
|
boost::array<const char *, 6> format_flags = { { "", "-", "+", " ", "#", "0" } };
|
|
boost::array<const char *, 6> minimum_width = { { "", "1", "2", "5", "10", "20" } }; // TODO: , "*" } };
|
|
boost::array<const char *, 7> precision = { { "", ".", ".0", ".2", ".5", ".10", ".20" } }; // TODO: , ".*" } };
|
|
|
|
struct interop_row
|
|
{
|
|
char conversion_specifier;
|
|
interop_datatype datatype[12];
|
|
};
|
|
|
|
// Each row represents a conversion specifier which is indicated in the first column
|
|
// The subsequent columns are argument type specifiers for that conversion specifier
|
|
// The data in the cell is the value to pass into snprintf and format to see what comes out
|
|
|
|
interop_row interop_matrix[] = {
|
|
// |----------------------------------- ISO C99 ---------------------------------------| |-------------- Microsoft --------------|
|
|
// spc, hh , h , (none) , l , ll , j , z , L , w , I , I32 , I64
|
|
{ 'c', { ID_UNDEF , ID_UNDEF , ID_CHAR , ID_WCHAR , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_WCHAR , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 's', { ID_UNDEF , ID_UNDEF , ID_STR , ID_WSTR , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_WSTR , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
|
|
{ 'd', { ID_BYTE , ID_SHORT , ID_INT , ID_LONG , ID_LLONG , ID_INTMAX, ID_SSIZET, ID_UNDEF , ID_UNDEF , ID_SPTRDF, ID_INT , ID_LLONG } },
|
|
{ 'd', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
|
|
{ 'd', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
|
|
{ 'i', { ID_BYTE , ID_SHORT , ID_INT , ID_LONG , ID_LLONG , ID_INTMAX, ID_SSIZET, ID_UNDEF , ID_UNDEF , ID_SPTRDF, ID_INT , ID_LLONG } },
|
|
{ 'i', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
|
|
{ 'i', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
|
|
|
|
{ 'o', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
|
|
{ 'o', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
|
|
{ 'x', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
|
|
{ 'x', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
|
|
{ 'X', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
|
|
{ 'X', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
|
|
{ 'u', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
|
|
{ 'u', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
|
|
|
|
{ 'f', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'f', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'f', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'f', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'f', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'F', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'F', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'F', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'F', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'F', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'e', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'e', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'e', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'e', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'e', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'E', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'E', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'E', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'E', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'E', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'a', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'a', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'a', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'a', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'a', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'A', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'A', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'A', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'A', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'A', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'g', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'g', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'g', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'g', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'g', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'G', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'G', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'G', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'G', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'G', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
|
|
// boolalpha - not supported in snprintf per ISO C99 but is by boost::format so...
|
|
{ 'b', { ID_UNDEF , ID_UNDEF , ID_BOOLF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
{ 'b', { ID_UNDEF , ID_UNDEF , ID_BOOLT , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
|
|
// this is the terminator for conversion specifier loops:
|
|
{ 0 , { ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
|
|
};
|
|
|
|
std::string call_snprintf(const std::string& fmtStr, interop_datatype type)
|
|
{
|
|
// enough space to hold any value in this test
|
|
char buf[BUFSIZ];
|
|
int len = 0;
|
|
|
|
switch (type)
|
|
{
|
|
case ID_ZERO: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_z ); break;
|
|
case ID_BOOLF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_bf ); break;
|
|
case ID_BOOLT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_bt ); break;
|
|
case ID_BYTE: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_by ); break;
|
|
case ID_UBYTE: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_uby); break;
|
|
case ID_CHAR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_c ); break;
|
|
case ID_WCHAR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_wc ); break;
|
|
case ID_STR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_s ); break;
|
|
case ID_WSTR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ws ); break;
|
|
case ID_SHORT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_h ); break;
|
|
case ID_USHORT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_uh ); break;
|
|
case ID_INT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_i ); break;
|
|
case ID_UINT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ui ); break;
|
|
case ID_LONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_l ); break;
|
|
case ID_ULONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ul ); break;
|
|
case ID_LLONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ll ); break;
|
|
case ID_ULLONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ull); break;
|
|
case ID_INTMAX: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_max); break;
|
|
case ID_SSIZET: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_sst); break;
|
|
case ID_SIZET: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_st ); break;
|
|
case ID_SPTRDF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_pt ); break;
|
|
case ID_PTRDIF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_pt ); break;
|
|
#if defined(INFINITY)
|
|
case ID_INF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), INFINITY); break;
|
|
#endif
|
|
#if defined(NAN)
|
|
case ID_NAN: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), NAN); break;
|
|
#endif
|
|
case ID_DOUBLE: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_db ); break;
|
|
case ID_NEGDBL: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ndb); break;
|
|
case ID_LNGDBL: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ldb); break;
|
|
case ID_NEGLNG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_nld); break;
|
|
default: throw logic_error("unhandled type in call_snprintf");
|
|
}
|
|
|
|
if (len < 0)
|
|
{
|
|
throw logic_error("snprintf length 0");
|
|
}
|
|
|
|
return std::string(buf, len);
|
|
}
|
|
|
|
std::string call_format(const std::string& fmtStr, interop_datatype type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ID_ZERO: return ::boost::str(::boost::format(fmtStr) % g_z );
|
|
case ID_BOOLF: return ::boost::str(::boost::format(fmtStr) % g_bf );
|
|
case ID_BOOLT: return ::boost::str(::boost::format(fmtStr) % g_bt );
|
|
case ID_BYTE: return ::boost::str(::boost::format(fmtStr) % g_by );
|
|
case ID_UBYTE: return ::boost::str(::boost::format(fmtStr) % g_uby);
|
|
case ID_CHAR: return ::boost::str(::boost::format(fmtStr) % g_c );
|
|
case ID_WCHAR: return ::boost::str(::boost::format(fmtStr) % g_wc );
|
|
case ID_STR: return ::boost::str(::boost::format(fmtStr) % g_s );
|
|
case ID_WSTR: return ::boost::str(::boost::format(fmtStr) % g_ws );
|
|
case ID_SHORT: return ::boost::str(::boost::format(fmtStr) % g_h );
|
|
case ID_USHORT: return ::boost::str(::boost::format(fmtStr) % g_uh );
|
|
case ID_INT: return ::boost::str(::boost::format(fmtStr) % g_i );
|
|
case ID_UINT: return ::boost::str(::boost::format(fmtStr) % g_ui );
|
|
case ID_LONG: return ::boost::str(::boost::format(fmtStr) % g_l );
|
|
case ID_ULONG: return ::boost::str(::boost::format(fmtStr) % g_ul );
|
|
case ID_LLONG: return ::boost::str(::boost::format(fmtStr) % g_ll );
|
|
case ID_ULLONG: return ::boost::str(::boost::format(fmtStr) % g_ull);
|
|
case ID_INTMAX: return ::boost::str(::boost::format(fmtStr) % g_max);
|
|
case ID_SSIZET: return ::boost::str(::boost::format(fmtStr) % g_sst);
|
|
case ID_SIZET: return ::boost::str(::boost::format(fmtStr) % g_st );
|
|
case ID_SPTRDF: return ::boost::str(::boost::format(fmtStr) % g_pt );
|
|
case ID_PTRDIF: return ::boost::str(::boost::format(fmtStr) % g_pt );
|
|
#if defined(INFINITY)
|
|
case ID_INF: return ::boost::str(::boost::format(fmtStr) % INFINITY);
|
|
#endif
|
|
#if defined(NAN)
|
|
case ID_NAN: return ::boost::str(::boost::format(fmtStr) % NAN);
|
|
#endif
|
|
case ID_DOUBLE: return ::boost::str(::boost::format(fmtStr) % g_db );
|
|
case ID_NEGDBL: return ::boost::str(::boost::format(fmtStr) % g_ndb);
|
|
case ID_LNGDBL: return ::boost::str(::boost::format(fmtStr) % g_ldb);
|
|
case ID_NEGLNG: return ::boost::str(::boost::format(fmtStr) % g_nld);
|
|
default: throw logic_error("unhandled type in call_format");
|
|
}
|
|
}
|
|
|
|
po::variables_map g_args;
|
|
ofstream g_os;
|
|
|
|
void
|
|
write_header()
|
|
{
|
|
if (g_args.count("snprintf"))
|
|
{
|
|
#if BOOST_LIB_C_GNU
|
|
g_os << "# glibc.version = " << BOOST_VERSION_NUMBER_MAJOR(BOOST_LIB_C_GNU) << "."
|
|
<< BOOST_VERSION_NUMBER_MINOR(BOOST_LIB_C_GNU) << "."
|
|
<< BOOST_VERSION_NUMBER_PATCH(BOOST_LIB_C_GNU)
|
|
<< endl;
|
|
#elif BOOST_COMP_MSVC
|
|
g_os << "# msvc.version = " << BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) << "."
|
|
<< BOOST_VERSION_NUMBER_MINOR(BOOST_COMP_MSVC) << "."
|
|
<< BOOST_VERSION_NUMBER_PATCH(BOOST_COMP_MSVC)
|
|
<< endl;
|
|
#else
|
|
g_os << "# libc.version = unknown" << endl;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
g_os << "# boost.version = " << BOOST_VERSION / 100000 << "." // major version
|
|
<< BOOST_VERSION / 100 % 1000 << "." // minor version
|
|
<< BOOST_VERSION % 100 // patch level
|
|
<< endl;
|
|
}
|
|
}
|
|
|
|
void
|
|
log(const std::string& spec, bool ok, const std::string& result)
|
|
{
|
|
boost::io::ios_all_saver saver(g_os);
|
|
g_os << setw(20) << right << spec << "\t"
|
|
<< (ok ? "OK " : "ERR") << "\t" << "\"" << result << "\"" << endl;
|
|
}
|
|
|
|
void cell(std::size_t nrow, std::size_t ncol)
|
|
{
|
|
const interop_row& row(interop_matrix[nrow]);
|
|
|
|
const interop_datatype& dataType(row.datatype[ncol]);
|
|
if (dataType == ID_UNDEF || dataType == ID_NOTSUP)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if !defined(INFINITY)
|
|
if (dataType == ID_INF)
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(NAN)
|
|
if (dataType == ID_NAN)
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
// TODO: every combination of format flags - right now we do only one
|
|
for (std::size_t ffi = 0; ffi < format_flags.size(); ++ffi)
|
|
{
|
|
for (std::size_t mwi = 0; mwi < minimum_width.size(); ++mwi)
|
|
{
|
|
for (std::size_t pri = 0; pri < precision.size(); ++pri)
|
|
{
|
|
// Make the format string
|
|
std::stringstream fss;
|
|
fss << '%';
|
|
fss << format_flags[ffi];
|
|
fss << minimum_width[mwi];
|
|
fss << precision[pri];
|
|
fss << length_modifier[ncol];
|
|
fss << row.conversion_specifier;
|
|
std::string fmtStr = fss.str();
|
|
|
|
try
|
|
{
|
|
std::string result = g_args.count("snprintf") ?
|
|
call_snprintf(fmtStr, dataType) :
|
|
call_format (fmtStr, dataType) ;
|
|
log(fmtStr, true, result);
|
|
}
|
|
catch (const std::exception& ex)
|
|
{
|
|
log(fmtStr, false, ex.what());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
matrix()
|
|
{
|
|
for (std::size_t row = 0; interop_matrix[row].conversion_specifier != 0x00; ++row)
|
|
{
|
|
for (std::size_t col = 0; col < length_modifier.size(); ++col)
|
|
{
|
|
cell(row, col);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
write_pctpct()
|
|
{
|
|
if (g_args.count("snprintf"))
|
|
{
|
|
char buf[BUFSIZ];
|
|
int len = SNPRINTF(buf, BUFSIZ, "%%");
|
|
log("%%", len == 1, len == 1 ? buf : "snprintf length != 1");
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
log("%%", true, ::boost::format("%%").str());
|
|
}
|
|
catch (std::exception& ex)
|
|
{
|
|
log("%%", false, ex.what());
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
generate()
|
|
{
|
|
string genpath = g_args["generate"].as<string>();
|
|
g_os.open(genpath.c_str(), ios::out | ios::trunc);
|
|
write_header();
|
|
write_pctpct();
|
|
matrix();
|
|
g_os.close();
|
|
}
|
|
|
|
} // matrix
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// main entry point
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
using matrix::g_args;
|
|
|
|
po::options_description desc("Allowed options");
|
|
desc.add_options()
|
|
("generate,g", po::value<string>()->required(), "generate output filename")
|
|
("help,h", "produce help message")
|
|
("snprintf,s", "use snprintf instead of boost::format")
|
|
;
|
|
|
|
po::store(po::command_line_parser(argc, argv).options(desc).run(), g_args);
|
|
po::notify(g_args);
|
|
|
|
if (g_args.count("help")) {
|
|
cout << "Usage: format_matrix [options]\n";
|
|
cout << desc;
|
|
return 0;
|
|
}
|
|
|
|
matrix::generate();
|
|
|
|
return 0;
|
|
}
|