1 /* 2 * Copyright (c) 1999 3 * Silicon Graphics Computer Systems, Inc. 4 * 5 * Copyright (c) 1999 6 * Boris Fomitchev 7 * 8 * This material is provided "as is", with absolutely no warranty expressed 9 * or implied. Any use is at your own risk. 10 * 11 * Permission to use or copy this software for any purpose is hereby granted 12 * without fee, provided the above notices are retained on all copies. 13 * Permission to modify the code and to distribute modified code is granted, 14 * provided the above notices are retained, and a notice that the code was 15 * modified is included with the above copyright notice. 16 * 17 */ 18 #ifndef _STLP_NUM_PUT_C 19 #define _STLP_NUM_PUT_C 20 21 #ifndef _STLP_INTERNAL_NUM_PUT_H 22 # include <stl/_num_put.h> 23 #endif 24 25 #ifndef _STLP_INTERNAL_LIMITS 26 # include <stl/_limits.h> 27 #endif 28 29 _STLP_BEGIN_NAMESPACE 30 31 _STLP_MOVE_TO_PRIV_NAMESPACE 32 33 // __do_put_float and its helper functions. Strategy: write the output 34 // to a buffer of char, transform the buffer to _CharT, and then copy 35 // it to the output. 36 37 //---------------------------------------------------------------------- 38 // num_put facet 39 40 template <class _CharT, class _OutputIter> 41 _OutputIter _STLP_CALL 42 __copy_float_and_fill(const _CharT* __first, const _CharT* __last, 43 _OutputIter __oi, 44 ios_base::fmtflags __flags, 45 streamsize __width, _CharT __fill, 46 _CharT __xplus, _CharT __xminus) { 47 if (__width <= __last - __first) 48 return _STLP_STD::copy(__first, __last, __oi); 49 else { 50 streamsize __pad = __width - (__last - __first); 51 ios_base::fmtflags __dir = __flags & ios_base::adjustfield; 52 53 if (__dir == ios_base::left) { 54 __oi = _STLP_STD::copy(__first, __last, __oi); 55 return _STLP_PRIV __fill_n(__oi, __pad, __fill); 56 } 57 else if (__dir == ios_base::internal && __first != __last && 58 (*__first == __xplus || *__first == __xminus)) { 59 *__oi++ = *__first++; 60 __oi = _STLP_PRIV __fill_n(__oi, __pad, __fill); 61 return _STLP_STD::copy(__first, __last, __oi); 62 } 63 else { 64 __oi = _STLP_PRIV __fill_n(__oi, __pad, __fill); 65 return _STLP_STD::copy(__first, __last, __oi); 66 } 67 } 68 } 69 70 #if !defined (_STLP_NO_WCHAR_T) 71 // Helper routine for wchar_t 72 template <class _OutputIter> 73 _OutputIter _STLP_CALL 74 __put_float(__iostring &__str, _OutputIter __oi, 75 ios_base& __f, wchar_t __fill, 76 wchar_t __decimal_point, wchar_t __sep, 77 size_t __group_pos, const string& __grouping) { 78 const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__f.getloc()); 79 80 __iowstring __wbuf; 81 __convert_float_buffer(__str, __wbuf, __ct, __decimal_point); 82 83 if (!__grouping.empty()) { 84 __insert_grouping(__wbuf, __group_pos, __grouping, 85 __sep, __ct.widen('+'), __ct.widen('-'), 0); 86 } 87 88 return __copy_float_and_fill(__wbuf.data(), __wbuf.data() + __wbuf.size(), __oi, 89 __f.flags(), __f.width(0), __fill, __ct.widen('+'), __ct.widen('-')); 90 } 91 #endif /* WCHAR_T */ 92 93 // Helper routine for char 94 template <class _OutputIter> 95 _OutputIter _STLP_CALL 96 __put_float(__iostring &__str, _OutputIter __oi, 97 ios_base& __f, char __fill, 98 char __decimal_point, char __sep, 99 size_t __group_pos, const string& __grouping) { 100 if ((__group_pos < __str.size()) && (__str[__group_pos] == '.')) { 101 __str[__group_pos] = __decimal_point; 102 } 103 104 if (!__grouping.empty()) { 105 __insert_grouping(__str, __group_pos, 106 __grouping, __sep, '+', '-', 0); 107 } 108 109 return __copy_float_and_fill(__str.data(), __str.data() + __str.size(), __oi, 110 __f.flags(), __f.width(0), __fill, '+', '-'); 111 } 112 113 template <class _CharT, class _OutputIter, class _Float> 114 _OutputIter _STLP_CALL 115 __do_put_float(_OutputIter __s, ios_base& __f, 116 _CharT __fill, _Float __x) { 117 __iostring __buf; 118 119 size_t __group_pos = __write_float(__buf, __f.flags(), (int)__f.precision(), __x); 120 121 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__f.getloc()); 122 return __put_float(__buf, __s, __f, __fill, 123 __np.decimal_point(), __np.thousands_sep(), 124 __group_pos, __np.grouping()); 125 } 126 127 inline void __get_money_digits_aux (__iostring &__buf, ios_base &, _STLP_LONGEST_FLOAT_TYPE __x) 128 { __get_floor_digits(__buf, __x); } 129 130 #if !defined (_STLP_NO_WCHAR_T) 131 inline void __get_money_digits_aux (__iowstring &__wbuf, ios_base &__f, _STLP_LONGEST_FLOAT_TYPE __x) { 132 __iostring __buf; 133 __get_floor_digits(__buf, __x); 134 135 const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__f.getloc()); 136 __convert_float_buffer(__buf, __wbuf, __ct, wchar_t(0), false); 137 } 138 #endif 139 140 template <class _CharT> 141 void _STLP_CALL __get_money_digits(_STLP_BASIC_IOSTRING(_CharT) &__buf, ios_base& __f, _STLP_LONGEST_FLOAT_TYPE __x) 142 { __get_money_digits_aux(__buf, __f, __x); } 143 144 // _M_do_put_integer and its helper functions. 145 146 template <class _CharT, class _OutputIter> 147 _OutputIter _STLP_CALL 148 __copy_integer_and_fill(const _CharT* __buf, ptrdiff_t __len, 149 _OutputIter __oi, 150 ios_base::fmtflags __flg, streamsize __wid, _CharT __fill, 151 _CharT __xplus, _CharT __xminus) { 152 if (__len >= __wid) 153 return _STLP_STD::copy(__buf, __buf + __len, __oi); 154 else { 155 //casting numeric_limits<ptrdiff_t>::max to streamsize only works is ptrdiff_t is signed or streamsize representation 156 //is larger than ptrdiff_t one. 157 _STLP_STATIC_ASSERT((sizeof(streamsize) > sizeof(ptrdiff_t)) || 158 ((sizeof(streamsize) == sizeof(ptrdiff_t)) && numeric_limits<ptrdiff_t>::is_signed)) 159 ptrdiff_t __pad = __STATIC_CAST(ptrdiff_t, (min) (__STATIC_CAST(streamsize, (numeric_limits<ptrdiff_t>::max)()), 160 __STATIC_CAST(streamsize, __wid - __len))); 161 ios_base::fmtflags __dir = __flg & ios_base::adjustfield; 162 163 if (__dir == ios_base::left) { 164 __oi = _STLP_STD::copy(__buf, __buf + __len, __oi); 165 return _STLP_PRIV __fill_n(__oi, __pad, __fill); 166 } 167 else if (__dir == ios_base::internal && __len != 0 && 168 (__buf[0] == __xplus || __buf[0] == __xminus)) { 169 *__oi++ = __buf[0]; 170 __oi = __fill_n(__oi, __pad, __fill); 171 return _STLP_STD::copy(__buf + 1, __buf + __len, __oi); 172 } 173 else if (__dir == ios_base::internal && __len >= 2 && 174 (__flg & ios_base::showbase) && 175 (__flg & ios_base::basefield) == ios_base::hex) { 176 *__oi++ = __buf[0]; 177 *__oi++ = __buf[1]; 178 __oi = __fill_n(__oi, __pad, __fill); 179 return _STLP_STD::copy(__buf + 2, __buf + __len, __oi); 180 } 181 else { 182 __oi = __fill_n(__oi, __pad, __fill); 183 return _STLP_STD::copy(__buf, __buf + __len, __oi); 184 } 185 } 186 } 187 188 #if !defined (_STLP_NO_WCHAR_T) 189 // Helper function for wchar_t 190 template <class _OutputIter> 191 _OutputIter _STLP_CALL 192 __put_integer(char* __buf, char* __iend, _OutputIter __s, 193 ios_base& __f, 194 ios_base::fmtflags __flags, wchar_t __fill) { 195 locale __loc = __f.getloc(); 196 const ctype<wchar_t>& __ct = use_facet<ctype<wchar_t> >(__loc); 197 198 wchar_t __xplus = __ct.widen('+'); 199 wchar_t __xminus = __ct.widen('-'); 200 201 wchar_t __wbuf[64]; 202 __ct.widen(__buf, __iend, __wbuf); 203 ptrdiff_t __len = __iend - __buf; 204 wchar_t* __eend = __wbuf + __len; 205 206 const numpunct<wchar_t>& __np = use_facet<numpunct<wchar_t> >(__loc); 207 const string& __grouping = __np.grouping(); 208 209 if (!__grouping.empty()) { 210 int __basechars; 211 if (__flags & ios_base::showbase) 212 switch (__flags & ios_base::basefield) { 213 case ios_base::hex: __basechars = 2; break; 214 case ios_base::oct: __basechars = 1; break; 215 default: __basechars = 0; 216 } 217 else 218 __basechars = 0; 219 220 __len = __insert_grouping(__wbuf, __eend, __grouping, __np.thousands_sep(), 221 __xplus, __xminus, __basechars); 222 } 223 224 return __copy_integer_and_fill((wchar_t*)__wbuf, __len, __s, 225 __flags, __f.width(0), __fill, __xplus, __xminus); 226 } 227 #endif 228 229 // Helper function for char 230 template <class _OutputIter> 231 _OutputIter _STLP_CALL 232 __put_integer(char* __buf, char* __iend, _OutputIter __s, 233 ios_base& __f, ios_base::fmtflags __flags, char __fill) { 234 char __grpbuf[64]; 235 ptrdiff_t __len = __iend - __buf; 236 237 const numpunct<char>& __np = use_facet<numpunct<char> >(__f.getloc()); 238 const string& __grouping = __np.grouping(); 239 240 if (!__grouping.empty()) { 241 int __basechars; 242 if (__flags & ios_base::showbase) 243 switch (__flags & ios_base::basefield) { 244 case ios_base::hex: __basechars = 2; break; 245 case ios_base::oct: __basechars = 1; break; 246 default: __basechars = 0; 247 } 248 else 249 __basechars = 0; 250 251 // make sure there is room at the end of the buffer 252 // we pass to __insert_grouping 253 _STLP_STD::copy(__buf, __iend, (char *) __grpbuf); 254 __buf = __grpbuf; 255 __iend = __grpbuf + __len; 256 __len = __insert_grouping(__buf, __iend, __grouping, __np.thousands_sep(), 257 '+', '-', __basechars); 258 } 259 260 return __copy_integer_and_fill(__buf, __len, __s, __flags, __f.width(0), __fill, '+', '-'); 261 } 262 263 #if defined (_STLP_LONG_LONG) 264 typedef _STLP_LONG_LONG __max_int_t; 265 typedef unsigned _STLP_LONG_LONG __umax_int_t; 266 #else 267 typedef long __max_int_t; 268 typedef unsigned long __umax_int_t; 269 #endif 270 271 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_lo(); 272 _STLP_DECLSPEC const char* _STLP_CALL __hex_char_table_hi(); 273 274 template <class _Integer> 275 inline char* _STLP_CALL 276 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __true_type& /* is_signed */) { 277 const bool __negative = __x < 0 ; 278 __max_int_t __temp = __x; 279 __umax_int_t __utemp = __negative?-__temp:__temp; 280 281 for (; __utemp != 0; __utemp /= 10) 282 *--__ptr = (char)((int)(__utemp % 10) + '0'); 283 // put sign if needed or requested 284 if (__negative) 285 *--__ptr = '-'; 286 else if (__flags & ios_base::showpos) 287 *--__ptr = '+'; 288 return __ptr; 289 } 290 291 template <class _Integer> 292 inline char* _STLP_CALL 293 __write_decimal_backward(char* __ptr, _Integer __x, ios_base::fmtflags __flags, const __false_type& /* is_signed */) { 294 for (; __x != 0; __x /= 10) 295 *--__ptr = (char)((int)(__x % 10) + '0'); 296 // put sign if requested 297 if (__flags & ios_base::showpos) 298 *--__ptr = '+'; 299 return __ptr; 300 } 301 302 template <class _Integer> 303 char* _STLP_CALL 304 __write_integer_backward(char* __buf, ios_base::fmtflags __flags, _Integer __x) { 305 char* __ptr = __buf; 306 307 if (__x == 0) { 308 *--__ptr = '0'; 309 if ((__flags & ios_base::showpos) && ((__flags & (ios_base::oct | ios_base::hex)) == 0)) 310 *--__ptr = '+'; 311 // oct or hex base shall not be added to the 0 value (see '#' flag in C formating strings) 312 } 313 else { 314 switch (__flags & ios_base::basefield) { 315 case ios_base::oct: 316 { 317 __umax_int_t __temp = __x; 318 // if the size of integer is less than 8, clear upper part 319 if ( sizeof(__x) < 8 && sizeof(__umax_int_t) >= 8 ) 320 __temp &= 0xFFFFFFFF; 321 322 for (; __temp != 0; __temp >>=3) 323 *--__ptr = (char)((((unsigned)__temp)& 0x7) + '0'); 324 325 // put leading '0' if showbase is set 326 if (__flags & ios_base::showbase) 327 *--__ptr = '0'; 328 } 329 break; 330 case ios_base::hex: 331 { 332 const char* __table_ptr = (__flags & ios_base::uppercase) ? 333 __hex_char_table_hi() : __hex_char_table_lo(); 334 __umax_int_t __temp = __x; 335 // if the size of integer is less than 8, clear upper part 336 if ( sizeof(__x) < 8 && sizeof(__umax_int_t) >= 8 ) 337 __temp &= 0xFFFFFFFF; 338 339 for (; __temp != 0; __temp >>=4) 340 *--__ptr = __table_ptr[((unsigned)__temp & 0xF)]; 341 342 if (__flags & ios_base::showbase) { 343 *--__ptr = __table_ptr[16]; 344 *--__ptr = '0'; 345 } 346 } 347 break; 348 //case ios_base::dec: 349 default: 350 { 351 #if defined(__HP_aCC) && (__HP_aCC == 1) 352 bool _IsSigned = !((_Integer)-1 > 0); 353 if (_IsSigned) 354 __ptr = __write_decimal_backward(__ptr, __x, __flags, __true_type() ); 355 else 356 __ptr = __write_decimal_backward(__ptr, __x, __flags, __false_type() ); 357 #else 358 typedef typename __bool2type<numeric_limits<_Integer>::is_signed>::_Ret _IsSigned; 359 __ptr = __write_decimal_backward(__ptr, __x, __flags, _IsSigned()); 360 #endif 361 } 362 break; 363 } 364 } 365 366 // return pointer to beginning of the string 367 return __ptr; 368 } 369 370 template <class _CharT, class _OutputIter, class _Integer> 371 _OutputIter _STLP_CALL 372 __do_put_integer(_OutputIter __s, ios_base& __f, _CharT __fill, _Integer __x) { 373 // buffer size = number of bytes * number of digit necessary in the smallest Standard base (base 8, 3 digits/byte) 374 // plus the longest base representation '0x' 375 // Do not use __buf_size to define __buf static buffer, some compilers (HP aCC) do not accept const variable as 376 // the specification of a static buffer size. 377 char __buf[sizeof(_Integer) * 3 + 2]; 378 const ptrdiff_t __buf_size = sizeof(__buf) / sizeof(char); 379 ios_base::fmtflags __flags = __f.flags(); 380 char* __ibeg = __write_integer_backward((char*)__buf + __buf_size, __flags, __x); 381 return __put_integer(__ibeg, (char*)__buf + __buf_size, __s, __f, __flags, __fill); 382 } 383 384 template <class _CharT, class _OutputIter> 385 _OutputIter _STLP_CALL 386 __do_put_bool(_OutputIter __s, ios_base& __f, _CharT __fill, bool __x) { 387 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__f.getloc()); 388 389 basic_string<_CharT, char_traits<_CharT>, allocator<_CharT> > __str = __x ? __np.truename() : __np.falsename(); 390 391 streamsize __wid = __f.width(0); 392 if (__str.size() >= __STATIC_CAST(size_t, __wid)) 393 return _STLP_STD::copy(__str.begin(), __str.end(), __s); 394 else { 395 streamsize __pad = __wid - __str.size(); 396 ios_base::fmtflags __dir = __f.flags() & ios_base::adjustfield; 397 398 if (__dir == ios_base::left) { 399 __s = _STLP_STD::copy(__str.begin(), __str.end(), __s); 400 return __fill_n(__s, __pad, __fill); 401 } 402 else /* covers right and internal padding */ { 403 __s = __fill_n(__s, __pad, __fill); 404 return _STLP_STD::copy(__str.begin(), __str.end(), __s); 405 } 406 } 407 } 408 _STLP_MOVE_TO_STD_NAMESPACE 409 410 // 411 // num_put<> 412 // 413 414 template <class _CharT, class _OutputIterator> 415 locale::id num_put<_CharT, _OutputIterator>::id; 416 417 #if !defined (_STLP_NO_BOOL) 418 template <class _CharT, class _OutputIter> 419 _OutputIter 420 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 421 bool __val) const { 422 if (!(__f.flags() & ios_base::boolalpha)) 423 // 22.2.2.2.2.23: shall return do_put for int and not directly __do_put_integer. 424 return do_put(__s, __f, __fill, __STATIC_CAST(long, __val)); 425 426 return _STLP_PRIV __do_put_bool(__s, __f, __fill, __val); 427 } 428 #endif 429 430 template <class _CharT, class _OutputIter> 431 _OutputIter 432 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 433 long __val) const 434 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); } 435 436 template <class _CharT, class _OutputIter> 437 _OutputIter 438 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 439 unsigned long __val) const 440 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); } 441 442 template <class _CharT, class _OutputIter> 443 _OutputIter 444 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 445 double __val) const 446 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); } 447 448 #if !defined (_STLP_NO_LONG_DOUBLE) 449 template <class _CharT, class _OutputIter> 450 _OutputIter 451 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 452 long double __val) const 453 { return _STLP_PRIV __do_put_float(__s, __f, __fill, __val); } 454 #endif 455 456 #if defined (_STLP_LONG_LONG) 457 template <class _CharT, class _OutputIter> 458 _OutputIter 459 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 460 _STLP_LONG_LONG __val) const 461 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); } 462 463 template <class _CharT, class _OutputIter> 464 _OutputIter 465 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT __fill, 466 unsigned _STLP_LONG_LONG __val) const 467 { return _STLP_PRIV __do_put_integer(__s, __f, __fill, __val); } 468 #endif /* _STLP_LONG_LONG */ 469 470 471 // 22.2.2.2.2 Stage 1: "For conversion from void* the specifier is %p." 472 // This is not clear and I'm really don't follow this (below). 473 template <class _CharT, class _OutputIter> 474 _OutputIter 475 num_put<_CharT, _OutputIter>::do_put(_OutputIter __s, ios_base& __f, _CharT /*__fill*/, 476 const void* __val) const { 477 const ctype<_CharT>& __c_type = use_facet<ctype<_CharT> >(__f.getloc()); 478 ios_base::fmtflags __save_flags = __f.flags(); 479 480 __f.setf(ios_base::hex, ios_base::basefield); 481 __f.setf(ios_base::showbase); 482 __f.setf(ios_base::internal, ios_base::adjustfield); 483 __f.width((sizeof(void*) * 2) + 2); // digits in pointer type plus '0x' prefix 484 if ( __val == 0 ) { 485 // base ('0x') not shown for null, but I really want to type it 486 // for pointer. Print it first in this case. 487 const char* __table_ptr = (__save_flags & ios_base::uppercase) ? 488 _STLP_PRIV __hex_char_table_hi() : _STLP_PRIV __hex_char_table_lo(); 489 __s++ = __c_type.widen( '0' ); 490 __s++ = __c_type.widen( __table_ptr[16] ); 491 __f.width((sizeof(void*) * 2)); // digits in pointer type 492 } else { 493 __f.width((sizeof(void*) * 2) + 2); // digits in pointer type plus '0x' prefix 494 } 495 #if defined (_STLP_MSVC) 496 # pragma warning (push) 497 # pragma warning (disable : 4311) //pointer truncation from 'const void*' to 'unsigned long' 498 #endif 499 _OutputIter result = 500 #ifdef _STLP_LONG_LONG 501 ( sizeof(void*) == sizeof(unsigned long) ) ? 502 #endif 503 _STLP_PRIV __do_put_integer(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned long,__val)) 504 #ifdef _STLP_LONG_LONG 505 : /* ( sizeof(void*) == sizeof(unsigned _STLP_LONG_LONG) ) ? */ 506 _STLP_PRIV __do_put_integer(__s, __f, __c_type.widen('0'), __REINTERPRET_CAST(unsigned _STLP_LONG_LONG,__val)) 507 #endif 508 ; 509 #if defined (_STLP_MSVC) 510 # pragma warning (pop) 511 #endif 512 __f.flags(__save_flags); 513 return result; 514 } 515 516 _STLP_END_NAMESPACE 517 518 #endif /* _STLP_NUM_PUT_C */ 519 520 // Local Variables: 521 // mode:C++ 522 // End: 523