LCOV - code coverage report
Current view: top level - snapdev - ostream_int128.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 59 64 92.2 %
Date: 2022-07-09 19:51:09 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2021-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snapdev
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : #pragma once
      20             : 
      21             : /** \file
      22             :  * \brief Print large integers to any iostream.
      23             :  *
      24             :  * This function prints large integers (128 bits) to the specified iostream.
      25             :  */
      26             : 
      27             : // C++
      28             : //
      29             : #include    <ostream>
      30             : #include    <sstream>
      31             : 
      32             : 
      33             : namespace snapdev
      34             : {
      35             : 
      36             : /** \brief Convert an __int128 to a string.
      37             :  *
      38             :  * This function converts an __int128 to a string.
      39             :  *
      40             :  * \param[in] x  An __int128 number.
      41             :  *
      42             :  * \return A string representing that __int128 number.
      43             :  */
      44             : #pragma GCC diagnostic push
      45             : #pragma GCC diagnostic ignored "-Wpedantic"
      46        2022 : inline std::string to_string(__int128 x, __int128 base = 10, bool uppercase = false)
      47             : {
      48        2022 :     char buf[129];  // binary requires 128 + '-' = 129 chars
      49             : 
      50        2022 :     char const adjust((uppercase ? 'A' : 'a') - ('9' + 1));
      51             : 
      52        2022 :     int idx(sizeof(buf));
      53        2022 :     unsigned __int128 y(x < 0
      54        2022 :         ? -static_cast<unsigned __int128>(x)
      55             :         : static_cast<unsigned __int128>(x));
      56       36058 :     while(y >= static_cast<unsigned __int128>(base))
      57             :     {
      58       17018 :         --idx;
      59       17018 :         buf[idx] = y % base + '0';
      60       17018 :         if(buf[idx] > '9')
      61             :         {
      62           0 :             buf[idx] += adjust;
      63             :         }
      64       17018 :         y /= base;
      65             :     }
      66        2022 :     --idx;
      67        2022 :     buf[idx] = y + '0';
      68        2022 :     if(buf[idx] > '9')
      69             :     {
      70           0 :         buf[idx] += adjust;
      71             :     }
      72        2022 :     if(x < 0)
      73             :     {
      74        1011 :         --idx;
      75        1011 :         buf[idx] = '-';
      76             :     }
      77             : 
      78        2022 :     return std::string(buf + idx, sizeof(buf) - idx);
      79             : }
      80             : #pragma GCC diagnostic pop
      81             : 
      82             : 
      83             : /** \brief Convert an unsigned __int128 to a string.
      84             :  *
      85             :  * This function converts an unsigned __int128 to a string.
      86             :  *
      87             :  * \param[in] x  An unsigned __int128 number.
      88             :  *
      89             :  * \return A string representing that unsigned __int128 number.
      90             :  */
      91             : #pragma GCC diagnostic push
      92             : #pragma GCC diagnostic ignored "-Wpedantic"
      93         132 : inline std::string to_string(unsigned __int128 x, unsigned __int128 base = 10, bool uppercase = false)
      94             : {
      95         132 :     char buf[128];  // binary requires 128 chars
      96             : 
      97         132 :     char const adjust((uppercase ? 'A' : 'a') - ('9' + 1));
      98             : 
      99         132 :     int idx(sizeof(buf));
     100        4690 :     while(x >= base)
     101             :     {
     102        2279 :         --idx;
     103        2279 :         buf[idx] = x % base + '0';
     104        2279 :         if(buf[idx] > '9')
     105             :         {
     106        1348 :             buf[idx] += adjust;
     107             :         }
     108        2279 :         x /= base;
     109             :     }
     110         132 :     --idx;
     111         132 :     buf[idx] = x + '0';
     112         132 :     if(buf[idx] > '9')
     113             :     {
     114          48 :         buf[idx] += adjust;
     115             :     }
     116             : 
     117         132 :     return std::string(buf + idx, sizeof(buf) - idx);
     118             : }
     119             : #pragma GCC diagnostic pop
     120             : 
     121             : } //namespace snap
     122             : 
     123             : 
     124             : // no namespace for operators, it's easier that way
     125             : 
     126             : 
     127             : /** \brief Output an __int128 number.
     128             :  *
     129             :  * This function outputs the specified __int128 number to this output
     130             :  * stream. It respects the base and for hexadecimal, it also respects
     131             :  * the uppercase format.
     132             :  *
     133             :  * \note
     134             :  * The hexadecimal and octal formats do not understand negative numbers.
     135             :  * This function respects the C++ definition and prints out unsigned
     136             :  * numbers when one of the std::hex or std::oct format are set. If you
     137             :  * would prefer a negative number (i.e. -0x1 instead of 0xfff...fff)
     138             :  * then make sure to directly call the snapdev::to_string() function
     139             :  * instead.
     140             :  *
     141             :  * \warning
     142             :  * This implementation does not offer proper formatting.
     143             :  * It will first generate a string then output that string
     144             :  * which means the result is not what you'd expect if you
     145             :  * used formatting such as std::setfill() and std::setw().
     146             :  *
     147             :  * \param[in] os  The output stream.
     148             :  * \param[in] x  The value to be output in \p os.
     149             :  *
     150             :  * \return A reference to \p os.
     151             :  */
     152             : #pragma GCC diagnostic push
     153             : #pragma GCC diagnostic ignored "-Wpedantic"
     154        2149 : inline std::ostream & operator << (std::ostream & os, __int128 x)
     155             : {
     156        2149 :     std::ios_base::fmtflags const fmt(os.flags() & std::ios_base::basefield);
     157        2149 :     if(fmt == std::ios_base::oct)
     158             :     {
     159          42 :         if(os.flags() & std::ios_base::showbase)
     160             :         {
     161          21 :             os << '0';
     162             :         }
     163          42 :         return os << snapdev::to_string(static_cast<unsigned __int128>(x), 8);
     164             :     }
     165        2107 :     else if(fmt == std::ios_base::hex)
     166             :     {
     167          85 :         if(os.flags() & std::ios_base::showbase)
     168             :         {
     169          42 :             if(os.flags() & std::ios_base::uppercase)
     170             :             {
     171          21 :                 os << "0X";
     172             :             }
     173             :             else
     174             :             {
     175          21 :                 os << "0x";
     176             :             }
     177             :         }
     178          85 :         return os << snapdev::to_string(static_cast<unsigned __int128>(x), 16, (os.flags() & std::ios_base::uppercase) != 0);
     179             :     }
     180        2022 :     return os << snapdev::to_string(x);
     181             : }
     182             : #pragma GCC diagnostic pop
     183             : 
     184             : 
     185             : /** \brief Output an unsigned __int128 number.
     186             :  *
     187             :  * This function outputs the specified __int128 number to this output
     188             :  * stream. It respects the base and for hexadecimal, it also respects
     189             :  * the uppercase format.
     190             :  *
     191             :  * \warning
     192             :  * This implementation does not offer proper formatting.
     193             :  * It will first generate a string then output that string
     194             :  * which means the result is not what you'd expect if you
     195             :  * used formatting such as std::setfill() and std::setw().
     196             :  *
     197             :  * \param[in] os  The output stream.
     198             :  * \param[in] x  The value to be output in \p os.
     199             :  *
     200             :  * \return A reference to \p os.
     201             :  */
     202             : #pragma GCC diagnostic push
     203             : #pragma GCC diagnostic ignored "-Wpedantic"
     204           5 : inline std::ostream & operator << (std::ostream & os, unsigned __int128 x)
     205             : {
     206           5 :     std::ios_base::fmtflags const fmt(os.flags() & std::ios_base::basefield);
     207           5 :     int base(10);
     208           5 :     bool uppercase(false);
     209           5 :     if(fmt == std::ios_base::oct)
     210             :     {
     211           0 :         base = 8;
     212           0 :         if(os.flags() & std::ios_base::showbase)
     213             :         {
     214           0 :             os << '0';
     215             :         }
     216             :     }
     217           5 :     else if(fmt == std::ios_base::hex)
     218             :     {
     219           4 :         uppercase = (os.flags() & std::ios_base::uppercase) != 0;
     220           4 :         base = 16;
     221           4 :         if(os.flags() & std::ios_base::showbase)
     222             :         {
     223           2 :             if(uppercase)
     224             :             {
     225           1 :                 os << "0X";
     226             :             }
     227             :             else
     228             :             {
     229           1 :                 os << "0x";
     230             :             }
     231             :         }
     232             :     }
     233           5 :     return os << snapdev::to_string(x, base, uppercase);
     234             : }
     235             : #pragma GCC diagnostic pop
     236             : 
     237             : 
     238             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13