1 // ------------------------------------------------------------------------------
2 // format_matrix.cpp : tool to check for regressions between boost format
3 // releases and compare format specification handling
4 // ------------------------------------------------------------------------------
6 // Copyright 2017 James E. King, III. Use, modification, and distribution
7 // are subject to the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 // See http://www.boost.org/libs/format for library home page
12 // ------------------------------------------------------------------------------
13 // reference (ISO C99) : http://en.cppreference.com/w/cpp/io/c/fprintf
14 // reference (Java) : http://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html
15 // reference (Microsoft) : https://docs.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions
16 // reference (POSIX 2008): http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
18 #include <boost/array.hpp>
19 #include <boost/config.hpp>
20 #include <boost/cstdint.hpp>
21 #include <boost/filesystem/path.hpp>
22 #include <boost/format.hpp>
23 #include <boost/io/ios_state.hpp>
24 #include <boost/predef.h>
25 #include <boost/program_options.hpp>
29 #if BOOST_COMP_MSVC && BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) >= 19
30 #include <corecrt.h> // wint_t
41 #define SNPRINTF snprintf
42 #if BOOST_COMP_MSVC && BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) < 19
44 #define SNPRINTF _snprintf
47 namespace fs
= boost::filesystem
;
48 namespace po
= boost::program_options
;
57 ID_UNDEF
, // undefined behavior according to the spec, so combination is not tested
58 ID_NOTSUP
, // behavior is not supported and therefore not tested currently
60 // boolean type values:
64 // string type values:
65 ID_CHAR
, // single signed character
66 ID_UCHAR
, // single unsigned character
67 ID_WCHAR
, // single wide character
68 ID_STR
, // C style string
69 ID_WSTR
, // C style wide string
71 // integer type values:
72 ID_ZERO
, // zero value
75 ID_SHORT
, // signed short
76 ID_USHORT
, // unsigned short
77 ID_INT
, // signed integer
78 ID_UINT
, // unsigned integer
79 ID_LONG
, // signed long
80 ID_ULONG
, // unsigned long
81 ID_LLONG
, // signed long long
82 ID_ULLONG
, // unsigned long long
83 ID_INTMAX
, // intmax_t
86 ID_SPTRDF
, // signed ptrdiff_t
87 ID_PTRDIF
, // ptrdiff_t
89 // floating type values:
91 ID_NAN
, // not a number
93 ID_NEGDBL
, // negative double
94 ID_LNGDBL
, // long double
95 ID_NEGLNG
// negative long double
98 BOOST_CONSTEXPR
const bool g_bf
= false;
99 BOOST_CONSTEXPR
const bool g_bt
= true;
100 BOOST_CONSTEXPR
const uint64_t g_z
= 0;
101 BOOST_CONSTEXPR
const char g_by
= 0x60;
102 BOOST_CONSTEXPR
const unsigned char g_uby
= 0xA0;
103 BOOST_CONSTEXPR
const char g_c
= 0x58;
104 BOOST_CONSTEXPR
const wint_t g_wc
= L
'X'; // 'X', but wide
105 BOOST_CONSTEXPR
const char * g_s
= " string";
106 BOOST_CONSTEXPR
const wchar_t * g_ws
= L
"widestr";
107 BOOST_CONSTEXPR
const short g_h
= numeric_limits
<short>::min() + 12345;
108 BOOST_CONSTEXPR
const unsigned short g_uh
= numeric_limits
<unsigned short>::max() - 12345;
109 BOOST_CONSTEXPR
const int g_i
= numeric_limits
<int>::max() - 12345;
110 BOOST_CONSTEXPR
const unsigned int g_ui
= numeric_limits
<unsigned int>::max() - 12345;
111 BOOST_CONSTEXPR
const long g_l
= numeric_limits
<long>::max() - 12345;
112 BOOST_CONSTEXPR
const unsigned long g_ul
= numeric_limits
<unsigned long>::max() - 12345;
113 BOOST_CONSTEXPR
const int64_t g_ll
= numeric_limits
<int64_t>::max() - 12345;
114 BOOST_CONSTEXPR
const uint64_t g_ull
= numeric_limits
<uint64_t>::max() - 12345;
115 BOOST_CONSTEXPR
const intmax_t g_max
= numeric_limits
<intmax_t>::max() - 12345;
116 BOOST_CONSTEXPR
const size_t g_sst
= numeric_limits
<size_t>::min() - 12345;
117 BOOST_CONSTEXPR
const size_t g_st
= numeric_limits
<size_t>::max() - 12345;
118 BOOST_CONSTEXPR
const ptrdiff_t g_pt
= numeric_limits
<ptrdiff_t>::max() - 12345;
119 BOOST_CONSTEXPR
const double g_db
= 1234567.891234f
;
120 BOOST_CONSTEXPR
const double g_ndb
= -1234567.891234f
;
121 BOOST_CONSTEXPR
const long double g_ldb
= 6543211234567.891234l;
122 BOOST_CONSTEXPR
const long double g_nld
= -6543211234567.891234l;
123 #if defined(INFINITY)
124 BOOST_CONSTEXPR
const double g_inf
= INFINITY
;
127 BOOST_CONSTEXPR
const double g_nan
= NAN
;
130 boost::array
<const char *, 12> length_modifier
= { { "hh", "h", "", "l", "ll", "j", "z", "L", "w", "I", "I32", "I64" } };
131 boost::array
<const char *, 6> format_flags
= { { "", "-", "+", " ", "#", "0" } };
132 boost::array
<const char *, 6> minimum_width
= { { "", "1", "2", "5", "10", "20" } }; // TODO: , "*" } };
133 boost::array
<const char *, 7> precision
= { { "", ".", ".0", ".2", ".5", ".10", ".20" } }; // TODO: , ".*" } };
137 char conversion_specifier
;
138 interop_datatype datatype
[12];
141 // Each row represents a conversion specifier which is indicated in the first column
142 // The subsequent columns are argument type specifiers for that conversion specifier
143 // The data in the cell is the value to pass into snprintf and format to see what comes out
145 interop_row interop_matrix
[] = {
146 // |----------------------------------- ISO C99 ---------------------------------------| |-------------- Microsoft --------------|
147 // spc, hh , h , (none) , l , ll , j , z , L , w , I , I32 , I64
148 { '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
} },
149 { '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
} },
151 { '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
} },
152 { '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
} },
153 { '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
} },
154 { '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
} },
155 { '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
} },
156 { '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
} },
158 { '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
} },
159 { '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
} },
160 { '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
} },
161 { '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
} },
162 { '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
} },
163 { '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
} },
164 { '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
} },
165 { '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
} },
167 { '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
} },
168 { '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
} },
169 { '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
} },
170 { '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
} },
171 { '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
} },
172 { '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
} },
173 { '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
} },
174 { '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
} },
175 { '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
} },
176 { '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
} },
177 { '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
} },
178 { '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
} },
179 { '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
} },
180 { '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
} },
181 { '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
} },
182 { '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
} },
183 { '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
} },
184 { '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
} },
185 { '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
} },
186 { '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
} },
187 { '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
} },
188 { '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
} },
189 { '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
} },
190 { '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
} },
191 { '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
} },
192 { '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
} },
193 { '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
} },
194 { '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
} },
195 { '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
} },
196 { '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
} },
197 { '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
} },
198 { '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
} },
199 { '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
} },
200 { '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
} },
201 { '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
} },
202 { '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
} },
203 { '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
} },
204 { '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
} },
205 { '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
} },
206 { '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
} },
208 // boolalpha - not supported in snprintf per ISO C99 but is by boost::format so...
209 { '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
} },
210 { '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
} },
212 // this is the terminator for conversion specifier loops:
213 { 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
} },
216 std::string
call_snprintf(const std::string
& fmtStr
, interop_datatype type
)
218 // enough space to hold any value in this test
224 case ID_ZERO
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_z
); break;
225 case ID_BOOLF
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_bf
); break;
226 case ID_BOOLT
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_bt
); break;
227 case ID_BYTE
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_by
); break;
228 case ID_UBYTE
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_uby
); break;
229 case ID_CHAR
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_c
); break;
230 case ID_WCHAR
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_wc
); break;
231 case ID_STR
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_s
); break;
232 case ID_WSTR
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ws
); break;
233 case ID_SHORT
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_h
); break;
234 case ID_USHORT
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_uh
); break;
235 case ID_INT
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_i
); break;
236 case ID_UINT
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ui
); break;
237 case ID_LONG
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_l
); break;
238 case ID_ULONG
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ul
); break;
239 case ID_LLONG
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ll
); break;
240 case ID_ULLONG
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ull
); break;
241 case ID_INTMAX
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_max
); break;
242 case ID_SSIZET
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_sst
); break;
243 case ID_SIZET
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_st
); break;
244 case ID_SPTRDF
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_pt
); break;
245 case ID_PTRDIF
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_pt
); break;
246 #if defined(INFINITY)
247 case ID_INF
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_inf
); break;
250 case ID_NAN
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_nan
); break;
252 case ID_DOUBLE
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_db
); break;
253 case ID_NEGDBL
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ndb
); break;
254 case ID_LNGDBL
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_ldb
); break;
255 case ID_NEGLNG
: len
= SNPRINTF(buf
, BUFSIZ
, fmtStr
.c_str(), g_nld
); break;
256 default: throw logic_error("unhandled type in call_snprintf");
261 throw logic_error("snprintf length 0");
264 return std::string(buf
, len
);
267 std::string
call_format(const std::string
& fmtStr
, interop_datatype type
)
271 case ID_ZERO
: return ::boost::str(::boost::format(fmtStr
) % g_z
);
272 case ID_BOOLF
: return ::boost::str(::boost::format(fmtStr
) % g_bf
);
273 case ID_BOOLT
: return ::boost::str(::boost::format(fmtStr
) % g_bt
);
274 case ID_BYTE
: return ::boost::str(::boost::format(fmtStr
) % g_by
);
275 case ID_UBYTE
: return ::boost::str(::boost::format(fmtStr
) % g_uby
);
276 case ID_CHAR
: return ::boost::str(::boost::format(fmtStr
) % g_c
);
277 case ID_WCHAR
: return ::boost::str(::boost::format(fmtStr
) % g_wc
);
278 case ID_STR
: return ::boost::str(::boost::format(fmtStr
) % g_s
);
279 case ID_WSTR
: return ::boost::str(::boost::format(fmtStr
) % g_ws
);
280 case ID_SHORT
: return ::boost::str(::boost::format(fmtStr
) % g_h
);
281 case ID_USHORT
: return ::boost::str(::boost::format(fmtStr
) % g_uh
);
282 case ID_INT
: return ::boost::str(::boost::format(fmtStr
) % g_i
);
283 case ID_UINT
: return ::boost::str(::boost::format(fmtStr
) % g_ui
);
284 case ID_LONG
: return ::boost::str(::boost::format(fmtStr
) % g_l
);
285 case ID_ULONG
: return ::boost::str(::boost::format(fmtStr
) % g_ul
);
286 case ID_LLONG
: return ::boost::str(::boost::format(fmtStr
) % g_ll
);
287 case ID_ULLONG
: return ::boost::str(::boost::format(fmtStr
) % g_ull
);
288 case ID_INTMAX
: return ::boost::str(::boost::format(fmtStr
) % g_max
);
289 case ID_SSIZET
: return ::boost::str(::boost::format(fmtStr
) % g_sst
);
290 case ID_SIZET
: return ::boost::str(::boost::format(fmtStr
) % g_st
);
291 case ID_SPTRDF
: return ::boost::str(::boost::format(fmtStr
) % g_pt
);
292 case ID_PTRDIF
: return ::boost::str(::boost::format(fmtStr
) % g_pt
);
293 #if defined(INFINITY)
294 case ID_INF
: return ::boost::str(::boost::format(fmtStr
) % g_inf
);
297 case ID_NAN
: return ::boost::str(::boost::format(fmtStr
) % g_nan
);
299 case ID_DOUBLE
: return ::boost::str(::boost::format(fmtStr
) % g_db
);
300 case ID_NEGDBL
: return ::boost::str(::boost::format(fmtStr
) % g_ndb
);
301 case ID_LNGDBL
: return ::boost::str(::boost::format(fmtStr
) % g_ldb
);
302 case ID_NEGLNG
: return ::boost::str(::boost::format(fmtStr
) % g_nld
);
303 default: throw logic_error("unhandled type in call_format");
307 po::variables_map g_args
;
313 if (g_args
.count("snprintf"))
316 g_os
<< "# glibc.version = " << BOOST_VERSION_NUMBER_MAJOR(BOOST_LIB_C_GNU
) << "."
317 << BOOST_VERSION_NUMBER_MINOR(BOOST_LIB_C_GNU
) << "."
318 << BOOST_VERSION_NUMBER_PATCH(BOOST_LIB_C_GNU
)
320 #elif BOOST_COMP_MSVC
321 g_os
<< "# msvc.version = " << BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC
) << "."
322 << BOOST_VERSION_NUMBER_MINOR(BOOST_COMP_MSVC
) << "."
323 << BOOST_VERSION_NUMBER_PATCH(BOOST_COMP_MSVC
)
326 g_os
<< "# libc.version = unknown" << endl
;
331 g_os
<< "# boost.version = " << BOOST_VERSION
/ 100000 << "." // major version
332 << BOOST_VERSION
/ 100 % 1000 << "." // minor version
333 << BOOST_VERSION
% 100 // patch level
339 log(const std::string
& spec
, bool ok
, const std::string
& result
)
341 boost::io::ios_all_saver
saver(g_os
);
342 g_os
<< setw(20) << right
<< spec
<< "\t"
343 << (ok
? "OK " : "ERR") << "\t" << "\"" << result
<< "\"" << endl
;
346 void cell(std::size_t nrow
, std::size_t ncol
)
348 const interop_row
& row(interop_matrix
[nrow
]);
350 const interop_datatype
& dataType(row
.datatype
[ncol
]);
351 if (dataType
== ID_UNDEF
|| dataType
== ID_NOTSUP
)
356 #if !defined(INFINITY)
357 if (dataType
== ID_INF
)
364 if (dataType
== ID_NAN
)
370 // TODO: every combination of format flags - right now we do only one
371 for (std::size_t ffi
= 0; ffi
< format_flags
.size(); ++ffi
)
373 for (std::size_t mwi
= 0; mwi
< minimum_width
.size(); ++mwi
)
375 for (std::size_t pri
= 0; pri
< precision
.size(); ++pri
)
377 // Make the format string
378 std::stringstream fss
;
380 fss
<< format_flags
[ffi
];
381 fss
<< minimum_width
[mwi
];
382 fss
<< precision
[pri
];
383 fss
<< length_modifier
[ncol
];
384 fss
<< row
.conversion_specifier
;
385 std::string fmtStr
= fss
.str();
389 std::string result
= g_args
.count("snprintf") ?
390 call_snprintf(fmtStr
, dataType
) :
391 call_format (fmtStr
, dataType
) ;
392 log(fmtStr
, true, result
);
394 catch (const std::exception
& ex
)
396 log(fmtStr
, false, ex
.what());
406 for (std::size_t row
= 0; interop_matrix
[row
].conversion_specifier
!= 0x00; ++row
)
408 for (std::size_t col
= 0; col
< length_modifier
.size(); ++col
)
418 if (g_args
.count("snprintf"))
421 int len
= SNPRINTF(buf
, BUFSIZ
, "%%");
422 log("%%", len
== 1, len
== 1 ? buf
: "snprintf length != 1");
428 log("%%", true, ::boost::format("%%").str());
430 catch (std::exception
& ex
)
432 log("%%", false, ex
.what());
440 string genpath
= g_args
["generate"].as
<string
>();
441 g_os
.open(genpath
.c_str(), ios::out
| ios::trunc
);
450 ///////////////////////////////////////////////////////////////////////////////
453 main(int argc
, char *argv
[])
455 using matrix::g_args
;
457 po::options_description
desc("Allowed options");
459 ("generate,g", po::value
<string
>()->required(), "generate output filename")
460 ("help,h", "produce help message")
461 ("snprintf,s", "use snprintf instead of boost::format")
464 po::store(po::command_line_parser(argc
, argv
).options(desc
).run(), g_args
);
467 if (g_args
.count("help")) {
468 cout
<< "Usage: format_matrix [options]\n";