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 <cstdint>
#include <filesystem>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>

#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)

// Truncation warnings: yes, perhaps, but I think they are okay
# pragma warning(disable : 4244)
# pragma warning(disable : 4267)
# pragma warning(disable : 4305)

# define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING 1
#endif


namespace cif
{

extern CIFPP_EXPORT int VERBOSE;

[[nodiscard]] std::string get_version_nr();

[[nodiscard]] uint32_t get_terminal_width();

// --------------------------------------------------------------------

namespace colour
{
    enum colour_type
    {
        black,
        red,
        green,
        yellow,
        blue,
        magenta,
        cyan,
        white,
        _unused,
        none
    };

    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(coloured_string_t &) = delete;
            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)
            {
                if ((os.rdbuf() == std::cout.rdbuf() and isatty(STDOUT_FILENO)) or (os.rdbuf() == std::cerr.rdbuf() and isatty(STDERR_FILENO)))
                {
                    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(const progress_bar &) = delete;
    progress_bar &operator=(const progress_bar &) = delete;


    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:
    struct progress_bar_impl *m_impl = nullptr;
};

// --------------------------------------------------------------------
// 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