
.. _program_listing_file_cif++_utilities.hpp:

Program Listing for File utilities.hpp
======================================

|exhale_lsh| :ref:`Return to documentation for file <file_cif++_utilities.hpp>` (``cif++/utilities.hpp``)

.. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS

.. code-block:: cpp

   /*-
    * SPDX-License-Identifier: BSD-2-Clause
    *
    * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    *    list of conditions and the following disclaimer
    * 2. Redistributions in binary form must reproduce the above copyright notice,
    *    this list of conditions and the following disclaimer in the documentation
    *    and/or other materials provided with the distribution.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
   
   #pragma once
   
   #include "cif++/exports.hpp"
   
   #include <filesystem>
   #include <iostream>
   
   #ifndef STDOUT_FILENO
   #define STDOUT_FILENO 1
   #endif
   
   #ifndef STDERR_FILENO
   #define STDERR_FILENO 2
   #endif
   
   #if _WIN32
   #include <io.h>
   #define isatty _isatty
   #else
   #include <unistd.h>
   #endif
   
   #if _MSC_VER
   #pragma warning(disable : 4996) // unsafe function or variable  (strcpy e.g.)
   #pragma warning(disable : 4068) // unknown pragma
   #pragma warning(disable : 4100) // unreferenced formal parameter
   #pragma warning(disable : 4101) // unreferenced local variable
   #pragma warning(disable : 4702) // unreachable code (too bad, this one. Happens in for loops)
   #define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING 1
   #endif
   
   namespace cif
   {
   
   extern CIFPP_EXPORT int VERBOSE;
   
   std::string get_version_nr();
   
   uint32_t get_terminal_width();
   
   // --------------------------------------------------------------------
   
   namespace colour
   {
       enum colour_type
       {
           black = 0,
           red,
           green,
           yellow,
           blue,
           magenta,
           cyan,
           white,
           none = 9
       };
   
       enum style_type
       {
           bold = 1,
           underlined = 4,
           blink = 5,
           inverse = 7,
           regular = 22,
       };
   
       namespace detail
       {
           struct coloured_string_t
           {
               coloured_string_t(std::string_view s, colour_type fc, colour_type bc, style_type st)
                   : m_str(s)
                   , m_fore_colour(static_cast<int>(fc) + 30)
                   , m_back_colour(static_cast<int>(bc) + 40)
                   , m_style(static_cast<int>(st))
               {
               }
   
               coloured_string_t &operator=(coloured_string_t &) = delete;
   
               template <typename char_type, typename traits_type>
               friend std::basic_ostream<char_type, traits_type> &operator<<(
                   std::basic_ostream<char_type, traits_type> &os, const coloured_string_t &cs)
               {
                   bool use_colour = false;
   
                   if (os.rdbuf() == std::cout.rdbuf() and isatty(STDOUT_FILENO))
                       use_colour = true;
                   else if (os.rdbuf() == std::cerr.rdbuf() and isatty(STDERR_FILENO))
                       use_colour = true;
   
                   if (use_colour)
                   {
                       os << "\033[" << cs.m_fore_colour << ';' << cs.m_style << ';' << cs.m_back_colour << 'm'
                          << cs.m_str
                          << "\033[0m";
                   }
                   else
                       os << cs.m_str;
   
                   return os;
               }
   
               std::string_view m_str;
               int m_fore_colour, m_back_colour;
               int m_style;
           };
   
       } // namespace detail
   } // namespace colour
   
   template <typename T>
       requires std::is_assignable_v<std::string_view, T>
   inline auto coloured(T str,
       colour::colour_type fg, colour::colour_type bg = colour::colour_type::none,
       colour::style_type st = colour::style_type::regular)
   {
       return colour::detail::coloured_string_t(str, fg, bg, st);
   }
   
   // --------------------------------------------------------------------
   //  A progress bar
   
   class progress_bar
   {
     public:
       progress_bar(int64_t inMax, const std::string &inAction);
   
       ~progress_bar();
   
       void consumed(int64_t inConsumed); // consumed is relative
   
       void progress(int64_t inProgress); // progress is absolute
   
       void message(const std::string &inMessage);
   
       void flush();
   
     private:
       progress_bar(const progress_bar &) = delete;
       progress_bar &operator=(const progress_bar &) = delete;
   
       struct progress_bar_impl *m_impl;
   };
   
   // --------------------------------------------------------------------
   // Resources
   
   std::unique_ptr<std::istream> load_resource(std::filesystem::path name);
   
   void add_file_resource(const std::string &name, std::filesystem::path dataFile);
   
   void list_file_resources(std::ostream &os);
   
   void add_data_directory(std::filesystem::path dataDir);
   
   void list_data_directories(std::ostream &os);
   
   } // namespace cif
