diff options
Diffstat (limited to 'src/openvic/utility')
-rw-r--r-- | src/openvic/utility/BMP.cpp | 163 | ||||
-rw-r--r-- | src/openvic/utility/BMP.hpp | 51 | ||||
-rw-r--r-- | src/openvic/utility/Logger.cpp | 20 | ||||
-rw-r--r-- | src/openvic/utility/Logger.hpp | 87 | ||||
-rw-r--r-- | src/openvic/utility/NumberUtils.hpp | 27 | ||||
-rw-r--r-- | src/openvic/utility/StringUtils.hpp | 127 |
6 files changed, 0 insertions, 475 deletions
diff --git a/src/openvic/utility/BMP.cpp b/src/openvic/utility/BMP.cpp deleted file mode 100644 index 0ea0f30..0000000 --- a/src/openvic/utility/BMP.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "BMP.hpp" - -#include <cstring> -#include <set> - -#include "openvic/utility/Logger.hpp" - -using namespace OpenVic; - -BMP::~BMP() { - close(); -} - -bool BMP::open(char const* filepath) { - reset(); - errno = 0; - file = fopen(filepath, "rb"); - if (file == nullptr || errno != 0) { - Logger::error("Failed to open BMP file \"", filepath, "\" (errno = ", errno, ")"); - file = nullptr; - return false; - } - return true; -} - -bool BMP::read_header() { - if (header_validated) { - Logger::error("BMP header already validated!"); - return false; - } - if (file == nullptr) { - Logger::error("Cannot read BMP header before opening a file"); - return false; - } - if (fseek(file, 0, SEEK_SET) != 0) { - Logger::error("Failed to move to the beginning of the BMP file!"); - return false; - } - if (fread(&header, sizeof(header), 1, file) != 1) { - Logger::error("Failed to read BMP header!"); - return false; - } - - header_validated = true; - - // Validate constants - static constexpr uint16_t BMP_SIGNATURE = 0x4d42; - if (header.signature != BMP_SIGNATURE) { - Logger::error("Invalid BMP signature: ", header.signature, " (must be ", BMP_SIGNATURE, ")"); - header_validated = false; - } - static constexpr uint32_t DIB_HEADER_SIZE = 40; - if (header.dib_header_size != DIB_HEADER_SIZE) { - Logger::error("Invalid BMP DIB header size: ", header.dib_header_size, " (must be ", DIB_HEADER_SIZE, ")"); - header_validated = false; - } - static constexpr uint16_t NUM_PLANES = 1; - if (header.num_planes != NUM_PLANES) { - Logger::error("Invalid BMP plane count: ", header.num_planes, " (must be ", NUM_PLANES, ")"); - header_validated = false; - } - static constexpr uint16_t COMPRESSION = 0; // Only support uncompressed BMPs - if (header.compression != COMPRESSION) { - Logger::error("Invalid BMP compression method: ", header.compression, " (must be ", COMPRESSION, ")"); - header_validated = false; - } - - // Validate sizes and dimensions - // TODO - image_size_bytes can be 0 for non-compressed BMPs - if (header.file_size != header.offset + header.image_size_bytes) { - Logger::error("Invalid BMP memory sizes: file size = ", header.file_size, " != ", header.offset + header.image_size_bytes, - " = ", header.offset, " + ", header.image_size_bytes, " = image data offset + image data size"); - header_validated = false; - } - // TODO - support negative widths (i.e. horizontal flip) - if (header.width_px <= 0) { - Logger::error("Invalid BMP width: ", header.width_px, " (must be positive)"); - header_validated = false; - } - // TODO - support negative heights (i.e. vertical flip) - if (header.height_px <= 0) { - Logger::error("Invalid BMP height: ", header.height_px, " (must be positive)"); - header_validated = false; - } - // TODO - validate x_resolution_ppm - // TODO - validate y_resolution_ppm - - // Validate colours -#define VALID_BITS_PER_PIXEL 1, 2, 4, 8, 16, 24, 32 -#define STR(x) #x - static const std::set<uint16_t> BITS_PER_PIXEL { VALID_BITS_PER_PIXEL }; - if (!BITS_PER_PIXEL.contains(header.bits_per_pixel)) { - Logger::error("Invalid BMP bits per pixel: ", header.bits_per_pixel, " (must be one of " STR(VALID_BITS_PER_PIXEL) ")"); - header_validated = false; - } -#undef VALID_BITS_PER_PIXEL -#undef STR - static constexpr uint16_t PALETTE_BITS_PER_PIXEL_LIMIT = 8; - if (header.num_colours != 0 && header.bits_per_pixel > PALETTE_BITS_PER_PIXEL_LIMIT) { - Logger::error("Invalid BMP palette size: ", header.num_colours, " (should be 0 as bits per pixel is ", header.bits_per_pixel, " > 8)"); - header_validated = false; - } - // TODO - validate important_colours - - palette_size = header.bits_per_pixel > PALETTE_BITS_PER_PIXEL_LIMIT ? 0 - // Use header.num_colours if it's greater than 0 and at most 1 << header.bits_per_pixel - : 0 < header.num_colours && header.num_colours - 1 >> header.bits_per_pixel == 0 ? header.num_colours - : 1 << header.bits_per_pixel; - - const uint32_t expected_offset = palette_size * PALETTE_COLOUR_SIZE + sizeof(header); - if (header.offset != expected_offset) { - Logger::error("Invalid BMP image data offset: ", header.offset, " (should be ", expected_offset, ")"); - header_validated = false; - } - - return header_validated; -} - -bool BMP::read_palette() { - if (file == nullptr) { - Logger::error("Cannot read BMP palette before opening a file"); - return false; - } - if (!header_validated) { - Logger::error("Cannot read palette before BMP header is validated!"); - return false; - } - if (palette_size == 0) { - Logger::error("Cannot read BMP palette - header indicates this file doesn't have one"); - return false; - } - if (fseek(file, sizeof(header), SEEK_SET) != 0) { - Logger::error("Failed to move to the palette in the BMP file!"); - return false; - } - palette.resize(palette_size); - if (fread(palette.data(), palette_size * PALETTE_COLOUR_SIZE, 1, file) != 1) { - Logger::error("Failed to read BMP header!"); - palette.clear(); - return false; - } - return true; -} - -void BMP::close() { - if (file != nullptr) { - if (fclose(file) != 0) - Logger::error("Failed to close BMP!"); - file = nullptr; - } -} - -void BMP::reset() { - close(); - memset(&header, 0, sizeof(header)); - header_validated = false; - palette_size = 0; - palette.clear(); -} - -std::vector<colour_t> const& BMP::get_palette() const { - return palette; -} diff --git a/src/openvic/utility/BMP.hpp b/src/openvic/utility/BMP.hpp deleted file mode 100644 index 7ed36a5..0000000 --- a/src/openvic/utility/BMP.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include <cstdio> -#include <vector> - -#include "openvic/types/Colour.hpp" - -namespace OpenVic { - class BMP { -#pragma pack(push) -#pragma pack(1) - struct header_t { - uint16_t signature; // Signature: 0x4d42 (or 'B' 'M') - uint32_t file_size; // File size in bytes - uint16_t reserved1; // Not used - uint16_t reserved2; // Not used - uint32_t offset; // Offset to image data in bytes from beginning of file - uint32_t dib_header_size; // DIB header size in bytes - int32_t width_px; // Width of the image - int32_t height_px; // Height of image - uint16_t num_planes; // Number of colour planes - uint16_t bits_per_pixel; // Bits per pixel - uint32_t compression; // Compression type - uint32_t image_size_bytes; // Image size in bytes - int32_t x_resolution_ppm; // Pixels per meter - int32_t y_resolution_ppm; // Pixels per meter - uint32_t num_colours; // Number of colours - uint32_t important_colours; // Important colours - } header; -#pragma pack(pop) - - FILE* file = nullptr; - bool header_validated = false; - uint32_t palette_size = 0; - std::vector<colour_t> palette; - - public: - static constexpr uint32_t PALETTE_COLOUR_SIZE = sizeof(colour_t); - - BMP() = default; - ~BMP(); - - bool open(char const* filepath); - bool read_header(); - bool read_palette(); - void close(); - void reset(); - - std::vector<colour_t> const& get_palette() const; - }; -} diff --git a/src/openvic/utility/Logger.cpp b/src/openvic/utility/Logger.cpp deleted file mode 100644 index bf9a67c..0000000 --- a/src/openvic/utility/Logger.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Logger.hpp" - -#include <iostream> - -using namespace OpenVic; - -Logger::log_func_t Logger::info_func {}; -Logger::log_queue_t Logger::info_queue {}; -Logger::log_func_t Logger::error_func {}; -Logger::log_queue_t Logger::error_queue {}; - -char const* Logger::get_filename(char const* filepath) { - if (filepath == nullptr) return nullptr; - char const* last_slash = filepath; - while (*filepath != '\0') { - if (*filepath == '\\' || *filepath == '/') last_slash = filepath + 1; - filepath++; - } - return last_slash; -} diff --git a/src/openvic/utility/Logger.hpp b/src/openvic/utility/Logger.hpp deleted file mode 100644 index 417aba7..0000000 --- a/src/openvic/utility/Logger.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#include <functional> -#include <queue> -#include <sstream> -#ifdef __cpp_lib_source_location -#include <source_location> -#endif - -namespace OpenVic { - -#ifndef __cpp_lib_source_location -#include <string> - // Implementation of std::source_location for compilers that do not support it - // Note: uses non-standard extensions that are supported by Clang, GCC, and MSVC - // https://clang.llvm.org/docs/LanguageExtensions.html#source-location-builtins - // https://stackoverflow.com/a/67970107 - class source_location { - std::string _file; - int _line; - std::string _function; - - public: - source_location(std::string f, int l, std::string n) : _file(f), _line(l), _function(n) {} - static source_location current(std::string f = __builtin_FILE(), int l = __builtin_LINE(), std::string n = __builtin_FUNCTION()) { - return source_location(f, l, n); - } - - inline char const* file_name() const { return _file.c_str(); } - inline int line() const { return _line; } - inline char const* function_name() const { return _function.c_str(); } - }; -#endif - - class Logger { - using log_func_t = std::function<void(std::string&&)>; - using log_queue_t = std::queue<std::string>; - -#ifdef __cpp_lib_source_location - using source_location = std::source_location; -#else - using source_location = OpenVic::source_location; -#endif - - static char const* get_filename(char const* filepath); - - template<typename... Ts> - struct log { - log(log_func_t log_func, log_queue_t& log_queue, Ts&&... ts, source_location const& location) { - std::stringstream stream; - stream << "\n" << get_filename(location.file_name()) << "(" - << location.line() << ") `" << location.function_name() << "`: "; - ((stream << std::forward<Ts>(ts)), ...); - stream << std::endl; - log_queue.push(stream.str()); - if (log_func) { - do { - log_func(std::move(log_queue.front())); - log_queue.pop(); - } while (!log_queue.empty()); - } - } - }; - -#define LOG_FUNC(name) \ - private: \ - static log_func_t name##_func; \ - static log_queue_t name##_queue; \ - public: \ - static void set_##name##_func(log_func_t log_func) { \ - name##_func = log_func; \ - } \ - template <typename... Ts> \ - struct name { \ - name(Ts&&... ts, source_location const& location = source_location::current()) { \ - log<Ts...>{ name##_func, name##_queue, std::forward<Ts>(ts)..., location }; \ - } \ - }; \ - template <typename... Ts> \ - name(Ts&&...) -> name<Ts...>; - - LOG_FUNC(info) - LOG_FUNC(error) - -#undef LOG_FUNC - }; -} diff --git a/src/openvic/utility/NumberUtils.hpp b/src/openvic/utility/NumberUtils.hpp deleted file mode 100644 index 6211772..0000000 --- a/src/openvic/utility/NumberUtils.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#include <cstdint> - -namespace OpenVic::NumberUtils { - constexpr int64_t round_to_int64(float num) { - return (num > 0.0f) ? (num + 0.5f) : (num - 0.5f); - } - - constexpr int64_t round_to_int64(double num) { - return (num > 0.0) ? (num + 0.5) : (num - 0.5); - } - - constexpr uint64_t pow(uint64_t base, size_t exponent) { - uint64_t ret = 1; - while (exponent-- > 0) { - ret *= base; - } - return ret; - } - - constexpr int64_t pow(int64_t base, size_t exponent) { - int64_t ret = 1; - while (exponent-- > 0) { - ret *= base; - } - return ret; - } -} diff --git a/src/openvic/utility/StringUtils.hpp b/src/openvic/utility/StringUtils.hpp deleted file mode 100644 index 5d6001c..0000000 --- a/src/openvic/utility/StringUtils.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#include <cstdint> -#include <limits> -#include <string_view> - -namespace OpenVic::StringUtils { - /* The constexpr function 'string_to_uint64' will convert a string into a uint64_t integer value. - * The function takes four parameters: the input string (as a pair of pointers marking the start and - * end of the string), a bool pointer for reporting success, and the base for numerical conversion. - * The base parameter defaults to 10 (decimal), but it can be any value between 2 and 36. If the base - * given is 0, it will be set to 16 if the string starts with "0x" or "0X", otherwise 8 if the string - * still starts with "0", otherwise 10. The success bool pointer parameter is used to report whether - * or not conversion was successful. It can be nullptr if this information is not needed. - */ - constexpr uint64_t string_to_uint64(char const* str, const char* const end, bool* successful = nullptr, int base = 10) { - if (successful != nullptr) *successful = false; - - // Base value should be between 2 and 36. If it's not, return 0 as an invalid case. - if (str == nullptr || end <= str || base < 0 || base == 1 || base > 36) - return 0; - - // The result of the conversion will be stored in this variable. - uint64_t result = 0; - - // If base is zero, base is determined by the string prefix. - if (base == 0) { - if (*str == '0') { - if (str + 1 != end && (str[1] == 'x' || str[1] == 'X')) { - base = 16; // Hexadecimal. - str += 2; // Skip '0x' or '0X' - if (str == end) return 0; - } else { - base = 8; // Octal. - } - } else { - base = 10; // Decimal. - } - } else if (base == 16) { - // If base is 16 and string starts with '0x' or '0X', skip these characters. - if (*str == '0' && str + 1 != end && (str[1] == 'x' || str[1] == 'X')) { - str += 2; - if (str == end) return 0; - } - } - - // Convert the number in the string. - for (; str != end; ++str) { - int digit; - if (*str >= '0' && *str <= '9') { - digit = *str - '0'; // Calculate digit value for '0'-'9'. - } else if (*str >= 'a' && *str <= 'z') { - digit = *str - 'a' + 10; // Calculate digit value for 'a'-'z'. - } else if (*str >= 'A' && *str <= 'Z') { - digit = *str - 'A' + 10; // Calculate digit value for 'A'-'Z'. - } else { - break; // Stop conversion if current character is not a digit. - } - - if (digit >= base) { - break; // Stop conversion if current digit is greater than or equal to the base. - } - - // Check for overflow on multiplication - if (result > std::numeric_limits<uint64_t>::max() / base) { - return std::numeric_limits<uint64_t>::max(); - } - - result *= base; - - // Check for overflow on addition - if (result > std::numeric_limits<uint64_t>::max() - digit) { - return std::numeric_limits<uint64_t>::max(); - } - - result += digit; - } - - // If successful is not null and the entire string was parsed, - // set *successful to true (if not it is already false). - if (successful != nullptr && str == end) *successful = true; - - return result; - } - - constexpr uint64_t string_to_uint64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { - return string_to_uint64(str, str + length, successful, base); - } - - inline uint64_t string_to_uint64(const std::string_view str, bool* successful = nullptr, int base = 10) { - return string_to_uint64(str.data(), str.length(), successful, base); - } - - constexpr int64_t string_to_int64(char const* str, const char* const end, bool* successful = nullptr, int base = 10) { - if (successful != nullptr) *successful = false; - - if (str == nullptr || end <= str) return 0; - - // This flag will be set if the number is negative. - bool is_negative = false; - - // Check if there is a sign character. - if (*str == '+' || *str == '-') { - if (*str == '-') - is_negative = true; - ++str; - if (str == end) return 0; - } - - const uint64_t result = string_to_uint64(str, end, successful, base); - if (!is_negative) { - if (result >= std::numeric_limits<int64_t>::max()) - return std::numeric_limits<int64_t>::max(); - return result; - } else { - if (result > std::numeric_limits<int64_t>::max()) - return std::numeric_limits<int64_t>::min(); - return -result; - } - } - - constexpr int64_t string_to_int64(char const* str, size_t length, bool* successful = nullptr, int base = 10) { - return string_to_int64(str, str + length, successful, base); - } - - inline int64_t string_to_int64(const std::string_view str, bool* successful = nullptr, int base = 10) { - return string_to_int64(str.data(), str.length(), successful, base); - } -} |