# Program Listing for File utilities.hpp

↰ Return to documentation for file (`cif++/utilities.hpp`)

    /*-
     * 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
    #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);

      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