LCOV - code coverage report
Current view: top level - snapdev - isatty.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 14 15 93.3 %
Date: 2022-07-09 19:51:09 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-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             : // C++
      22             : //
      23             : #include    <fstream>
      24             : #include    <iostream>
      25             : #include    <ext/stdio_filebuf.h>
      26             : #include    <ext/stdio_sync_filebuf.h>
      27             : 
      28             : // C
      29             : //
      30             : #include    <unistd.h>
      31             : 
      32             : 
      33             : 
      34             : namespace snapdev
      35             : {
      36             : 
      37             : 
      38             : 
      39             : namespace detail
      40             : {
      41             : 
      42             : template<typename _CharT
      43             :        , typename _Traits = std::char_traits<_CharT>>
      44             : class our_basic_filebuf
      45             :     : public std::basic_filebuf<_CharT, _Traits>
      46             : {
      47             : public:
      48           1 :     std::__c_file * file() throw()
      49             :     {
      50             :         //return std::basic_filebuf<_CharT, _Traits>::_M_file.file();
      51           1 :         return this->_M_file.file();
      52             :     }
      53             : };
      54             : 
      55             : } // namespace detail
      56             : 
      57             : 
      58             : 
      59             : /** \brief Check whether a C++ iostream is a TTY.
      60             :  *
      61             :  * This function checks the specified stream and if it represents a TTY
      62             :  * returns true.
      63             :  *
      64             :  * If the stream is not a standard file stream, then the function always
      65             :  * returns false, even if ultimately the stream does represent a TTY. This
      66             :  * is because we can really only handle the standard fstream's objects here.
      67             :  *
      68             :  * \note
      69             :  * The function dynamic casts to a the three different types of buffers
      70             :  * to see whether we can find a file() function. If so, then we check
      71             :  * that the file isatty() or not.
      72             :  *
      73             :  * \tparam _CharT  type of character this stream handles.
      74             :  * \tparam _Traits  traits of the characters based on CharT by default.
      75             :  * \param[in] stream  The stream to check.
      76             :  *
      77             :  * \return true if \p stream is a TTY.
      78             :  */
      79             : template<typename _CharT
      80             :        , typename _Traits = std::char_traits<_CharT>>
      81           6 : bool isatty(std::basic_ios<_CharT, _Traits> const & s)
      82             : {
      83             :     // in most cases, we use cin, cout, cerr, or clog which are all
      84             :     // stdio_sync_filebuf<> objects
      85             :     {
      86             :         typedef __gnu_cxx::stdio_sync_filebuf<_CharT, _Traits> io_sync_buffer_t;
      87           6 :         io_sync_buffer_t * buffer(dynamic_cast<io_sync_buffer_t *>(s.rdbuf()));
      88           6 :         if(buffer != nullptr)
      89             :         {
      90           4 :             return ::isatty(fileno(buffer->file()));
      91             :         }
      92             :     }
      93             : 
      94             :     {
      95             :         typedef __gnu_cxx::stdio_filebuf<_CharT, _Traits> io_buffer_t;
      96           2 :         io_buffer_t * buffer(dynamic_cast<io_buffer_t *>(s.rdbuf()));
      97           2 :         if(buffer != nullptr)
      98             :         {
      99           0 :             return ::isatty(fileno(buffer->file()));
     100             :         }
     101             :     }
     102             : 
     103             :     // in this case, we first do a dynamic_cast<>() to make sure we find the
     104             :     // correct buffer; if present we can do a static_cast<>() to gain access
     105             :     // to the _M_file field and thus the file() function (there is also an
     106             :     // fd() function, but to be consistent with the other cases, I used a
     107             :     // file() like function only)
     108             :     {
     109             :         typedef std::basic_filebuf<_CharT, _Traits> file_buffer_t;
     110           2 :         file_buffer_t * file_buffer(dynamic_cast<file_buffer_t *>(s.rdbuf()));
     111           2 :         if(file_buffer != nullptr)
     112             :         {
     113             :             typedef detail::our_basic_filebuf<_CharT, _Traits> hack_buffer_t;
     114           1 :             hack_buffer_t * buffer(static_cast<hack_buffer_t *>(file_buffer));
     115           1 :             if(buffer != nullptr)
     116             :             {
     117           1 :                 return ::isatty(fileno(buffer->file()));
     118             :             }
     119             :         }
     120             :     }
     121             : 
     122           1 :     return false;
     123             : }
     124             : 
     125             : 
     126             : 
     127             : } // namespace snapdev
     128             : // vim: ts=4 sw=4 et
     129             : 

Generated by: LCOV version 1.13