diff --git a/apps/notes_tk/main.cpp b/apps/notes_tk/main.cpp index f864fb8..997d80f 100644 --- a/apps/notes_tk/main.cpp +++ b/apps/notes_tk/main.cpp @@ -12,7 +12,7 @@ int main(int argc, char *argv[]) // Start the gui app auto app = NotesTk(std::move(args)); - //app.setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); + app.setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER); app.run(); return 0; diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..addd2f6 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +SOURCE_DIR=$SCRIPT_DIR/src + +g++ $SOURCE_DIR/main.cpp \ + $SOURCE_DIR/base/core/base_types/Error.cpp \ + $SOURCE_DIR/base/core/base_types/Index.cpp \ + $SOURCE_DIR/base/core/data_structures/String.cpp \ + $SOURCE_DIR/base/core/file_utilities/FileSystemPath.cpp \ + $SOURCE_DIR/base/core/file_utilities/File.cpp \ + $SOURCE_DIR/base/core/file_utilities/Directory.cpp \ + $SOURCE_DIR/base/core/encoding/CharUtils.cpp \ + -o builder -g -fno-exceptions -fno-rtti \ + -I$SOURCE_DIR/base/core/data_structures \ + -I$SOURCE_DIR/base/core/base_types \ + -I$SOURCE_DIR/base/core/memory \ + -I$SOURCE_DIR/base/core/loggers \ + -I$SOURCE_DIR/base/core/encoding \ + -I$SOURCE_DIR/base/core/file_utilities diff --git a/src/base/compiler/KScope.cpp b/src/base/compiler/KScope.cpp new file mode 100644 index 0000000..ea1d70f --- /dev/null +++ b/src/base/compiler/KScope.cpp @@ -0,0 +1,78 @@ +#include "KScope.h" + +#include + +void KScopeLexer::run(const FileSystemPath& path) +{ + printf("Before read"); + File f(path); + + const auto content = f<.readText(); + printf("Content is: %s\n", content); + fflush(stdout); + + Vector tokens; + for(const auto c : content.data()) + { + printf("Char is: %c\n", c); + if (CharUtils::is_space(c)) + { + if (m_working_token.is_identifier() || m_working_token.is_number()) + { + on_token_finished(tokens); + } + } + else if (CharUtils::is_alpha(c)) + { + if (m_working_token.is_number()) + { + on_token_finished(tokens); + m_working_token = Token(); + m_working_token.set_is_identifier(); + } + else if (!m_working_token.is_identifier()) + { + m_working_token = Token(); + m_working_token.set_is_identifier(); + } + m_working_token.m_value += c; + } + else if (CharUtils::is_digit(c)) + { + if (m_working_token.is_number() || m_working_token.is_identifier()) + { + m_working_token.m_value += c; + } + else + { + m_working_token = Token(); + m_working_token.set_is_number(); + m_working_token.m_value += c; + } + } + else + { + if (m_working_token.is_identifier() || m_working_token.is_number()) + { + on_token_finished(tokens); + } + + m_working_token.set_is_literal(); + m_working_token.m_value += c; + on_token_finished(tokens); + } + } + on_token_finished(tokens); +} + +void KScopeLexer::on_token_finished(Vector& tokens) +{ + if (m_working_token.m_type == TokenT::NONE) + { + return; + } + + m_working_token.on_finished(); + tokens.push_back(m_working_token); + m_working_token = Token(); +} \ No newline at end of file diff --git a/src/base/compiler/KScope.h b/src/base/compiler/KScope.h new file mode 100644 index 0000000..243ec7b --- /dev/null +++ b/src/base/compiler/KScope.h @@ -0,0 +1,86 @@ +#pragma once + +#include "String.h" +#include "File.h" +#include "Vector.h" +#include "CharUtils.h" + +class KScopeLexer +{ +public: + enum class TokenT + { + NONE, + DEF, // LANG COMMANDS + EXTERN, + IDENTIFIER ,// GENERAL + LITERAL, + NUMBER + }; + + struct Token + { + bool is_identifier() const + { + return m_type == TokenT::IDENTIFIER; + } + + bool is_number() const + { + return m_type == TokenT::NUMBER; + } + + void set_is_identifier() + { + m_type = TokenT::IDENTIFIER; + } + + void set_is_number() + { + m_type = TokenT::NUMBER; + } + + void set_is_literal() + { + m_type = TokenT::LITERAL; + } + + void on_identifier_finished() + { + if (m_value == "def") + { + m_type = TokenT::DEF; + } + else if (m_value == "extern") + { + m_type = TokenT::EXTERN; + } + } + + void on_number_finished() + { + + } + + void on_finished() + { + if (is_identifier()) + { + on_identifier_finished(); + } + else if(is_number()) + { + on_number_finished(); + } + } + + TokenT m_type{TokenT::NONE}; + String m_value; + }; + + void run(const FileSystemPath& path); + + void on_token_finished(Vector& tokens); + + Token m_working_token; +}; \ No newline at end of file diff --git a/src/base/compression/Lz77Encoder.h b/src/base/compression/Lz77Encoder.h index 0d3ec85..64ecb79 100644 --- a/src/base/compression/Lz77Encoder.h +++ b/src/base/compression/Lz77Encoder.h @@ -33,8 +33,8 @@ public: bool hitBufferFull() const; private: - bool lookAheadSourceEmpty() const; + unsigned char getSearchBufferItem(unsigned index) const; unsigned lookAheadForMatchingChars(unsigned searchIndex); diff --git a/src/base/core/CMakeLists.txt b/src/base/core/CMakeLists.txt index d3c607d..2832eb9 100644 --- a/src/base/core/CMakeLists.txt +++ b/src/base/core/CMakeLists.txt @@ -40,8 +40,11 @@ list(APPEND SOURCES Dictionary.cpp Color.cpp CommandLineArgs.cpp + memory/Allocator.cpp data_structures/RawTree.cpp data_structures/Tree.cpp + data_structures/Vector.cpp + data_structures/String.cpp loggers/FileLogger.cpp file_utilities/Directory.cpp file_utilities/File.cpp @@ -81,6 +84,7 @@ target_include_directories(${MODULE_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/memory ${CMAKE_CURRENT_SOURCE_DIR}/streams ${CMAKE_CURRENT_SOURCE_DIR}/http + ${CMAKE_CURRENT_SOURCE_DIR}/base_types ${CMAKE_CURRENT_SOURCE_DIR}/data_structures ${CMAKE_CURRENT_SOURCE_DIR}/serializers ${CMAKE_CURRENT_SOURCE_DIR}/xml diff --git a/src/base/core/Color.cpp b/src/base/core/Color.cpp index 2fd35da..779fcde 100644 --- a/src/base/core/Color.cpp +++ b/src/base/core/Color.cpp @@ -34,6 +34,77 @@ std::unique_ptr Color::Create(unsigned char r, unsigned char g, unsigned return std::make_unique(r, g, b, a); } +std::size_t Color::getSize() const +{ + return getSize(mFormat, mBitDepth); +} + +std::size_t Color::getSize(Format format, unsigned bitDepth) +{ + return getNumChannels(format) * bitDepth / 8; +} + +std::size_t Color::getNumChannels(Format format) +{ + if (format == Format::GRAYSCALE || format == Format::LUT) + { + return 1; + } + else + { + return 4; + } +} + +uint8_t Color::getByte(std::size_t index) const +{ + if (mFormat == Format::GRAYSCALE || mFormat == Format::LUT) + { + if (index > 0) + { + throw std::range_error("Color index out of range in getByte()"); + } + return mValue; + } + else if (mFormat == Format::ARGB) + { + switch(index) + { + case 0: + return mAlpha * 255; + case 1: + return mR; + case 2: + return mG; + case 3: + return mB; + default: + throw std::range_error("Color index out of range in getByte()"); + } + } + else + { + switch(index) + { + case 0: + return mR; + case 1: + return mG; + case 2: + return mB; + case 3: + return mAlpha * 255; + default: + throw std::range_error("Color index out of range in getByte()"); + } + } +} + +void Color::setAlpha(float alpha) +{ + mAlpha = static_cast(alpha); +} + std::unique_ptr Color::Create(const Color& color) { return std::make_unique(color); diff --git a/src/base/core/Color.h b/src/base/core/Color.h index ea70540..5246fd6 100644 --- a/src/base/core/Color.h +++ b/src/base/core/Color.h @@ -3,10 +3,20 @@ #include #include #include +#include class Color { public: + enum class Format + { + GRAYSCALE, + GRAYSCALE_ALPHA, + LUT, + RGB, + ARGB, + RGBA + }; Color(const std::string& hexString); Color(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, double a = 1.0); @@ -25,10 +35,15 @@ public: std::string toString() const; - void setAlpha(float alpha) - { - mAlpha = static_cast(alpha); - } + std::size_t getSize() const; + + static std::size_t getNumChannels(Format format); + + static std::size_t getSize(Format format, unsigned bitDepth); + + uint8_t getByte(std::size_t index) const; + + void setAlpha(float alpha); bool operator==(const Color& rhs) const { @@ -49,7 +64,10 @@ private: unsigned char mR{0}; unsigned char mG{0}; unsigned char mB{0}; + unsigned char mValue{0}; double mAlpha{0.0}; + unsigned mBitDepth{8}; + Format mFormat{Format::RGBA}; }; using ColorPtr = std::shared_ptr; diff --git a/src/base/core/CommandLineArgs.cpp b/src/base/core/CommandLineArgs.cpp index 26ef06c..1ae103a 100644 --- a/src/base/core/CommandLineArgs.cpp +++ b/src/base/core/CommandLineArgs.cpp @@ -34,37 +34,37 @@ void CommandLineArgs::initialize(CommandLineArgs* args) #endif } -std::unique_ptr CommandLineArgs::Create() +Ptr CommandLineArgs::Create() { - return std::make_unique(); + return Ptr::create(); } -std::filesystem::path CommandLineArgs::getLaunchPath() +FileSystemPath CommandLineArgs::getLaunchPath() { return mLaunchPath; } void CommandLineArgs::recordLaunchPath() { - mLaunchPath = std::filesystem::current_path(); + mLaunchPath = FileSystemPath::current_dir(); } void CommandLineArgs::process(int argc, char *argv[]) { for(int idx=0; idx& args) +void CommandLineArgs::process(const Vector& args) { mArugments = args; } -std::vector CommandLineArgs::getUserArgs() const +Vector CommandLineArgs::getUserArgs() const { - std::vector user_args; + Vector user_args; for(unsigned idx=1; idx CommandLineArgs::getUserArgs() const return user_args; } -const std::vector CommandLineArgs::getArgs() const +const Vector CommandLineArgs::getArgs() const { return mArugments; } diff --git a/src/base/core/CommandLineArgs.h b/src/base/core/CommandLineArgs.h index 9a39346..b3d9614 100644 --- a/src/base/core/CommandLineArgs.h +++ b/src/base/core/CommandLineArgs.h @@ -1,33 +1,31 @@ #pragma once -#include -#include -#include -#include +#include "Pointer.h" +#include "Vector.h" +#include "String.h" +#include "FileSystemPath.h" class CommandLineArgs { public: CommandLineArgs(); - static std::unique_ptr Create(); + static Ptr Create(); - std::filesystem::path getLaunchPath(); + FileSystemPath getLaunchPath(); - const std::vector getArgs() const; + const Vector getArgs() const; - std::vector getUserArgs() const; + Vector getUserArgs() const; static void initialize(CommandLineArgs* args); void process(int argc, char *argv[]); - void process(const std::vector& args); + void process(const Vector& args); void recordLaunchPath(); private: - std::vector mArugments; - std::filesystem::path mLaunchPath; -}; - -using CommandLineArgsUPtr = std::unique_ptr; + Vector mArugments; + FileSystemPath mLaunchPath; +}; \ No newline at end of file diff --git a/src/base/core/Serializeable.h b/src/base/core/Serializeable.h new file mode 100644 index 0000000..5c7c29a --- /dev/null +++ b/src/base/core/Serializeable.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +class Serializeable +{ +public: + virtual std::size_t getSize() const = 0; + + virtual uint8_t getByte(std::size_t index) const = 0; +}; \ No newline at end of file diff --git a/src/base/core/base_types/ByteTypes.h b/src/base/core/base_types/ByteTypes.h new file mode 100644 index 0000000..b739fbd --- /dev/null +++ b/src/base/core/base_types/ByteTypes.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Vector.h" + +#include + +using Byte = uint8_t; +using VecBytes = Vector; + +using Word = uint16_t; +using DWord = uint32_t; +using QWord = uint64_t; \ No newline at end of file diff --git a/src/base/core/base_types/Error.cpp b/src/base/core/base_types/Error.cpp new file mode 100644 index 0000000..919b9d5 --- /dev/null +++ b/src/base/core/base_types/Error.cpp @@ -0,0 +1,11 @@ +#include "Error.h" + +Error::Error(const String& msg) + : m_message(msg) +{ +} + +const String& Error::msg() const +{ + return m_message; +} \ No newline at end of file diff --git a/src/base/core/base_types/Error.h b/src/base/core/base_types/Error.h new file mode 100644 index 0000000..9339664 --- /dev/null +++ b/src/base/core/base_types/Error.h @@ -0,0 +1,15 @@ +#pragma once + +#include "String.h" + +class Error +{ +public: + Error(const String& msg); + + Error() = default; + + const String& msg() const; +private: + String m_message; +}; \ No newline at end of file diff --git a/src/base/core/base_types/Index.cpp b/src/base/core/base_types/Index.cpp new file mode 100644 index 0000000..0a62876 --- /dev/null +++ b/src/base/core/base_types/Index.cpp @@ -0,0 +1,17 @@ +#include "Index.h" + +Index::Index(std::size_t value) + : m_value(value), + m_valid(true) +{ +} + +bool Index::valid() const +{ + return m_valid; +} + +std::size_t Index::value() const +{ + return m_value; +} \ No newline at end of file diff --git a/src/base/core/base_types/Index.h b/src/base/core/base_types/Index.h new file mode 100644 index 0000000..2e46485 --- /dev/null +++ b/src/base/core/base_types/Index.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Index +{ +public: + Index() = default; + + Index(std::size_t value); + + bool valid() const; + + std::size_t value() const; + +private: + std::size_t m_value{0}; + bool m_valid{false}; +}; \ No newline at end of file diff --git a/src/base/core/base_types/Result.h b/src/base/core/base_types/Result.h new file mode 100644 index 0000000..1ae75cc --- /dev/null +++ b/src/base/core/base_types/Result.h @@ -0,0 +1,41 @@ +#pragma once + +#include "Error.h" + +template +class Result +{ +public: + Result(const T& val) + : m_value(val) + { + + } + + Result(const Error& error) + : m_error(error), + m_ok(false) + { + + } + + const Error& error() const + { + return m_error; + } + + bool ok() const + { + return m_ok; + } + + const T& value() const + { + return m_value; + } + +private: + T m_value; + Error m_error; + bool m_ok{true}; +}; \ No newline at end of file diff --git a/src/base/core/build.toml b/src/base/core/build.toml new file mode 100644 index 0000000..e69de29 diff --git a/src/base/core/data_structures/CircleBuffer.h b/src/base/core/data_structures/CircleBuffer.h index 8b83f8b..30612da 100644 --- a/src/base/core/data_structures/CircleBuffer.h +++ b/src/base/core/data_structures/CircleBuffer.h @@ -1,8 +1,6 @@ #pragma once -#include - -#include +#include "Vector.h" template class CircleBuffer @@ -60,5 +58,5 @@ public: private: std::size_t mStartPointer{0}; std::size_t mEndPointer{0}; - std::vector mData; + Vector mData; }; diff --git a/src/base/core/data_structures/List.h b/src/base/core/data_structures/List.h index 86354f5..d75f846 100644 --- a/src/base/core/data_structures/List.h +++ b/src/base/core/data_structures/List.h @@ -1,8 +1,7 @@ #pragma once -#include -#include -#include +#include "Error.h" +#include "Vector.h" class AbstractList { @@ -20,7 +19,7 @@ public: void initializeTo(std::size_t size, T value) { - mData = std::vector(size, value); + mData = Vector(size, value); } const T* getDataPtr() const @@ -28,7 +27,7 @@ public: return mData.data(); } - const std::vector& getData() const + const Vector& getData() const { return mData; } @@ -46,7 +45,7 @@ public: } } - void setData(const std::vector& data) + void setData(const Vector& data) { mData = data; } @@ -65,5 +64,5 @@ public: } private: - std::vector mData; + Vector mData; }; diff --git a/src/base/core/data_structures/Map.h b/src/base/core/data_structures/Map.h new file mode 100644 index 0000000..68e9a86 --- /dev/null +++ b/src/base/core/data_structures/Map.h @@ -0,0 +1,6 @@ +#pragma once + +template +class Map{ + +}; \ No newline at end of file diff --git a/src/base/core/data_structures/Optional.h b/src/base/core/data_structures/Optional.h new file mode 100644 index 0000000..aacbcca --- /dev/null +++ b/src/base/core/data_structures/Optional.h @@ -0,0 +1,29 @@ +#pragma once + +template +class Optional{ + +public: + Optional() = default; + + Optional(const T& value) + : m_is_set(true), + m_value(value) + { + + } + + const T& value() const + { + return m_value; + } + + bool is_set() const + { + return m_is_set; + } + +private: + bool m_is_set{false}; + T m_value; +}; \ No newline at end of file diff --git a/src/base/core/data_structures/Pair.h b/src/base/core/data_structures/Pair.h new file mode 100644 index 0000000..6d8e95a --- /dev/null +++ b/src/base/core/data_structures/Pair.h @@ -0,0 +1,27 @@ +#pragma once + +template +class Pair +{ +public: + Pair(const T& t, const U& u) + : m_first(t), + m_second(u) + { + + } + + const T& first() const + { + return m_first; + } + + const U& second() const + { + return m_second; + } + +private: + T m_first; + U m_second; +}; \ No newline at end of file diff --git a/src/base/core/data_structures/RawTree.h b/src/base/core/data_structures/RawTree.h index 633473e..ef05a20 100644 --- a/src/base/core/data_structures/RawTree.h +++ b/src/base/core/data_structures/RawTree.h @@ -1,7 +1,5 @@ #pragma once -#include - template class RawNode { diff --git a/src/base/core/data_structures/String.cpp b/src/base/core/data_structures/String.cpp new file mode 100644 index 0000000..6d509c5 --- /dev/null +++ b/src/base/core/data_structures/String.cpp @@ -0,0 +1,232 @@ +#include "String.h" + +#include + +String::String() +{ + m_data.push_back('\0'); +} + +String::String(const Vector& data) +{ + append(data); +} + +String::String(const char* data) +{ + append(data); +} + +void String::append(const char* data) +{ + if (data == nullptr) + { + m_data.push_back('\0'); + return; + } + + auto loc = data; + while(*loc != '\0') + { + m_data.push_back(*loc); + loc++; + } + m_data.push_back('\0'); +} + +const Vector& String::data() const +{ + return m_data; +} + +bool String::empty() const +{ + return m_data.empty() || m_data[0] == '\0'; +} + +void String::append(const Vector& data) +{ + if (data.capacity() == 0) + { + m_data.push_back('\0'); + return; + } + + if (m_data.size() == 1 && m_data[0] == '\0') + { + m_data.clear(); + } + + for(const auto c : data) + { + if(c == '\0') + { + break; + } + else + { + m_data.push_back(static_cast(c)); + } + } + m_data.push_back('\0'); +} + +Pair String::rsplit(char c) const +{ + if (const auto index = rindex(c); index.valid()) + { + String left; + slice(0, index.value(), left); + + String right; + slice(index.value(), size(), right); + return {left, right}; + } + return {*this, {}}; +} + +bool String::slice(std::size_t idx, String& out) const +{ + if (idx >= m_data.size() - 1) + { + return false; + } + auto ok = m_data.slice(idx, out.m_data); + if (!ok) + { + return ok; + } + out.m_data.push_back('\0'); + return true; +} + +bool String::slice(std::size_t start, std::size_t end, String& out) const +{ + if (end >= m_data.size() - 1) + { + return false; + } + auto ok = m_data.slice(start, end, out.m_data); + if (!ok) + { + return ok; + } + out.m_data.push_back('\0'); + return true; +} + +Index String::rindex(char c) const +{ + if (m_data.size() <= 2) + { + return {}; + } + for(std::size_t idx=m_data.size()-2; idx >= 0; idx--) + { + if (m_data[idx] == c) + { + return Index(idx); + } + } + return {}; +} + +const char* String::raw() const +{ + return m_data.data(); +} + +std::size_t String::size() const +{ + return m_data.size() - 1; +} + +void String::reverse() +{ + if (m_data.size() == 1) + { + return; + } + for(size_t idx=0; idx<(m_data.size()-1)/2; idx++) + { + const auto ridx = m_data.size() - 2 - idx; + const auto tmp0 = m_data[idx]; + m_data[idx] = m_data[ridx]; + m_data[ridx] = tmp0; + } +} + +String String::to_string(size_t input) +{ + String conv; + auto input_cpy = input; + while(input_cpy > 0) + { + const auto rem = input_cpy % 10; + conv += static_cast(48 + rem); + input_cpy /= 10; + } + conv.reverse(); + return conv; +} + +char String::operator[](std::size_t idx) const +{ + return m_data[idx]; +} + +String& String::operator<<(const char* body) +{ + append(body); + return *this; +} + +bool String::operator==(const String& other) const +{ + return m_data == other.m_data; +} + +bool String::operator!=(const String& other) const +{ + return !(*this == other); +} + +String& String::operator<<(size_t idx) +{ + /* + const auto num_digits = static_cast(log10(double(idx))) + 1; + char body[num_digits+1]; + snprintf(body, num_digits+1, "%d", static_cast(idx)); + append(body); + */ + return *this; +} + +String& String::operator+=(const String& str) +{ + if (m_data.empty()) + { + m_data = str.m_data; + } + else + { + m_data.pop_back(); + m_data.extend(str.m_data); + } + return *this; +} + +String String::operator+(const String& str) const +{ + auto ret = *this; + ret += str; + return ret; +} + +String& String::operator+=(char c) +{ + m_data.push_back('\0'); + m_data[m_data.size()-2] = c; + return *this; +} + diff --git a/src/base/core/data_structures/String.h b/src/base/core/data_structures/String.h new file mode 100644 index 0000000..7b4db08 --- /dev/null +++ b/src/base/core/data_structures/String.h @@ -0,0 +1,59 @@ +#pragma once + +#include "Vector.h" +#include "Pair.h" +#include "Index.h" +#include "ByteTypes.h" + +class String +{ +public: + String(); + + String(const Vector& data); + + String(const char* data); + + const Vector& data() const; + + bool empty() const; + + const char* raw() const; + + Pair rsplit(char c) const; + + Index rindex(char c) const; + + void reverse(); + + std::size_t size() const; + + bool slice(std::size_t idx, String& out) const; + + bool slice(std::size_t start, std::size_t end, String& out) const; + + static String to_string(size_t input); + + char operator[](std::size_t idx) const; + + String& operator<<(const char* body); + + String& operator<<(size_t idx); + + String& operator+=(const String& str); + + String& operator+=(char c); + + String operator+(const String& str) const; + + bool operator==(const String& other) const; + + bool operator!=(const String& other) const; + +private: + void append(const Vector& data); + + void append(const char* data); + + Vector m_data; +}; \ No newline at end of file diff --git a/src/base/core/data_structures/Tree.h b/src/base/core/data_structures/Tree.h index 7b19016..5b85435 100644 --- a/src/base/core/data_structures/Tree.h +++ b/src/base/core/data_structures/Tree.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "Pointer.h" template class Node @@ -10,7 +10,7 @@ public: : mData(data) {} - void addChild(std::unique_ptr child) + void addChild(Ptr child) { if(!mLeftChild) { @@ -45,12 +45,12 @@ public: private: T mData; unsigned char mTag{0}; - std::unique_ptr mLeftChild; - std::unique_ptr mRightChild; + Ptr mLeftChild; + Ptr mRightChild; }; template -using NodePtr = std::unique_ptr >; +using NodePtr = Ptr >; template class Tree diff --git a/src/base/core/data_structures/Vector.cpp b/src/base/core/data_structures/Vector.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/base/core/data_structures/Vector.h b/src/base/core/data_structures/Vector.h new file mode 100644 index 0000000..04fa077 --- /dev/null +++ b/src/base/core/data_structures/Vector.h @@ -0,0 +1,233 @@ +#pragma once + +#include "Allocator.h" +#include + +template +class Vector +{ +public: + Vector() = default; + + Vector(std::size_t size) + { + resize(size); + m_size = size; + } + + Vector(const Vector& v) + { + *this = v; + } + + ~Vector() + { + clear(); + } + + T* begin() const + { + return m_data; + } + + T* end() const + { + return m_data + m_size; + } + + const T* data() const + { + return m_data; + } + + T* data() + { + return m_data; + } + + bool slice(std::size_t slice_idx, Vector& v) const + { + if (slice_idx >= m_size) + { + return false; + } + v.resize(slice_idx); + for(std::size_t idx=0; idx= m_size) + { + return false; + } + v.resize(slice_end - slice_start); + for(std::size_t idx=slice_start; idx= m_capacity) + { + const std::size_t new_size = 1.5*m_size; + resize_capacity(new_size); + } + m_data[m_size] = item; + m_size++; + } + + const T& operator[] (const std::size_t idx) const + { + return m_data[idx]; + } + + T& operator[] (const std::size_t idx) + { + return m_data[idx]; + } + + Vector& operator=(const Vector& v) + { + resize(v.size()); + for(std::size_t idx=0; idx& other) const + { + if (m_size != other.m_size) + { + return false; + } + for(std::size_t idx=0; idx 0; + } + + void resize_capacity(std::size_t new_capacity) + { + if (!has_allocated()) + { + m_data = m_allocator.alloc_array(new_capacity); + m_capacity = new_capacity; + } + else if (new_capacity != m_capacity) + { + auto temp = m_allocator.alloc_array(new_capacity); + for(std::size_t idx=0; idx m_capacity) + { + m_size = m_capacity; + } + } + else if(m_size != m_capacity) + { + m_size = m_capacity; + } + } + + T* m_data{nullptr}; + Allocator m_allocator; + std::size_t m_size{0}; + std::size_t m_capacity{0}; +}; \ No newline at end of file diff --git a/src/base/core/encoding/ByteUtils.h b/src/base/core/encoding/ByteUtils.h index cb15b22..80ae138 100644 --- a/src/base/core/encoding/ByteUtils.h +++ b/src/base/core/encoding/ByteUtils.h @@ -1,44 +1,40 @@ #pragma once +#include "ByteTypes.h" +#include "String.h" #include -#include -#include class ByteUtils { public: - using Word = int16_t; - using DWord = int32_t; - using QWord = int64_t; - - static bool MostSignificantBitIsOne(char c); + static bool MostSignificantBitIsOne(Byte c); static Word GetWordFirstBit(const Word word); static Word GetWordLastByte(const Word word); - static unsigned char getByteN(uint32_t input, unsigned n); + static Byte getByteN(DWord input, std::size_t n); - static unsigned char getHigherNBits(unsigned char input, unsigned num); + static Byte getHigherNBits(Byte input, std::size_t num); - static unsigned char getLowerNBits(uint32_t input, unsigned num); + static Byte getLowerNBits(DWord input, std::size_t num); - static unsigned char getTwoBitsAtN(unsigned char input, unsigned n); + static Byte getTwoBitsAtN(Byte input, std::size_t n); - static unsigned char getMBitsAtN(unsigned char input, unsigned m, unsigned n); + static Byte getMBitsAtN(Byte input, std::size_t m, std::size_t n); - static bool getBitN(uint32_t input, unsigned n); + static bool getBitN(DWord input, std::size_t n); - static unsigned char getFromString(const std::string& string); + static Byte getFromString(const String& string); - static std::string toString(uint32_t input, unsigned length = 8); + static String toString(DWord input, std::size_t length = 8); - static uint32_t mirror(uint32_t input, unsigned length=0); + static DWord mirror(DWord input, std::size_t length=0); - static void ReverseBuffer(char* buffer, char* reverse, unsigned size, unsigned targetSize); + static void ReverseBuffer(Byte* buffer, Byte* reverse, std::size_t size, std::size_t targetSize); template - static T ToType(char* buffer, bool reverse = true) + static T ToType(Byte* buffer, bool reverse = true) { T result {0}; if(reverse) @@ -54,17 +50,17 @@ public: return result; } - static Word ToWord(char* buffer, bool reverse = true); + static Word ToWord(Byte* buffer, bool reverse = true); - static DWord ToDWord(char* buffer, bool reverse = true); + static DWord ToDWord(Byte* buffer, bool reverse = true); - static QWord ToQWord(char* buffer, bool reverse = true); + static QWord ToQWord(Byte* buffer, bool reverse = true); - static bool Compare(char* buffer, const char* tag, unsigned size); + static bool Compare(Byte* buffer, const char* tag, std::size_t size); - static bool CompareDWords(char* buffer, const char* tag); + static bool CompareDWords(Byte* buffer, const char* tag); - static bool CompareWords(char* buffer, const char* tag); + static bool CompareWords(Byte* buffer, const char* tag); static const int BYTE_FIRST_BIT = 0x40; // 1000 0000 static const Word WORD_FIRST_BIT = static_cast(0x8000); // 1000 0000 - 0000 0000 diff --git a/src/base/core/encoding/CharUtils.cpp b/src/base/core/encoding/CharUtils.cpp new file mode 100644 index 0000000..b35ba7a --- /dev/null +++ b/src/base/core/encoding/CharUtils.cpp @@ -0,0 +1,35 @@ +#include "CharUtils.h" + +bool CharUtils::is_alpha_upper(char c) +{ + const auto unsigned_c = static_cast(c); + return unsigned_c >= 65 && unsigned_c <= 90; +} + +bool CharUtils::is_alpha_lower(char c) +{ + const auto unsigned_c = static_cast(c); + return unsigned_c >= 97 && unsigned_c <= 122; +} + +bool CharUtils::is_alpha(char c) +{ + return is_alpha_upper(c) || is_alpha_lower(c); +} + +bool CharUtils::is_alnum(char c) +{ + return is_alpha(c) || is_digit(c); +} + +bool CharUtils::is_digit(char c) +{ + const auto unsigned_c = static_cast(c); + return unsigned_c >= 48 && unsigned_c <= 57; +} + +bool CharUtils::is_space(char c) +{ + return c == ' ' || c == '\f' || c == '\n' + || c == '\r' || c == '\t' || c == '\v'; +} \ No newline at end of file diff --git a/src/base/core/encoding/CharUtils.h b/src/base/core/encoding/CharUtils.h new file mode 100644 index 0000000..6e76866 --- /dev/null +++ b/src/base/core/encoding/CharUtils.h @@ -0,0 +1,17 @@ +#pragma once + +class CharUtils +{ +public: + static bool is_alpha_upper(char c); + + static bool is_alpha_lower(char c); + + static bool is_alpha(char c); + + static bool is_alnum(char c); + + static bool is_digit(char c); + + static bool is_space(char c); +}; \ No newline at end of file diff --git a/src/base/core/encoding/StringUtils.h b/src/base/core/encoding/StringUtils.h index e91010b..b46aab0 100644 --- a/src/base/core/encoding/StringUtils.h +++ b/src/base/core/encoding/StringUtils.h @@ -1,5 +1,7 @@ #pragma once +#include "ByteTypes.h" + #include #include diff --git a/src/base/core/file_utilities/Directory.cpp b/src/base/core/file_utilities/Directory.cpp index 49aac5a..5b1f21e 100644 --- a/src/base/core/file_utilities/Directory.cpp +++ b/src/base/core/file_utilities/Directory.cpp @@ -1,30 +1,84 @@ #include "Directory.h" +#include +#include +#include -std::vector Directory::getFilesWithExtension(const Path& path, const std::string& extension, bool recursive) +Vector Directory::getSubdirectories(const FileSystemPath& path) { - std::vector paths; - if (std::filesystem::is_directory(path)) + Vector ret; + auto dirp = ::opendir(path.as_string().raw()); + while(auto ep = ::readdir(dirp)) { - for (const auto& entry : std::filesystem::directory_iterator(path)) + auto rel_path = String(ep->d_name); + if (rel_path == "." || rel_path == "..") { - if (std::filesystem::is_regular_file(entry) && entry.path().extension() == extension) + continue; + } + + auto full_path = path.join(rel_path); + struct stat sb; + auto rc = lstat(full_path.as_string().raw(), &sb); + if (rc == -1) + { + printf("Got error"); + } + if (S_ISDIR(sb.st_mode)) + { + printf("Adding full path: %s\n", full_path.as_string().raw()); + ret.push_back(full_path); + } + } + ::closedir(dirp); + return ret; +} + +Vector Directory::getFiles(const FileSystemPath& path, bool recursive) +{ + Vector paths; + if (path.is_directory()) + { + for (const auto& entry : getSubdirectories(path)) + { + if (entry.is_regular_file()) { - paths.push_back(entry.path()); + paths.push_back(entry); } - else if(recursive && std::filesystem::is_directory(entry)) + else if(recursive && entry.is_directory()) { - const auto child_paths = getFilesWithExtension(entry, extension, recursive); - paths.insert(paths.end(), child_paths.begin(), child_paths.end()); + const auto child_paths = getFiles(entry, recursive); + paths.extend(child_paths); } } } return paths; } -void Directory::createIfNotExisting(const Path& path) +Vector Directory::getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive) { - Path working_path; - if (std::filesystem::is_directory(path)) + Vector paths; + if (path.is_directory()) + { + for (const auto& entry : getSubdirectories(path)) + { + if (entry.is_regular_file() && entry.extension() == extension) + { + paths.push_back(entry); + } + else if(recursive && entry.is_directory()) + { + const auto child_paths = getFilesWithExtension(entry, extension, recursive); + paths.extend(child_paths); + } + } + } + return paths; +} + +void Directory::create(const FileSystemPath& path, bool existsOk) +{ + (void)existsOk; + FileSystemPath working_path; + if (path.is_directory()) { working_path = path; } @@ -33,8 +87,8 @@ void Directory::createIfNotExisting(const Path& path) working_path = path.parent_path(); } - if (!std::filesystem::exists(working_path)) + if (!working_path.exists()) { - std::filesystem::create_directories(working_path); + //std::filesystem::create_directories(working_path); } } diff --git a/src/base/core/file_utilities/Directory.h b/src/base/core/file_utilities/Directory.h index a225f32..7c27b66 100644 --- a/src/base/core/file_utilities/Directory.h +++ b/src/base/core/file_utilities/Directory.h @@ -1,14 +1,16 @@ #pragma once -#include -#include - -using Path = std::filesystem::path; +#include "Vector.h" +#include "FileSystemPath.h" class Directory { public: - static void createIfNotExisting(const Path& path); + static Vector getSubdirectories(const FileSystemPath& path); - static std::vector getFilesWithExtension(const Path& path, const std::string& extension, bool recursive=false); + static void create(const FileSystemPath& path, bool existsOK = false); + + static Vector getFiles(const FileSystemPath& path, bool recursive=false); + + static Vector getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive=false); }; diff --git a/src/base/core/file_utilities/File.cpp b/src/base/core/file_utilities/File.cpp index e09fc47..c23e8be 100644 --- a/src/base/core/file_utilities/File.cpp +++ b/src/base/core/file_utilities/File.cpp @@ -1,17 +1,116 @@ #include "File.h" -#include "FileLogger.h" +//#include "FileLogger.h" #include "ByteUtils.h" +#include "Directory.h" +#include "Result.h" -#include -#include +#include +#include +#include +#include +#include +#include +#include -File::File(std::filesystem::path path) - : mFullPath(path), - mInHandle(), - mOutHandle() +class FileImpl { +public: + void do_open(const FileSystemPath& path, File::AccessMode accessMode) + { + int flags{0}; + if (accessMode == File::AccessMode::Read) + { + flags |= O_RDONLY; + } + else + { + flags |= O_WRONLY; + flags |= O_CREAT; + } + m_fd = ::open(path.as_string().raw(), flags); + if (accessMode == File::AccessMode::Read) + { + m_open_for_read = true; + } + else + { + m_open_for_write = true; + } + } + + void do_close() + { + ::close(m_fd); + m_open_for_read = false; + m_open_for_write = false; + } + + bool is_ok() const + { + return m_valid; + } + + bool is_open_for_read() const + { + return m_open_for_read; + } + + bool is_open_for_write() const + { + return m_open_for_write; + } + + Result do_read(VecBytes& bytes) + { + errno = 0; + const auto rc = ::read(m_fd, bytes.data(), bytes.capacity()); + if (rc < 0) + { + const auto last_err = errno; + String msg(::strerror(last_err)); + return Result(Error(msg)); + } + return Result(rc); + } + + std::size_t do_write(const VecBytes& bytes) + { + return ::write(m_fd, bytes.data(), bytes.size()); + } + + std::size_t do_write(const Vector& bytes, int size = -1) + { + if (size > -1) + { + return ::write(m_fd, bytes.data(), size); + } + else + { + return ::write(m_fd, bytes.data(), bytes.size()); + } + } + + void update_size() + { + struct stat buf; + ::fstat(m_fd, &buf); + m_size = buf.st_size; + } + + bool m_open_for_write{false}; + bool m_open_for_read{false}; + bool m_valid{false}; + std::size_t m_size{0}; + bool m_is_open{false}; + int m_fd{-1}; +}; + +File::File(const FileSystemPath& path) + : m_impl(Ptr::create()), + m_path(path) +{ } File::~File() @@ -19,145 +118,149 @@ File::~File() close(); } -std::string File::getExtension() const +String File::getExtension() const { - return mFullPath.extension().string(); + return m_path.extension(); } -std::string File::dumpBinary() +bool File::readBinary(VecBytes& buffer) +{ + auto ok = open(AccessMode::Read, true); + if (!ok) + { + return false; + } + + m_impl->update_size(); + buffer.resize(m_impl->m_size); + const auto result = m_impl->do_read(buffer); + buffer.resize(result.value()); + return true; +} + +String File::readText() +{ + VecBytes buffer; + auto ok = open(AccessMode::Read, true); + if (!ok) + { + return {}; + } + + m_impl->update_size(); + buffer.resize(m_impl->m_size); + const auto result = m_impl->do_read(buffer); + if (!result.ok()) + { + printf("Got error: %s\n", result.error().msg()); + return {}; + } + + buffer.resize(result.value()); + return String(buffer); +} + +String File::dumpBinary() { open(AccessMode::Read); - std::stringstream sstr; - sstr << "Count | Binary | Decimal | ASCII \n"; + String sstr; + sstr << "Count | Binary | Decimal | Hex | ASCII \n"; + + VecBytes buffer; + readBinary(buffer); + unsigned count = 0; - while(mInHandle->peek() != EOF) + /* + for(const auto byte : buffer) { - const unsigned char val = static_cast(mInHandle->get()); - const unsigned char ascii_val = std::isalpha(val) ? val : '.'; - sstr << count << " | " << ByteUtils::toString(val) << " | " << static_cast(val) << " | " << ascii_val << '\n'; + const auto ascii_val = std::isalpha(byte) ? byte : '.'; + String hex_sstr; + hex_sstr << std::setfill('0') << std::setw(2) << std::hex << static_cast(byte); + + sstr << count << " | " << ByteUtils::toString(byte) << " | " << static_cast(byte) << " | " << hex_sstr.str() << " | " << ascii_val << '\n'; if (count % 10 == 0) { sstr << "\n"; } count++; } - const auto out = sstr.str(); + */ close(); - return out; + return sstr; } -std::ifstream* File::getInHandle() const +Optional File::readNextByte() { - return mInHandle.get(); -} - -std::ofstream* File::getOutHandle() const -{ - return mOutHandle.get(); -} - -std::optional File::readNextByte() -{ - if (!mInHandle) + if (!open(AccessMode::Read)) { - if (!open(AccessMode::Read)) - { - return std::nullopt; - } + return {}; } - if (mInHandle->good()) + if (m_impl->is_ok()) { - if (auto val = mInHandle->get(); val == EOF) + VecBytes buffer(1); + m_impl->do_read(buffer); + if (buffer[0] == EOF) { - return std::nullopt; + return {}; } else { - return val; + return buffer[0]; } } else { - return std::nullopt; + return {}; } } -bool File::open(AccessMode accessMode) +bool File::open(AccessMode accessMode, bool binary) { - if (mFullPath.is_absolute() && !std::filesystem::exists(mFullPath.parent_path())) + if (m_path.is_absolute() && !m_path.parent_path().exists()) { - std::filesystem::create_directories(mFullPath.parent_path()); + Directory::create(m_path.parent_path(), true); } - if(accessMode == AccessMode::Read) - { - auto flags = std::ifstream::in; - mInHandle = std::make_unique(); - mInHandle->open(mFullPath, flags); - if (!mInHandle->is_open()) - { - MLOG_ERROR("Failed to open file at :" << mFullPath); - return false; - } - } - else - { - auto flags = std::ofstream::out; - mOutHandle = std::make_unique(); - mOutHandle->open(mFullPath, flags); - if (!mOutHandle->is_open()) - { - MLOG_ERROR("Failed to open file at :" << mFullPath); - return false; - } - } + m_impl->do_open(m_path, accessMode); return true; } void File::close() { - if(mOutHandle) - { - mOutHandle->close(); - } - if(mInHandle) - { - mInHandle->close(); - } + m_impl->do_close(); } FileFormat::Format File::inferFormat() const { - const auto extension = getExtension(); - return FileFormat::inferFormat(extension); + //const auto extension = getExtension(); + //return FileFormat::inferFormat(extension); + return {}; } -void File::writeText(const std::string& text) +void File::writeText(const String& text) { bool had_to_open{false}; - if (!mOutHandle) + if (!m_impl->is_open_for_write()) { had_to_open = true; - if (!open(File::AccessMode::Write)) - { - return; - } + m_impl->do_open(m_path, File::AccessMode::Write); } - (*mOutHandle) << text; + m_impl->do_write(text.data(), text.data().size() - 1); if (had_to_open) { - close(); + m_impl->do_close(); } } -std::vector File::readLines() +Vector File::readLines() { - std::vector content; + Vector content; + /* if (!pathExists()) { return {}; @@ -168,18 +271,20 @@ std::vector File::readLines() return {}; } - std::string str; + String str; while(std::getline(*mInHandle, str)) { content.push_back(str); } close(); + */ return content; } -std::string File::read() +String File::read() { + /* if (!pathExists()) { return {}; @@ -190,31 +295,16 @@ std::string File::read() return {}; } - std::stringstream buffer; + String buffer; buffer << mInHandle->rdbuf(); close(); - return buffer.str(); -} - -std::string File::readText() -{ - if (!pathExists()) - { - return {}; - } - - if(!open(AccessMode::Read)) - { - return {}; - } - - std::string str((std::istreambuf_iterator(*mInHandle)), - std::istreambuf_iterator()); - return str; + */ + String buffer; + return buffer; } bool File::pathExists() const { - return std::filesystem::exists(mFullPath); + return m_path.exists(); } diff --git a/src/base/core/file_utilities/File.h b/src/base/core/file_utilities/File.h index b2cb3f0..09dbcfc 100644 --- a/src/base/core/file_utilities/File.h +++ b/src/base/core/file_utilities/File.h @@ -1,57 +1,53 @@ #pragma once #include "FileFormats.h" +#include "FileSystemPath.h" +#include "Optional.h" +#include "String.h" +#include "ByteTypes.h" +#include "Pointer.h" -#include -#include -#include -#include -#include -#include - -using Path = std::filesystem::path; +class FileImpl; class File { public: enum class AccessMode{ Read, - Write + Write, + ReadWrite }; public: - File(std::filesystem::path fullPath); + File(const FileSystemPath& path); ~File(); void close(); - std::string dumpBinary(); + String dumpBinary(); - std::string getExtension() const; - - std::ifstream* getInHandle() const; - - std::ofstream* getOutHandle() const; + String getExtension() const; FileFormat::Format inferFormat() const; - std::string readText(); + String readText(); - std::vector readLines(); + Vector readLines(); - std::string read(); + String read(); bool pathExists() const; - bool open(AccessMode mode); + bool open(AccessMode mode, bool binary = false); - std::optional readNextByte(); + bool readBinary(VecBytes& bytes); - void writeText(const std::string& text); + Optional readNextByte(); + + void writeText(const String& text); private: - std::filesystem::path mFullPath; - std::unique_ptr mInHandle; - std::unique_ptr mOutHandle; + Ptr m_impl; + FileSystemPath m_path; }; diff --git a/src/base/core/file_utilities/FileFormats.h b/src/base/core/file_utilities/FileFormats.h index 0dccf8f..1aeb124 100644 --- a/src/base/core/file_utilities/FileFormats.h +++ b/src/base/core/file_utilities/FileFormats.h @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include "Map.h" +#include "String.h" class FileFormat{ @@ -24,13 +24,13 @@ public: Unknown }; - using ExtensionMap = std::map; + using ExtensionMap = Map; public: - static bool isFormat(const std::string& extension, Format format); + static bool isFormat(const String& extension, Format format); - static Format inferFormat(const std::string& query); + static Format inferFormat(const String& query); - static std::string getExtension(Format format); + static String getExtension(Format format); private: static ExtensionMap mExtensions; diff --git a/src/base/core/file_utilities/FileSystemPath.cpp b/src/base/core/file_utilities/FileSystemPath.cpp new file mode 100644 index 0000000..7290531 --- /dev/null +++ b/src/base/core/file_utilities/FileSystemPath.cpp @@ -0,0 +1,114 @@ +#include "FileSystemPath.h" + +#include +#include +#include +#include +#include + +FileSystemPath::FileSystemPath(const String& path) + : m_path(path) +{ + +} + +const String& FileSystemPath::as_string() const +{ + return m_path; +} + +Result FileSystemPath::is_empty() const +{ + if (!is_regular_file()) + { + return {Error("Requested empty check but target is not regular file.")}; + } + + const auto size_result = get_size(); + if (!size_result.ok()) + { + return {size_result.error().msg()}; + } + return {size_result.value() == 0}; +} + +Result FileSystemPath::get_size() const +{ + if (!is_regular_file()) + { + return {Error("Requested size but target is not regular file.")}; + } + + struct stat buf; + ::stat(m_path.raw(), &buf); + return buf.st_size; +} + +FileSystemPath FileSystemPath::current_dir() +{ + errno = 0; + const auto path_max = ::pathconf(".", _PC_PATH_MAX); + std::size_t size{0}; + if (path_max == -1) + { + size = 1024; + } + else if(path_max > 10240) + { + size = 10240; + } + else + { + size = path_max; + } + + Vector buffer(path_max); + const auto ret = ::getcwd(buffer.data(), path_max); + return FileSystemPath(String(buffer.data())); +} + +bool FileSystemPath::is_regular_file() const +{ + struct stat path_stat; + ::stat(m_path.raw(), &path_stat); + return S_ISREG(path_stat.st_mode); +} + +bool FileSystemPath::is_directory() const +{ + struct stat path_stat; + ::stat(m_path.raw(), &path_stat); + return S_ISDIR(path_stat.st_mode); +} + +bool FileSystemPath::is_absolute() const +{ + return false; +} + +FileSystemPath FileSystemPath::parent_path() const +{ + const auto split = m_path.rsplit('/'); + return FileSystemPath(split.first()); +} + +String FileSystemPath::extension() const +{ + const auto split = m_path.rsplit('.'); + String result("."); + result += split.second(); + return result; +} + +bool FileSystemPath::exists() const +{ + return ::access(m_path.raw(), F_OK) == 0; +} + +FileSystemPath FileSystemPath::join(const String& entry) const +{ + auto new_path = *this; + new_path.m_path+=m_delimiter; + new_path.m_path+=entry; + return new_path; +} \ No newline at end of file diff --git a/src/base/core/file_utilities/FileSystemPath.h b/src/base/core/file_utilities/FileSystemPath.h new file mode 100644 index 0000000..1aca9cb --- /dev/null +++ b/src/base/core/file_utilities/FileSystemPath.h @@ -0,0 +1,38 @@ +#pragma once + +#include "String.h" +#include "Result.h" + +class FileSystemPath +{ +public: + FileSystemPath() = default; + + FileSystemPath(const String& path); + + const String& as_string() const; + + static FileSystemPath current_dir(); + + String extension() const; + + bool exists() const; + + Result is_empty() const; + + Result get_size() const; + + FileSystemPath join(const String& entry) const; + + bool is_regular_file() const; + + bool is_directory() const; + + bool is_absolute() const; + + FileSystemPath parent_path() const; + +private: + String m_delimiter{"/"}; + String m_path; +}; \ No newline at end of file diff --git a/src/base/core/loggers/ConsoleLogger.cpp b/src/base/core/loggers/ConsoleLogger.cpp new file mode 100644 index 0000000..234027d --- /dev/null +++ b/src/base/core/loggers/ConsoleLogger.cpp @@ -0,0 +1,17 @@ +#include "ConsoleLogger.h" + +#include +#include + +void ConsoleLogger::logLine(const String& msg) +{ + printf("%s\n", msg.raw()); +} + +void ConsoleLogger::logLine(const char* fmt, ...) +{ + va_list(args); + va_start(args, fmt); + vprintf((String(fmt) + "\n").raw(), args); + va_end(args); +} \ No newline at end of file diff --git a/src/base/core/loggers/ConsoleLogger.h b/src/base/core/loggers/ConsoleLogger.h new file mode 100644 index 0000000..fc7e3c4 --- /dev/null +++ b/src/base/core/loggers/ConsoleLogger.h @@ -0,0 +1,11 @@ +#pragma once + +#include "String.h" + +class ConsoleLogger +{ +public: + static void logLine(const String& msg); + + static void logLine(const char* fmt, ...); +}; \ No newline at end of file diff --git a/src/base/core/loggers/FileLogger.cpp b/src/base/core/loggers/FileLogger.cpp index d9330b9..e6aa155 100644 --- a/src/base/core/loggers/FileLogger.cpp +++ b/src/base/core/loggers/FileLogger.cpp @@ -1,9 +1,20 @@ #include "FileLogger.h" #include -#include -#include -#include + +FileLogger::FileLogger() + :mWorkDirectory(), + mFileName("MT_Log.txt") +{ + +} + + +FileLogger& FileLogger::GetInstance() +{ + static FileLogger instance; + return instance; +} FileLogger::~FileLogger() { diff --git a/src/base/core/loggers/FileLogger.h b/src/base/core/loggers/FileLogger.h index 1d73311..59831ec 100644 --- a/src/base/core/loggers/FileLogger.h +++ b/src/base/core/loggers/FileLogger.h @@ -1,33 +1,21 @@ #pragma once -#define MLOG_ALL(msg, level) {std::ostringstream mt_logstream;\ +#define MLOG_ALL(msg, level) {String mt_logstream;\ mt_logstream << msg; \ FileLogger::GetInstance().LogLine(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);}; #define MLOG_INFO(msg) MLOG_ALL(msg, "Info"); #define MLOG_ERROR(msg) MLOG_ALL(msg, "Error"); -#include -#include -#include -#include +#include "Pointer.h" +#include "String.h" class FileLogger { - FileLogger() - :mWorkDirectory(), - mFileName("MT_Log.txt"), - mFileStream() - { - - } + FileLogger(); public: - static FileLogger& GetInstance() - { - static FileLogger instance; - return instance; - } + static FileLogger& GetInstance(); FileLogger(FileLogger const&) = delete; void operator=(FileLogger const&) = delete; @@ -36,22 +24,19 @@ public: void disable(); - void SetWorkDirectory(const std::string& workDir); + void SetWorkDirectory(const String& workDir); - void SetFileName(const std::string& fileName); + void SetFileName(const String& fileName); void Open(); void Close(); - void LogLine(const std::ostringstream& line); + void LogLine(const String& line); - void LogLine(const std::string& logType, const std::ostringstream& line, const std::string& fileName = "", const std::string& functionName = "", int lineNumber=-1); + void LogLine(const String& logType, const String& line, const String& fileName = "", const String& functionName = "", int lineNumber=-1); private: bool mDisabled{false}; - std::string mWorkDirectory; - std::string mFileName; - std::ofstream mFileStream; -}; - -using FileLoggerPtr = std::shared_ptr; + String mWorkDirectory; + String mFileName; +}; \ No newline at end of file diff --git a/src/base/core/memory/Allocator.cpp b/src/base/core/memory/Allocator.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/base/core/memory/Allocator.h b/src/base/core/memory/Allocator.h new file mode 100644 index 0000000..110ee8a --- /dev/null +++ b/src/base/core/memory/Allocator.h @@ -0,0 +1,29 @@ +#pragma once + +//#include +#include + +template +class Allocator +{ +public: + T* allocate() + { + return new T; + } + + void do_delete(T** p) + { + delete p; + } + + T* alloc_array(std::size_t size) + { + return new T[size]; + } + + void delete_array(T*& arr) + { + delete[] arr; + } +}; \ No newline at end of file diff --git a/src/base/core/memory/Pointer.h b/src/base/core/memory/Pointer.h new file mode 100644 index 0000000..ad3aa85 --- /dev/null +++ b/src/base/core/memory/Pointer.h @@ -0,0 +1,61 @@ +#pragma once + +#include "Allocator.h" +#include + +template +class Ptr +{ +public: + Ptr() + { + } + + static Ptr create() + { + Ptr p; + p.allocate(); + return std::move(p); + } + + void allocate() + { + m_raw = m_allocator.allocate(); + } + + ~Ptr() + { + if (m_raw != nullptr) + { + m_allocator.do_delete(&m_raw); + } + } + + Ptr(const Ptr& other) = delete; + + Ptr(Ptr&& other) + : m_allocator(std::move(other.m_allocator)), + m_raw(other.m_raw) + { + other.m_raw = nullptr; + } + + T* get() + { + return m_raw; + } + + const T* get() const + { + return m_raw; + } + + T* operator->() + { + return m_raw; + } + +private: + Allocator m_allocator; + T* m_raw{nullptr}; +}; \ No newline at end of file diff --git a/src/base/core/streams/BitStream.cpp b/src/base/core/streams/BitStream.cpp index 28afdb6..2d43c1d 100644 --- a/src/base/core/streams/BitStream.cpp +++ b/src/base/core/streams/BitStream.cpp @@ -2,15 +2,12 @@ #include "ByteUtils.h" -#include -#include - BitStream::~BitStream() { } -unsigned char BitStream::getCurrentByte() +Byte BitStream::getCurrentByte() { if (mByteOffset < 0) { @@ -19,19 +16,18 @@ unsigned char BitStream::getCurrentByte() return mCurrentByte; } -void BitStream::write(uint32_t data) +void BitStream::write(DWord data) { - unsigned num_bytes = sizeof(uint32_t); - for(unsigned idx=0; idx(data >> 8); - const auto byte1 = static_cast((data << 8) >> 8); + const auto byte0 = static_cast(data >> 8); + const auto byte1 = static_cast((data << 8) >> 8); writeByte(byte0); writeByte(byte1); } @@ -41,24 +37,26 @@ int BitStream::getCurrentByteOffset() const return mByteOffset; } -unsigned BitStream::getCurrentBitOffset() const +std::size_t BitStream::getCurrentBitOffset() const { return mBitOffset; } -std::string BitStream::logLocation() +String BitStream::logLocation() { - std::stringstream sstr; - sstr << "Byte offset " << mByteOffset<< " | Bit offset " << mBitOffset; - sstr << " | Working byte " << ByteUtils::toString(getCurrentByte()) << '\n'; - return sstr.str(); + String ret; + ret << "Byte offset " << mByteOffset<< " | Bit offset " << mBitOffset; + ret << " | Working byte " << ByteUtils::toString(getCurrentByte()) << '\n'; + return ret; } -std::string BitStream::logNextNBytes(unsigned n) const +String BitStream::logNextNBytes(std::size_t n) const { std::stringstream sstr; - unsigned count{0}; - for(auto byte : peekNextNBytes(n)) + std::size_t count{0}; + VecBytes bytes; + peekNextNBytes(n, bytes); + for(auto byte : bytes) { sstr << mByteOffset + count << " | " << ByteUtils::toString(byte) + '\n'; count++; @@ -66,28 +64,28 @@ std::string BitStream::logNextNBytes(unsigned n) const return sstr.str(); } -void BitStream::writeNBits(uint32_t data, unsigned length) +void BitStream::writeNBits(DWord data, std::size_t length) { const auto num_left = 8 - mBitOffset; const int overshoot = length - num_left; if (overshoot > 0) { - unsigned char lower_bits = ByteUtils::getLowerNBits(data, num_left); + Byte lower_bits = ByteUtils::getLowerNBits(data, num_left); mCurrentByte |= lower_bits << mBitOffset; writeByte(mCurrentByte, false); - unsigned num_bytes = overshoot / 8; - for (unsigned idx=0; idx< num_bytes; idx++) + std::size_t num_bytes = overshoot / 8; + for (std::size_t idx=0; idx< num_bytes; idx++) { - mCurrentByte = ByteUtils::getMBitsAtN(static_cast(data), overshoot, idx*8 + num_left); + mCurrentByte = ByteUtils::getMBitsAtN(static_cast(data), overshoot, idx*8 + num_left); writeByte(mCurrentByte, false); } if (const auto remainder = overshoot % 8; remainder > 0) { - mCurrentByte = ByteUtils::getMBitsAtN(static_cast(data), remainder, num_bytes*8 + num_left); + mCurrentByte = ByteUtils::getMBitsAtN(static_cast(data), remainder, num_bytes*8 + num_left); mBitOffset = remainder; } else @@ -98,7 +96,7 @@ void BitStream::writeNBits(uint32_t data, unsigned length) } else { - mCurrentByte |= (static_cast(data) << mBitOffset); + mCurrentByte |= (static_cast(data) << mBitOffset); mBitOffset += length; if (mBitOffset == 8) { @@ -107,10 +105,9 @@ void BitStream::writeNBits(uint32_t data, unsigned length) mBitOffset = 0; } } - } -bool BitStream::readNextNBits(unsigned n, unsigned char& buffer) +bool BitStream::readNextNBits(std::size_t n, Byte& buffer) { if (mByteOffset < 0) { @@ -123,15 +120,15 @@ bool BitStream::readNextNBits(unsigned n, unsigned char& buffer) int overshoot = n + mBitOffset - 8; if (overshoot > 0) { - unsigned char last_byte = mCurrentByte; + const auto last_byte = mCurrentByte; if (!readNextByte()) { return false; } auto num_lower = 8 - mBitOffset; - char lower_bits = ByteUtils::getHigherNBits(last_byte, num_lower); - char higher_bits = ByteUtils::getLowerNBits(mCurrentByte, overshoot); + const auto lower_bits = ByteUtils::getHigherNBits(last_byte, num_lower); + const auto higher_bits = ByteUtils::getLowerNBits(mCurrentByte, overshoot); buffer = (higher_bits << num_lower) | lower_bits; @@ -145,3 +142,44 @@ bool BitStream::readNextNBits(unsigned n, unsigned char& buffer) return true; } } + +void BitStream::resetOffsets() +{ + mEndByteOffset = mByteOffset; + mEndBitOffset = mBitOffset; + mEndByte = mCurrentByte; + + mCurrentByte = 0; + mByteOffset = -1; + mBitOffset = 0; +} + +void BitStream::reset() +{ + resetOffsets(); + mCurrentByte = 0; +} + +void BitStream::flushRemainingBits() +{ + if (mBitOffset > 0) + { + writeByte(mCurrentByte, false); + mBitOffset = 0; + } +} + +std::pair BitStream::getRemainingBits() const +{ + return {mEndByte, mEndBitOffset}; +} + +void BitStream::setChecksumCalculator(AbstractChecksumCalculator* calc) +{ + mChecksumCalculator = calc; +} + +void BitStream::clearChecksumCalculator() +{ + mChecksumCalculator = nullptr; +} diff --git a/src/base/core/streams/BitStream.h b/src/base/core/streams/BitStream.h index 9cef91a..e316a7d 100644 --- a/src/base/core/streams/BitStream.h +++ b/src/base/core/streams/BitStream.h @@ -1,92 +1,63 @@ #pragma once #include "AbstractChecksumCalculator.h" - -#include -#include -#include +#include "ByteTypes.h" +#include "String.h" +#include "Optional.h" +#include "Pair.h" class BitStream { public: virtual ~BitStream(); - unsigned char getCurrentByte(); + Byte getCurrentByte(); int getCurrentByteOffset() const; - unsigned getCurrentBitOffset() const; + std::size_t getCurrentBitOffset() const; virtual bool isFinished() const = 0; - std::string logNextNBytes(unsigned n) const; + String logNextNBytes(std::size_t n) const; - std::string logLocation(); + String logLocation(); - virtual std::vector peekNextNBytes(unsigned n) const = 0; + virtual void peekNextNBytes(std::size_t n, VecBytes& bytes) const = 0; - virtual bool readNextNBits(unsigned n, unsigned char& buffer); + virtual bool readNextNBits(std::size_t n, Byte& buffer); - virtual std::optional readNextByte() = 0; + virtual Optional readNextByte() = 0; - virtual void writeNBits(uint32_t data, unsigned length); + virtual void writeNBits(DWord data, std::size_t length); - virtual void writeByte(unsigned char data, bool checkOverflow = true) = 0; + virtual void writeByte(Byte data, bool checkOverflow = true) = 0; - void write(uint32_t data); + void write(DWord data); - void writeWord(uint16_t data); + void writeWord(Word data); - virtual void writeBytes(const std::vector data) = 0; + virtual void writeBytes(const VecBytes& data) = 0; - void resetOffsets() - { - mEndByteOffset = mByteOffset; - mEndBitOffset = mBitOffset; - mEndByte = mCurrentByte; + void resetOffsets(); - mCurrentByte = 0; - mByteOffset = -1; - mBitOffset = 0; - } + virtual void reset(); - virtual void reset() - { - resetOffsets(); - mCurrentByte = 0; - } + void flushRemainingBits(); - void flushRemainingBits() - { - if (mBitOffset > 0) - { - writeByte(mCurrentByte, false); - mBitOffset = 0; - } - } + Pair getRemainingBits() const; - std::pair getRemainingBits() const - { - return {mEndByte, mEndBitOffset}; - } + void setChecksumCalculator(AbstractChecksumCalculator* calc); - void setChecksumCalculator(AbstractChecksumCalculator* calc) - { - mChecksumCalculator = calc; - } - - void clearChecksumCalculator() - { - mChecksumCalculator = nullptr; - } + void clearChecksumCalculator(); protected: int mByteOffset{-1}; - unsigned mBitOffset{0}; - unsigned char mCurrentByte{0}; + std::size_t mBitOffset{0}; + Byte mCurrentByte{0}; int mEndByteOffset{-1}; - unsigned mEndBitOffset{0}; - unsigned char mEndByte{0}; + std::size_t mEndBitOffset{0}; + Byte mEndByte{0}; AbstractChecksumCalculator* mChecksumCalculator{nullptr}; }; diff --git a/src/base/core/streams/BufferBitStream.cpp b/src/base/core/streams/BufferBitStream.cpp index 5f9d3f2..12381ae 100644 --- a/src/base/core/streams/BufferBitStream.cpp +++ b/src/base/core/streams/BufferBitStream.cpp @@ -9,10 +9,10 @@ bool BufferBitStream::isFinished() const return mByteOffset == static_cast(mBuffer.size()) - 1; } -std::vector BufferBitStream::peekNextNBytes(unsigned n) const +void BufferBitStream::peekNextNBytes(std::size_t n, VecBytes& ret) const { - std::vector ret (n, 0); - unsigned count = 0; + ret.resize(n, 0); + std::size_t count = 0; int start = mByteOffset; if (start<0) @@ -28,12 +28,11 @@ std::vector BufferBitStream::peekNextNBytes(unsigned n) const } ret[count] = mBuffer[idx]; - count ++; + count++; } - return ret; } -std::optional BufferBitStream::readNextByte() +std::optional BufferBitStream::readNextByte() { if (mByteOffset + 1 == static_cast(mBuffer.size())) { @@ -47,14 +46,14 @@ std::optional BufferBitStream::readNextByte() } } -void BufferBitStream::setBuffer(const std::vector& data) +void BufferBitStream::setBuffer(const VecBytes& data) { mBuffer = data; } -void BufferBitStream::writeByte(unsigned char data, bool checkOverflow) +void BufferBitStream::writeByte(uint8_t data, bool checkOverflow) { - unsigned char out_byte{0}; + uint8_t out_byte{0}; if (checkOverflow && mBitOffset > 0) { out_byte = ByteUtils::getLowerNBits(mCurrentByte, mBitOffset); @@ -76,12 +75,12 @@ void BufferBitStream::writeByte(unsigned char data, bool checkOverflow) } -void BufferBitStream::writeBytes(const std::vector data) +void BufferBitStream::writeBytes(const VecBytes& data) { std::copy(data.begin(), data.end(), std::back_inserter(mBuffer)); } -const std::vector& BufferBitStream::getBuffer() const +const VecBytes& BufferBitStream::getBuffer() const { return mBuffer; } diff --git a/src/base/core/streams/BufferBitStream.h b/src/base/core/streams/BufferBitStream.h index 6acde9a..04794fb 100644 --- a/src/base/core/streams/BufferBitStream.h +++ b/src/base/core/streams/BufferBitStream.h @@ -2,28 +2,25 @@ #include "BitStream.h" -#include -#include - class BufferBitStream : public BitStream { public: - const std::vector& getBuffer() const; + const VecBytes& getBuffer() const; bool isFinished() const override; - std::vector peekNextNBytes(unsigned n) const override; + void peekNextNBytes(std::size_t n, VecBytes& bytes) const override; - std::optional readNextByte() override; + std::optional readNextByte() override; void reset() override; - void setBuffer(const std::vector& data); + void setBuffer(const VecBytes& data); - void writeByte(unsigned char data, bool checkOverflow = true) override; + void writeByte(uint8_t data, bool checkOverflow = true) override; - void writeBytes(const std::vector data) override; + void writeBytes(const VecBytes& data) override; private: - std::vector mBuffer; + VecBytes mBuffer; }; diff --git a/src/base/core/streams/InputBitStream.cpp b/src/base/core/streams/InputBitStream.cpp index 8568853..c6b19b5 100644 --- a/src/base/core/streams/InputBitStream.cpp +++ b/src/base/core/streams/InputBitStream.cpp @@ -12,16 +12,15 @@ bool InputBitStream::isFinished() const return mStream->good(); } -std::vector InputBitStream::peekNextNBytes(unsigned) const +void InputBitStream::peekNextNBytes(std::size_t, VecBytes&) const { - return {}; } -std::optional InputBitStream::readNextByte() +std::optional InputBitStream::readNextByte() { if (mStream->good()) { - return static_cast(mStream->get()); + return static_cast(mStream->get()); } else { @@ -29,7 +28,7 @@ std::optional InputBitStream::readNextByte() } } -void InputBitStream::writeByte(unsigned char, bool) +void InputBitStream::writeByte(Byte, bool) { } diff --git a/src/base/core/streams/InputBitStream.h b/src/base/core/streams/InputBitStream.h index 03d3fb1..c6ff565 100644 --- a/src/base/core/streams/InputBitStream.h +++ b/src/base/core/streams/InputBitStream.h @@ -10,13 +10,13 @@ class InputBitStream : public BitStream bool isFinished() const override; - std::vector peekNextNBytes(unsigned n) const override; + void peekNextNBytes(std::size_t n, VecBytes& bytes) const override; - std::optional readNextByte() override; + std::optional readNextByte() override; - void writeByte(unsigned char data, bool checkOverflow = true) override; + void writeByte(Byte data, bool checkOverflow = true) override; - void writeBytes(const std::vector) override + void writeBytes(const VecBytes&) override { } diff --git a/src/base/core/streams/OutputBitStream.cpp b/src/base/core/streams/OutputBitStream.cpp index 2579e24..37fa6db 100644 --- a/src/base/core/streams/OutputBitStream.cpp +++ b/src/base/core/streams/OutputBitStream.cpp @@ -12,22 +12,22 @@ bool OutputBitStream::isFinished() const return true; } -std::vector OutputBitStream::peekNextNBytes(unsigned) const +void OutputBitStream::peekNextNBytes(std::size_t, VecBytes&) const { - return {}; + } -std::optional OutputBitStream::readNextByte() +std::optional OutputBitStream::readNextByte() { return std::nullopt; } -void OutputBitStream::writeByte(unsigned char data, bool) +void OutputBitStream::writeByte(uint8_t data, bool) { (*mStream) << data; } -void OutputBitStream::writeBytes(const std::vector data) +void OutputBitStream::writeBytes(const VecBytes& data) { for(auto byte : data) { diff --git a/src/base/core/streams/OutputBitStream.h b/src/base/core/streams/OutputBitStream.h index 75215d3..bd22014 100644 --- a/src/base/core/streams/OutputBitStream.h +++ b/src/base/core/streams/OutputBitStream.h @@ -11,13 +11,13 @@ public: bool isFinished() const override; - std::vector peekNextNBytes(unsigned n) const override; + void peekNextNBytes(std::size_t n, VecBytes& bytes) const override; - std::optional readNextByte() override; + std::optional readNextByte() override; - void writeByte(unsigned char data, bool checkOverflow = true) override; + void writeByte(Byte data, bool checkOverflow = true) override; - void writeBytes(const std::vector data) override; + void writeBytes(const VecBytes& data) override; private: std::basic_ostream* mStream{nullptr}; diff --git a/src/base/geometry/grid/Grid.h b/src/base/geometry/grid/Grid.h index 424fa8a..7159f4f 100644 --- a/src/base/geometry/grid/Grid.h +++ b/src/base/geometry/grid/Grid.h @@ -12,7 +12,7 @@ public: this->mData->initializeTo(numPointsX * numPointsY * numPointsZ, T()); } - T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx) const override + T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx = 1) const override { return this->mData->getItem(getOffset(idx, jdx, kdx)); } @@ -37,3 +37,40 @@ public: return this->mData->getLength(); } }; + +template +class SerializeableGrid : public Grid +{ +public: + SerializeableGrid(std::size_t itemSize, const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ = 1) + : Grid(bounds, numPointsX, numPointsY, numPointsZ), + mItemSize(itemSize) + { + } + + uint8_t getByte(std::size_t index) + { + const auto item_index = index/mItemSize; + const auto item_internal_index = index % mItemSize; + return this->mData->getItem(item_index).getByte(item_internal_index); + } + + void toBuffer(uint8_t* buffer, std::size_t bufferMaxSize) + { + std::size_t count{0}; + std::size_t item_count{0}; + while(count < bufferMaxSize && item_count < this->mData->getLength()) + { + const auto& item = this->mData->getItem(item_count); + for(std::size_t idx = 0; idx< item.getSize(); idx++) + { + buffer[count] = item.getByte(idx); + count++; + } + item_count++; + } + } + +private: + std::size_t mItemSize{1}; +}; diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt index a127f1a..5702c45 100644 --- a/src/console/CMakeLists.txt +++ b/src/console/CMakeLists.txt @@ -5,7 +5,8 @@ list(APPEND HEADERS BasicWebApp.h) list(APPEND SOURCES - BasicWebApp.cpp + TermInfo.cpp + BasicWebApp.cpp MainApplication.cpp) add_library(${MODULE_NAME} SHARED ${SOURCES} ${HEADERS}) @@ -17,4 +18,4 @@ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src) target_link_libraries(${MODULE_NAME} PUBLIC core audio network database web graphics publishing) set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) -set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src) \ No newline at end of file +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src) diff --git a/src/console/TermInfo.cpp b/src/console/TermInfo.cpp new file mode 100644 index 0000000..ae0ab7b --- /dev/null +++ b/src/console/TermInfo.cpp @@ -0,0 +1,111 @@ +#include "TermInfo.h" + +#include +#include "File.h" +#include +#include + +bool TermInfo::load_terminfo(const std::string& terminfo_dir, + const std::string& term) +{ + const auto path = std::filesystem::path(terminfo_dir); + if (!std::filesystem::is_directory(path)) + { + return false; + } + + std::string suffix = "/" + term; + suffix = term[0] + suffix; + + const auto file_path = path / std::filesystem::path(suffix); + + auto file = File(file_path); + + std::cout << "trying: " << file_path << std::endl; + if (!file.pathExists()) + { + return false; + } + + if (!file.open(File::AccessMode::Read)) + { + return false; + } + + std::vector content; + file.readBinary(content); + short header_size = 12; + if (content.size() < static_cast(header_size)) + { + std::cerr << "terminfo file missing header: " << content.size() << std::endl; + return false; + } + + short magic_number = 256*content[1] + content[0]; + if (magic_number != 282) // octal 0432 + { + std::cerr << "unexpected magic number" << std::endl; + } + short name_size = 256*content[3] + content[2]; + //short bool_size = 256*content[5] + content[4]; + //short numbers_size = 256*content[7] + content[6]; + //short strings_size = 256*content[9] + content[8]; + //short string_table_size = 256*content[11] + content[10]; + std::cout << "got name size: " << name_size << std::endl; + + const auto bool_offset = static_cast(header_size + name_size); + if (content.size() < bool_offset) + { + std::cerr << "unexpected terminfo size" << std::endl; + } + std::vector names; + std::string working_name; + for(std::size_t idx=header_size; idx common_paths = {"/usr/share/terminfo"}; + for (const auto& path : common_paths) + { + if (load_terminfo(path, term)) + { + return; + } + } + + + std::cerr << "Couldn't find terminfo" << std::endl; + } + + + diff --git a/src/console/TermInfo.h b/src/console/TermInfo.h new file mode 100644 index 0000000..74e7fcf --- /dev/null +++ b/src/console/TermInfo.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +class TermInfo +{ +// https://invisible-island.net/ncurses/ +// https://man7.org/linux/man-pages/man5/terminfo.5.html +// Best grab a coffee +public: + bool load_terminfo(const std::string& terminfo_dir, + const std::string& term); + + void load(); +}; + + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..74c9d89 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,43 @@ +#include "Vector.h" +#include "String.h" +#include "FileSystemPath.h" +#include "Directory.h" +#include "File.h" + +#include + +int main() +{ + /* + FileSystemPath main_path(__FILE__); + printf("Starting build.\n"); + + auto main_directory = main_path.parent_path(); + for(const auto& subdir : Directory::getSubdirectories(main_directory)) + { + for(const auto& subsubdir : Directory::getSubdirectories(subdir)) + { + const auto build_file = subsubdir.join("build.toml"); + if (build_file.exists()) + { + printf("Found dir file: %s\n", build_file.as_string().raw()); + // Gather all files + //const auto header_files = Directory::getFilesWithExtension(subsubdir, ".h", true); + //for(const auto& header : header_files) + //{ + // printf("Found header file: %s\n", header.as_string().raw()); + // } + + // Gather all directories + + // Build library + + } + } + } + */ + + printf("Finished build.\n"); + + return 0; +} diff --git a/src/media/image/CMakeLists.txt b/src/media/image/CMakeLists.txt index ec4f824..5ef107f 100644 --- a/src/media/image/CMakeLists.txt +++ b/src/media/image/CMakeLists.txt @@ -4,6 +4,7 @@ set(platform_LIB_INCLUDES) list(APPEND image_HEADERS Image.h + Pixel.h IImageWriter.h PlatformImage.h PlatformImageWriter.h @@ -14,6 +15,7 @@ list(APPEND image_HEADERS list(APPEND image_LIB_INCLUDES Image.cpp + Pixel.cpp ImageBitStream.cpp PlatformImage.cpp png/BasicPngWriter.cpp @@ -21,6 +23,7 @@ list(APPEND image_LIB_INCLUDES png/PngReader.cpp png/PngHeader.cpp png/PngInfo.cpp + png/PngFilter.cpp ) if(WIN32) diff --git a/src/media/image/Image.cpp b/src/media/image/Image.cpp index c9ed06c..be331b2 100644 --- a/src/media/image/Image.cpp +++ b/src/media/image/Image.cpp @@ -3,14 +3,16 @@ #include "Color.h" #include "Grid.h" +#include + #ifdef _WIN32 #include "Win32WicImage.h" #endif -Image::Image(unsigned width, unsigned height, DataType dataType) +Image::Image(unsigned width, unsigned height, Color::Format format) : mWidth(width), mHeight(height), - mDataType(dataType) + mFormat(format) { initialize(); } @@ -20,49 +22,37 @@ Image::~Image() } -std::unique_ptr Image::Create(unsigned width, unsigned height, DataType dataType) +std::unique_ptr Image::Create(unsigned width, unsigned height, Color::Format format) { - return std::make_unique(width, height, dataType); + return std::make_unique(width, height, format); } void Image::initialize() { Bounds bounds(0.0, mWidth, 0.0, mHeight); - if (mDataType == DataType::UCHAR) - { - mData = std::make_unique >(bounds, mWidth, mHeight, mNumChannels); - } - else - { - mData = std::make_unique >(bounds, mWidth, mHeight, mNumChannels); - } + const auto pixel_size = Color::getSize(mFormat, mBitDepth); + mGrid = std::make_unique >(pixel_size, bounds, mWidth, mHeight); } void Image::setPixelValues(const Indices& indices, const std::vector& colors) { - if (!mData) + if (!mGrid) { initialize(); } - if (mDataType == DataType::UCHAR) + assert(indices.size() == colors.size()); + + for (std::size_t idx=0; idx< indices.size(); idx++) { - auto grid = getGridT(); - for (std::size_t idx=0; idx< indices.size(); idx++) - { - auto id = indices[idx]; - auto color = colors[idx]; - grid->setItem(id.first, id.second, 0, color.getR()); - grid->setItem(id.first, id.second, 1, color.getG()); - grid->setItem(id.first, id.second, 2, color.getB()); - } + const auto id = indices[idx]; + mGrid->getItem(id.first, id.second).setColor(colors[idx]); } } unsigned Image::getBytesPerRow() const { - const auto bitsPerEntry = mBitDepth <= 8 ? 1 : 2; - return mWidth * mNumChannels * bitsPerEntry; + return mWidth * Color::getSize(mFormat, mBitDepth); } unsigned Image::getWidth() const @@ -91,25 +81,29 @@ PlatformImage* Image::getPlatformImage() return mPlatformImage.get(); } -AbstractGrid* Image::getGrid() const +SerializeableGrid* Image::getGrid() const { - return mData.get(); + return mGrid.get(); } -template -Grid* Image::getGridT() const +uint8_t Image::getByte(std::size_t index) const { - return dynamic_cast*>(this->mData.get()); + return mGrid->getByte(index); } -Image::DataType Image::getType() const +void Image::toBuffer(uint8_t* buffer, std::size_t bufferMaxSize) { - return mDataType; + mGrid->toBuffer(buffer, bufferMaxSize); +} + +Color::Format Image::getFormat() const +{ + return mFormat; } unsigned Image::getNumChannels() const { - return mNumChannels; + return Color::getNumChannels(mFormat); } void Image::setWidth(unsigned width) @@ -127,8 +121,8 @@ void Image::setBitDepth(unsigned bitDepth) mBitDepth = bitDepth; } -void Image::setNumChannels(unsigned numChannels) +void Image::setFormat(Color::Format format) { - mNumChannels = numChannels; + mFormat = format; } diff --git a/src/media/image/Image.h b/src/media/image/Image.h index 817915b..4050000 100644 --- a/src/media/image/Image.h +++ b/src/media/image/Image.h @@ -1,30 +1,25 @@ #pragma once #include "PlatformImage.h" +#include "Pixel.h" #include #include class Color; -class AbstractGrid; template -class Grid; +class SerializeableGrid; class Image { public: - enum class DataType - { - UCHAR - }; - using Index = std::pair; using Indices = std::vector; - Image(unsigned width, unsigned height, DataType dataType = DataType::UCHAR); + Image(unsigned width, unsigned height, Color::Format format = Color::Format::RGBA); ~Image(); - static std::unique_ptr Create(unsigned width, unsigned height, DataType dataType = DataType::UCHAR); + static std::unique_ptr Create(unsigned width, unsigned height, Color::Format format = Color::Format::RGBA); unsigned getBytesPerRow() const; unsigned getWidth() const; @@ -32,28 +27,27 @@ public: unsigned getBitDepth() const; unsigned getNumChannels() const; - AbstractGrid* getGrid() const; + uint8_t getByte(std::size_t index) const; + SerializeableGrid* getGrid() const; - template - Grid* getGridT() const; - - DataType getType() const; + Color::Format getFormat() const; PlatformImage* getPlatformImage(); void setPixelValues(const Indices& indices, const std::vector& colors); void setWidth(unsigned width); void setHeight(unsigned height); void setBitDepth(unsigned bitDepth); - void setNumChannels(unsigned numChannels); + void setFormat(Color::Format format); + + void toBuffer(uint8_t* buffer, std::size_t bufferMaxSize); private: void initialize(); unsigned mWidth{1}; unsigned mHeight{1}; unsigned mBitDepth{8}; - unsigned mNumChannels{4}; + Color::Format mFormat{Color::Format::RGBA}; - DataType mDataType; - std::unique_ptr mData; + std::unique_ptr > mGrid; std::unique_ptr mPlatformImage; }; diff --git a/src/media/image/ImageBitStream.cpp b/src/media/image/ImageBitStream.cpp index a53df70..75ac0fd 100644 --- a/src/media/image/ImageBitStream.cpp +++ b/src/media/image/ImageBitStream.cpp @@ -1,6 +1,7 @@ #include "ImageBitStream.h" -#include "AbstractGrid.h" +#include "Grid.h" +#include "Pixel.h" ImageBitStream::ImageBitStream(Image* image) : BitStream(), @@ -14,25 +15,22 @@ bool ImageBitStream::isFinished() const return mByteOffset == static_cast(mImage->getGrid()->getDataSize()); } -std::vector ImageBitStream::peekNextNBytes(unsigned) const +std::vector ImageBitStream::peekNextNBytes(std::size_t) const { return {}; } -std::optional ImageBitStream::readNextByte() +std::optional ImageBitStream::readNextByte() { mByteOffset++; - if (isFinished() ) { return std::nullopt; } - //const auto val = mImage->getData()->getAsUnsignedChar(mByteOffset); - //return val; - return {}; + return mImage->getByte(mByteOffset); } -void ImageBitStream::writeByte(unsigned char, bool ) +void ImageBitStream::writeByte(uint8_t, bool ) { mByteOffset++; diff --git a/src/media/image/ImageBitStream.h b/src/media/image/ImageBitStream.h index 0ad286d..a759a87 100644 --- a/src/media/image/ImageBitStream.h +++ b/src/media/image/ImageBitStream.h @@ -4,6 +4,8 @@ #include "Image.h" +#include + class ImageBitStream : public BitStream { public: @@ -11,13 +13,13 @@ public: bool isFinished() const override; - std::vector peekNextNBytes(unsigned n) const override; + std::vector peekNextNBytes(std::size_t n) const override; - std::optional readNextByte() override; + std::optional readNextByte() override; - void writeByte(unsigned char data, bool checkOverflow = true) override; + void writeByte(uint8_t data, bool checkOverflow = true) override; - void writeBytes(const std::vector) override + void writeBytes(const std::vector&) override { } diff --git a/src/media/image/Pixel.cpp b/src/media/image/Pixel.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/media/image/Pixel.h b/src/media/image/Pixel.h new file mode 100644 index 0000000..c5bb43f --- /dev/null +++ b/src/media/image/Pixel.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Color.h" +#include "Serializeable.h" + +class Pixel : public Serializeable +{ +public: + void setColor(const Color& color) + { + mColor = color; + } + + std::size_t getSize() const override + { + return mColor.getSize(); + } + + uint8_t getByte(std::size_t index) const override + { + return mColor.getByte(index); + } + +private: + Color mColor; +}; \ No newline at end of file diff --git a/src/media/image/png/BasicPngWriter.cpp b/src/media/image/png/BasicPngWriter.cpp index c98d300..4ba964e 100644 --- a/src/media/image/png/BasicPngWriter.cpp +++ b/src/media/image/png/BasicPngWriter.cpp @@ -88,13 +88,13 @@ void BasicPngWriter::writeHeader() auto crc = mPngHeader.getCrc(); - //std::cout << mPngHeader.toString() << "*********" << std::endl; + std::cout << mPngHeader.toString() << "*********" << std::endl; mOutStream->write(crc); } void BasicPngWriter::writeEndChunk() { - //std::cout << "Start writing end chunk" << std::endl; + std::cout << "Start writing end chunk" << std::endl; unsigned length{ 0 }; mOutStream->write(length); @@ -109,7 +109,7 @@ void BasicPngWriter::writeEndChunk() auto crc = crc_check.getChecksum(); mOutStream->write(crc); - //std::cout << "Writing end chunk" << std::endl; + std::cout << "Finishe Writing end chunk" << std::endl; } void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer) @@ -128,7 +128,7 @@ void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer) } (void)length; - //std::cout << "Writing idat length " << num_bytes << std::endl; + std::cout << "Writing idat length " << num_bytes << std::endl; mOutStream->write(static_cast(num_bytes)); std::vector char_data = StringUtils::toBytes("IDAT"); @@ -148,7 +148,7 @@ void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer) } auto crc = crc_check.getChecksum(); - //std::cout << "Writing idat crc" << crc << std::endl; + std::cout << "Writing idat crc: " << crc << std::endl; mOutStream->write(crc); //std::cout << "Finished Writing idat crc" << crc << std::endl; } @@ -158,7 +158,7 @@ void BasicPngWriter::write(const Path& path, Image* image) { std::unique_ptr out_file; - if (path.empty()) + if (!path.empty()) { out_file = std::make_unique(path); out_file->open(File::AccessMode::Write); diff --git a/src/media/image/png/BasicPngWriter.h b/src/media/image/png/BasicPngWriter.h index ee2e051..fd60e91 100644 --- a/src/media/image/png/BasicPngWriter.h +++ b/src/media/image/png/BasicPngWriter.h @@ -22,7 +22,9 @@ public: virtual ~BasicPngWriter(); - static std::unique_ptr Create(); + using Ptr = std::unique_ptr; + + static BasicPngWriter::Ptr Create(); void setCompressionMethod(Deflate::CompressionMethod method); @@ -44,7 +46,7 @@ private: std::unique_ptr mInStream; std::unique_ptr mOutStream; - unsigned mPngInfoUserSet{ false }; + bool mPngInfoUserSet{ false }; PngInfo mPngInfo; PngHeader mPngHeader; diff --git a/src/media/image/png/PngFilter.cpp b/src/media/image/png/PngFilter.cpp new file mode 100644 index 0000000..35ba226 --- /dev/null +++ b/src/media/image/png/PngFilter.cpp @@ -0,0 +1,77 @@ +#include "PngFilter.h" +#include + +PngFilter::PngFilter(BitStream* inputStream, BitStream* outputStream) + : mInputStream(inputStream), + mOutputStream(outputStream) + +{ + +} + +void PngFilter::encode() +{ + auto image_stream = dynamic_cast(mInputStream); + if (!image_stream) + { + MLOG_ERROR("Expected ImageStream in PngFilter encode - aborting."); + return; + } + + const auto bytes_per_scanline = image_stream->getBytesPerScanline(); + unsigned count{0}; + if (mFilterType == FilterType::NONE) + { + while(true) + { + if (const auto byte = image_stream->readNextByte()) + { + if (count % bytes_per_scanline == 0) + { + mOutputStream->writeByte(0); + } + + mOutputStream->writeByte(*byte); + } + else + { + break; + } + count++; + } + } +} + +void PngFilter::decode() +{ + auto image_stream = dynamic_cast(mOutputStream); + if (!image_stream) + { + MLOG_ERROR("Expected ImageStream in PngFilter decode - aborting."); + return; + } + + const auto bytes_per_scanline = image_stream->getBytesPerScanline(); + unsigned count{0}; + + FilterType working_filter_type = FilterType::NONE; + while(auto byte = mInputStream->readNextByte()) + { + if (count % bytes_per_scanline == 0) + { + working_filter_type = static_cast(*byte); + } + else + { + if (working_filter_type == FilterType::NONE) + { + image_stream->writeByte(*byte); + } + else + { + //std::cout << "Got filter type " << static_cast(working_filter_type) << std::endl; + } + } + count++; + } +} \ No newline at end of file diff --git a/src/media/image/png/PngFilter.h b/src/media/image/png/PngFilter.h index 1075c66..680008e 100644 --- a/src/media/image/png/PngFilter.h +++ b/src/media/image/png/PngFilter.h @@ -19,83 +19,13 @@ public: PAETH }; - PngFilter(BitStream* inputStream, BitStream* outputStream) - : mInputStream(inputStream), - mOutputStream(outputStream) + PngFilter(BitStream* inputStream, BitStream* outputStream); - { + void encode(); - } - - void encode() - { - auto image_stream = dynamic_cast(mInputStream); - if (!image_stream) - { - MLOG_ERROR("Expected ImageStream in PngFilter encode - aborting."); - return; - } - - const auto bytes_per_scanline = image_stream->getBytesPerScanline(); - unsigned count{0}; - if (mFilterType == FilterType::NONE) - { - while(true) - { - if (const auto byte = image_stream->readNextByte()) - { - if (count % bytes_per_scanline == 0) - { - mOutputStream->writeByte(0); - } - - mOutputStream->writeByte(*byte); - } - else - { - break; - } - count++; - } - } - } - - void decode() - { - auto image_stream = dynamic_cast(mOutputStream); - if (!image_stream) - { - MLOG_ERROR("Expected ImageStream in PngFilter decode - aborting."); - return; - } - - const auto bytes_per_scanline = image_stream->getBytesPerScanline(); - unsigned count{0}; - - FilterType working_filter_type = FilterType::NONE; - while(auto byte = mInputStream->readNextByte()) - { - if (count % bytes_per_scanline == 0) - { - working_filter_type = static_cast(*byte); - } - else - { - if (working_filter_type == FilterType::NONE) - { - image_stream->writeByte(*byte); - } - else - { - //std::cout << "Got filter type " << static_cast(working_filter_type) << std::endl; - } - } - count++; - } - } + void decode(); private: - FilterType mFilterType{FilterType::NONE}; BitStream* mInputStream{nullptr}; BitStream* mOutputStream{nullptr}; diff --git a/src/media/image/png/PngHeader.cpp b/src/media/image/png/PngHeader.cpp index b9fa13b..1cfadfa 100644 --- a/src/media/image/png/PngHeader.cpp +++ b/src/media/image/png/PngHeader.cpp @@ -10,26 +10,46 @@ std::string PngHeader::toString() const sstr << "PngHeader" << "\n"; sstr << "width: " << mWidth << "\n"; sstr << "height: " << mHeight << "\n"; - sstr << "bitDepth: " << (int)mBitDepth << "\n"; + sstr << "bitDepth: " << static_cast(mBitDepth) << "\n"; sstr << "cached CRC: " << mCachedCrc << "\n"; sstr << mPngInfo.toString(); return sstr.str(); } -uint32_t PngHeader::getLength() const +DWord PngHeader::getWidth() const +{ + return mWidth; +} + +DWord PngHeader::getHeight() const +{ + return mHeight; +} + +Byte PngHeader::getBitDepth() const +{ + return mBitDepth; +} + +const PngInfo& PngHeader::getPngInfo() const +{ + return mPngInfo; +} + +DWord PngHeader::getLength() const { return 13; } -unsigned char PngHeader::getHighBitCheck() const +Byte PngHeader::getHighBitCheck() const { return 0x89; } -std::vector PngHeader::getSignature() const +void PngHeader::getSignature(VecBytes& sig) const { - return {13, 10, 26, 10}; + sig = {13, 10, 26, 10}; } std::string PngHeader::getFileName() const @@ -42,7 +62,7 @@ const std::string& PngHeader::getChunkName() const return mName; } -const std::vector& PngHeader::getData() const +const VecBytes& PngHeader::getData() const { return mData; } @@ -50,9 +70,9 @@ const std::vector& PngHeader::getData() const void PngHeader::updateData() { mData.clear(); - unsigned num_bytes = sizeof(uint32_t); + const auto num_bytes = sizeof(DWord); - for(unsigned idx=0; idx(mPngInfo.mColorType)); - mData.push_back(static_cast(mPngInfo.mCompressionMethod)); - mData.push_back(static_cast(mPngInfo.mFilterMethod)); - mData.push_back(static_cast(mPngInfo.mInterlaceMethod)); + mData.push_back(static_cast(mPngInfo.mColorType)); + mData.push_back(static_cast(mPngInfo.mCompressionMethod)); + mData.push_back(static_cast(mPngInfo.mFilterMethod)); + mData.push_back(static_cast(mPngInfo.mInterlaceMethod)); } -uint32_t PngHeader::getCrc() +DWord PngHeader::getCrc() { CyclicRedundancyChecker crc_check; std::vector char_data = StringUtils::toBytes(mName); diff --git a/src/media/image/png/PngHeader.h b/src/media/image/png/PngHeader.h index ba96b6b..0f4ff96 100644 --- a/src/media/image/png/PngHeader.h +++ b/src/media/image/png/PngHeader.h @@ -8,35 +8,23 @@ class PngHeader { public: - uint32_t getLength() const; + DWord getLength() const; - uint32_t getCrc(); + DWord getCrc(); - const std::vector& getData() const; + const VecBytes& getData() const; - uint32_t getWidth() const - { - return mWidth; - } + DWord getWidth() const; - uint32_t getHeight() const - { - return mHeight; - } + DWord getHeight() const; - unsigned char getBitDepth() const - { - return mBitDepth; - } + Byte getBitDepth() const; - const PngInfo& getPngInfo() const - { - return mPngInfo; - } + const PngInfo& getPngInfo() const; - unsigned char getHighBitCheck() const; + Byte getHighBitCheck() const; - std::vector getSignature() const; + void getSignature(VecBytes& sig) const; std::string getFileName() const; @@ -44,20 +32,20 @@ public: void setPngInfo(const PngInfo& info); - void setImageData(uint32_t width, uint32_t height, unsigned char bitDepth); + void setImageData(DWord width, DWord height, Byte bitDepth); std::string toString() const; void updateData(); private: - uint32_t mWidth{0}; - uint32_t mHeight{0}; - unsigned char mBitDepth{0}; + DWord mWidth{0}; + DWord mHeight{0}; + Byte mBitDepth{0}; PngInfo mPngInfo; std::string mName{"IHDR"}; - uint32_t mCachedCrc{0}; + DWord mCachedCrc{0}; - std::vector mData; + VecBytes mData; }; diff --git a/src/media/image/png/PngInfo.cpp b/src/media/image/png/PngInfo.cpp index c505a1e..6bc3f53 100644 --- a/src/media/image/png/PngInfo.cpp +++ b/src/media/image/png/PngInfo.cpp @@ -19,23 +19,9 @@ std::string PngInfo::toString(ColorType colorType) const } } -unsigned PngInfo::getNumChannels() const +ColorType PngInfo::ColorType() const { - switch(mColorType) - { - case ColorType::GREYSCALE: - return 1; - case ColorType::RGB: - return 3; - case ColorType::PALETTE: - return 1; - case ColorType::GREYSCALE_ALPHA: - return 2; - case ColorType::RGB_ALPHA: - return 4; - default: - return 1; - } + return mColorType; } std::string PngInfo::toString(CompressionMethod method) const @@ -73,7 +59,7 @@ std::string PngInfo::toString(InterlaceMethod method) const } } -bool PngInfo::bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const +bool PngInfo::bitDepthIsValid(ColorType colorType, Byte bitDepth) const { switch(colorType) { @@ -92,12 +78,12 @@ bool PngInfo::bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const } } -bool PngInfo::compressionMethodIsValid(unsigned char method) +bool PngInfo::compressionMethodIsValid(Byte method) { return method == 0; } -bool PngInfo::filterMethodIsValid(unsigned char method) +bool PngInfo::filterMethodIsValid(Byte method) { return method == 0; } diff --git a/src/media/image/png/PngInfo.h b/src/media/image/png/PngInfo.h index d6e1e08..1319ff4 100644 --- a/src/media/image/png/PngInfo.h +++ b/src/media/image/png/PngInfo.h @@ -1,12 +1,14 @@ #pragma once +#include "ByteTypes.h" + #include #include class PngInfo { public: - enum class ColorType : unsigned char + enum class ColorType : Byte { GREYSCALE = 0, RGB = 2, @@ -15,23 +17,23 @@ public: RGB_ALPHA = 6 }; - enum class CompressionMethod : unsigned char + enum class CompressionMethod : Byte { DEFLATE = 0 }; - enum class FilterMethod : unsigned char + enum class FilterMethod : Byte { ADAPTIVE = 0 }; - enum class InterlaceMethod : unsigned char + enum class InterlaceMethod : Byte { NONE = 0, ADAM7 = 1 }; - unsigned getNumChannels() const; + ColorType getColorType() const; std::string toString(ColorType colorType) const; @@ -41,11 +43,11 @@ public: std::string toString(InterlaceMethod method) const; - bool bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const; + bool bitDepthIsValid(ColorType colorType, Byte bitDepth) const; - bool compressionMethodIsValid(unsigned char method); + bool compressionMethodIsValid(Byte method); - bool filterMethodIsValid(unsigned char method); + bool filterMethodIsValid(Byte method); std::string toString() const; diff --git a/src/media/image/png/PngWriter.cpp b/src/media/image/png/PngWriter.cpp index e8744de..c08dbfa 100644 --- a/src/media/image/png/PngWriter.cpp +++ b/src/media/image/png/PngWriter.cpp @@ -26,6 +26,15 @@ std::unique_ptr PngWriter::Create() return std::make_unique(); } +void PngWriter::setCompressionMethod(Deflate::CompressionMethod method) +{ +#ifdef _WIN32 + (void)method; +#else + dynamic_cast(mWriterImpl.get())->setCompressionMethod(method); +#endif +} + void PngWriter::write(const Path& path, Image* image) { mWriterImpl->write(path, image); diff --git a/src/media/image/png/PngWriter.h b/src/media/image/png/PngWriter.h index 6cb994d..03091c3 100644 --- a/src/media/image/png/PngWriter.h +++ b/src/media/image/png/PngWriter.h @@ -2,6 +2,7 @@ #include "Image.h" #include "IImageWriter.h" +#include "DeflateElements.h" #include #include @@ -14,6 +15,8 @@ public: static std::unique_ptr Create(); + void setCompressionMethod(Deflate::CompressionMethod method); + void write(const Path& path, Image* image) override; private: diff --git a/src/ui/windows/ui_interfaces/wayland/WaylandInterface.cpp b/src/ui/windows/ui_interfaces/wayland/WaylandInterface.cpp index e5f02b9..1cdf19d 100644 --- a/src/ui/windows/ui_interfaces/wayland/WaylandInterface.cpp +++ b/src/ui/windows/ui_interfaces/wayland/WaylandInterface.cpp @@ -12,6 +12,7 @@ #include #include +#include void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) @@ -41,6 +42,7 @@ void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry void WaylandInterface::registryHandleGlobalRemoveEvent(void *data, struct wl_registry *registry, uint32_t name) { + std::cout << "remove handler called " << std::endl; (void)data; (void)registry; (void)name; @@ -90,7 +92,7 @@ void WaylandInterface::initialize() addWindow(mDesktopManager->getWindowManager()->getWindow(idx)); } - mDesktopManager->getWindowManager()->getMainWindow()->show(); + mDesktopManager->getWindowManager()->getMainWindow()->show(); } void WaylandInterface::initializeHardwareRendering() diff --git a/src/ui/windows/ui_interfaces/wayland/WaylandSurface.cpp b/src/ui/windows/ui_interfaces/wayland/WaylandSurface.cpp index f3fe6a0..c26e6c9 100644 --- a/src/ui/windows/ui_interfaces/wayland/WaylandSurface.cpp +++ b/src/ui/windows/ui_interfaces/wayland/WaylandSurface.cpp @@ -6,6 +6,8 @@ #include "DrawingContext.h" #include "FontsManager.h" +#include + void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, FontsManager* fontsManager, WaylandEglInterface* eglInterface) { auto wayland_window = std::make_unique(window, compositor, xdg_wm_base, buffer, eglInterface); @@ -78,7 +80,7 @@ void WaylandSurface::initialize() void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial) { xdg_surface_ack_configure(xdg_surface, serial); - beforePaint(nullptr); + mWindow->doPaint(nullptr); } void WaylandSurface::beforePaint(mt::Screen* screen) @@ -124,21 +126,30 @@ void WaylandSurface::beforePaintSoftware() const auto height = mWindow->getHeight(); const int stride = width * mWorkingBitDepth; + std::cout << "before paint" << std::endl; + const int shm_pool_size = getImageBufferSize(); mBuffer->initializeSharedBuffer(shm_pool_size); mBuffer->setUpPool(shm_pool_size, width, height, stride); + //int offset{0}; + + mWindow->getImage()->toBuffer(mBuffer->getPoolData(), width*height*stride, Image::Format::ARGB); + //ImagePrimitives::drawCheckerboard(mBuffer->getPoolData(), width, height, offset); + std::cout << "checkerboard drawn" << std::endl; } void WaylandSurface::afterPaintSoftware() { + std::cout << "after paint" << std::endl; + const int shm_pool_size = getImageBufferSize(); mBuffer->tearDownPool(shm_pool_size); wl_surface_attach(mSurface, mBuffer->getWorkingBuffer(), 0, 0); - //wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX); + wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX); wl_surface_commit(mSurface); } diff --git a/src/ui/windows/ui_interfaces/wayland/WaylandSurface.h b/src/ui/windows/ui_interfaces/wayland/WaylandSurface.h index 275e548..ec91148 100644 --- a/src/ui/windows/ui_interfaces/wayland/WaylandSurface.h +++ b/src/ui/windows/ui_interfaces/wayland/WaylandSurface.h @@ -53,7 +53,7 @@ private: unsigned getImageBufferSize() const; - mt::Window* mWindow{nullptr}; + //mt::Window* mWindow{nullptr}; wl_compositor* mCompositor{nullptr}; xdg_wm_base* mXdgWmBase{nullptr}; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3f41db8..d94c95e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,6 +4,7 @@ set(UNIT_TEST_TARGETS) set(INTEGRATION_TEST_TARGETS) add_subdirectory(core) +#add_subdirectory(console) add_subdirectory(database) add_subdirectory(fonts) add_subdirectory(geometry) @@ -18,6 +19,7 @@ set(TEST_MODULES audio compiler compression + console image ipc mesh diff --git a/test/bootstrap_tests.sh b/test/bootstrap_tests.sh new file mode 100755 index 0000000..327deb7 --- /dev/null +++ b/test/bootstrap_tests.sh @@ -0,0 +1,23 @@ +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +CORE_SRC_DIR=$SCRIPT_DIR/../src/base/core + +g++ $SCRIPT_DIR/test_runner.cpp \ + $SCRIPT_DIR/../src/base/core/CommandLineArgs.cpp \ + $CORE_SRC_DIR/base_types/Error.cpp \ + $CORE_SRC_DIR/base_types/Index.cpp \ + $CORE_SRC_DIR/data_structures/String.cpp \ + $CORE_SRC_DIR/file_utilities/FileSystemPath.cpp \ + $CORE_SRC_DIR/loggers/ConsoleLogger.cpp \ + $SCRIPT_DIR/test_utils/TestCaseRunner.cpp \ + $SCRIPT_DIR/core/TestString.cpp \ + $SCRIPT_DIR/core/TestVector.cpp \ + -o bootstrap_tests -g \ + -I$SCRIPT_DIR/test_utils \ + -I$CORE_SRC_DIR \ + -I$CORE_SRC_DIR/encoding \ + -I$CORE_SRC_DIR/loggers \ + -I$CORE_SRC_DIR/data_structures \ + -I$CORE_SRC_DIR/base_types \ + -I$CORE_SRC_DIR/memory \ + -I$CORE_SRC_DIR/file_utilities \ No newline at end of file diff --git a/test/console/CMakeLists.txt b/test/console/CMakeLists.txt new file mode 100644 index 0000000..bae7845 --- /dev/null +++ b/test/console/CMakeLists.txt @@ -0,0 +1,9 @@ +include(TestTargets) + +unit_tests( + MODULE_NAME console + FILES + TestConsoleApp.cpp + DEPENDENCIES + console +) diff --git a/test/console/TestConsoleApp.cpp b/test/console/TestConsoleApp.cpp new file mode 100644 index 0000000..bb15f0b --- /dev/null +++ b/test/console/TestConsoleApp.cpp @@ -0,0 +1,93 @@ +#include "TestFramework.h" +#include "TestUtils.h" + +#include "TermInfo.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +TEST_CASE(TestConsoleApp, "console") +{ + //std::cout << "Hi from test console\n"; + + int ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd > 0) + { + std::cout << "opened tty ok\n" << std::endl; + } + + if (isatty(ttyfd)) + { + auto tty_name = ttyname(ttyfd); + std::string tty_name_str; + if (tty_name != nullptr) + { + tty_name_str = std::string(tty_name); + } + + std::string fd_msg = "Hello tty: '" + tty_name_str + "'\n"; + //write(ttyfd, fd_msg.data(), fd_msg.size()); + + TermInfo term_info; + term_info.load(); + /* + + termios orig_tios; + tcgetattr(ttyfd, &orig_tios); + + termios tios; + memcpy(&tios, &orig_tios, sizeof(tios)); + + cfmakeraw(&tios); + tios.c_cc[VMIN] = 1; + tios.c_cc[VTIME] = 0; + + tcsetattr(ttyfd, TCSAFLUSH, &tios); + + //int cap_enter_ca = 23; + //int cap_exit_ca = 24; + //int cap_hide_cursor = 26; + //int cap_clear_screen = 27; + + + fd_set fds; + FD_ZERO(&fds); + + int timeout = 2000; + timeval tv; + tv.tv_sec = timeout/1000; + tv.tv_usec = (timeout - (tv.tv_sec*1000))*1000; + + while(true) + { + + int select_rv = select(1, &fds, nullptr, nullptr, &tv); + + if (select_rv == 0) + { + std::cout << "timeout" << std::endl; + break; + } + std::vector buffer(100); + auto read_size = read(ttyfd, buffer.data(), buffer.size()); + std::string out(buffer.begin(), buffer.begin()+read_size); + std::cout << "buf: " << out << std::endl; + } + std::cout << "loop break" << std::endl; + tcsetattr(ttyfd, TCSAFLUSH, &orig_tios); + */ + + } + + close(ttyfd); +} diff --git a/test/core/TestStringUtils.cpp b/test/core/TestString.cpp similarity index 57% rename from test/core/TestStringUtils.cpp rename to test/core/TestString.cpp index 7c7e005..5441d79 100644 --- a/test/core/TestStringUtils.cpp +++ b/test/core/TestString.cpp @@ -1,8 +1,43 @@ -#include "StringUtils.h" +#include "String.h" #include "TestFramework.h" -#include "TestUtils.h" +//#include "TestUtils.h" +#include +TEST_CASE(TestBasicStringOps, "core") +{ + String str; + str += 'a'; + str += 'b'; + str += 'c'; + str += 'd'; + REQUIRE(str == "abcd"); +} + +TEST_CASE(TestStringReverse, "core") +{ + String str0; + str0.reverse(); + REQUIRE(str0.empty()); + + String str1("a"); + str1.reverse(); + REQUIRE(str1 == "a"); + + String str2("ab"); + str2.reverse(); + REQUIRE(str2 == "ba"); + + String str3("abc"); + str3.reverse(); + REQUIRE(str3 == "cba"); + + String str4("abcd"); + str4.reverse(); + REQUIRE(str4 == "dcba"); +} + +/* TEST_CASE(TestStringUtils_StripSurroundingWhitepsace, "core") { std::string input = " super() "; @@ -28,3 +63,5 @@ TEST_CASE(TestStringUtils_startsWith, "core") starts_with = StringUtils::startsWith(input, "```", ignore_whitespace); REQUIRE(starts_with); } + +*/ diff --git a/test/core/TestVector.cpp b/test/core/TestVector.cpp new file mode 100644 index 0000000..938676a --- /dev/null +++ b/test/core/TestVector.cpp @@ -0,0 +1,18 @@ +#include "Vector.h" + +#include "TestFramework.h" + +#include + +TEST_CASE(TestVectorOps, "core") +{ + Vector vec; + for(size_t idx=0;idx<100;idx++) + { + vec.push_back(idx); + } + for(size_t idx=0; idx<100; idx++) + { + REQUIRE(vec[idx] == idx); + } +} diff --git a/test/image/TestPngWriter.cpp b/test/image/TestPngWriter.cpp index 3db10b3..a340064 100644 --- a/test/image/TestPngWriter.cpp +++ b/test/image/TestPngWriter.cpp @@ -11,7 +11,7 @@ #include "TestUtils.h" #include -TEST_CASE(TestCompressedPng, "image") +TEST_CASE(TestUncompressedPng, "image") { unsigned width = 20; unsigned height = 20; @@ -30,13 +30,14 @@ TEST_CASE(TestCompressedPng, "image") image->getGridT()->setData(data); PngWriter writer; - //writer.setCompressionMethod(Deflate::CompressionMethod::NONE); - writer.write(TestUtils::getTestOutputDir() / "test_compressed.png", image.get()); + writer.setCompressionMethod(Deflate::CompressionMethod::NONE); + writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_uncompressed.png", image.get()); - return; - File test_file(TestUtils::getTestOutputDir() / "test_compressed.png"); + File test_file(TestUtils::getTestOutputDir(__FILE__) / "test_uncompressed.png"); test_file.open(File::AccessMode::Read); + std::cout << test_file.dumpBinary(); + return; while(auto byte = test_file.readNextByte()) { //std::cout << static_cast(*byte) << std::endl; @@ -63,13 +64,8 @@ TEST_CASE(TestFixedPng, "image") image->getGridT()->setData(data); PngWriter writer; - //writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN); - writer.write(TestUtils::getTestOutputDir() / "test_fixed.png", image.get()); - - //return; - File test_file(TestUtils::getTestOutputDir() / "test_fixed.png"); - //std::cout << test_file.dumpBinary(); - + writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN); + writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_fixed.png", image.get()); } TEST_CASE(TestDynamicCompressedPng, "image") @@ -93,9 +89,9 @@ TEST_CASE(TestDynamicCompressedPng, "image") PngWriter writer; //writer.setPath(TestUtils::getTestOutputDir() / "test_dynamic.png"); - writer.write(TestUtils::getTestOutputDir() / "test_dynamic.png", image.get()); + writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_dynamic.png", image.get()); //return; - File test_file(TestUtils::getTestOutputDir() / "test_dynamic.png"); + File test_file(TestUtils::getTestOutputDir(__FILE__) / "test_dynamic.png"); //std::cout << test_file.dumpBinary(); } diff --git a/test/test_runner.cpp b/test/test_runner.cpp index b2cb3f7..30ab10f 100644 --- a/test/test_runner.cpp +++ b/test/test_runner.cpp @@ -1,6 +1,7 @@ #include "TestFramework.h" #include "CommandLineArgs.h" +#include "ConsoleLogger.h" #ifdef _WIN32 #include @@ -13,10 +14,12 @@ int main(int argc, char *argv[]) CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); #endif - auto args = CommandLineArgs::Create(); - args->process(argc, argv); + CommandLineArgs args; + args.process(argc, argv); - TestCaseRunner::getInstance().run(args->getUserArgs()); + ConsoleLogger::logLine("Starting test run."); + TestCaseRunner::getInstance().run(args.getUserArgs()); + ConsoleLogger::logLine("Finished test run."); #ifdef _WIN32 CoUninitialize(); diff --git a/test/test_utils/TestCase.h b/test/test_utils/TestCase.h index 1a01a45..21df33c 100644 --- a/test/test_utils/TestCase.h +++ b/test/test_utils/TestCase.h @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include "String.h" +#include "Pointer.h" #include class TestCase @@ -9,7 +9,7 @@ class TestCase public: using TestCaseFunction = std::function; - TestCase(const std::string& name, const std::string& tags, TestCaseFunction func) + TestCase(const String& name, const String& tags, TestCaseFunction func) : mTestFunction(func), mName(name), mTags(tags) @@ -19,12 +19,12 @@ public: virtual ~TestCase() = default; - const std::string& getName() const + const String& getName() const { return mName; } - const std::string& getTags() const + const String& getTags() const { return mTags; } @@ -38,8 +38,8 @@ public: TestCaseFunction mTestFunction{nullptr}; private: - std::string mName; - std::string mTags; + String mName; + String mTags; }; -using TestCasePtr = std::unique_ptr; +using TestCasePtr = Ptr; diff --git a/test/test_utils/TestCaseRunner.cpp b/test/test_utils/TestCaseRunner.cpp index 8d5ffc2..0979866 100644 --- a/test/test_utils/TestCaseRunner.cpp +++ b/test/test_utils/TestCaseRunner.cpp @@ -1,13 +1,11 @@ #include "TestCaseRunner.h" #include "FileLogger.h" -#include "TestUiApplication.h" - -#include -#include +#include "ConsoleLogger.h" +//#include "TestUiApplication.h" bool TestCaseRunner::sLastTestFailed = false; -std::string TestCaseRunner::sFailureLine = {}; +String TestCaseRunner::sFailureLine = {}; TestCaseRunner::TestCaseRunner() { @@ -19,6 +17,7 @@ TestCaseRunner::~TestCaseRunner() } +/* TestUiApplication* TestCaseRunner::getTestApplication() { return mTestApplication; @@ -28,6 +27,7 @@ void TestCaseRunner::setTestApplication(TestUiApplication* app) { mTestApplication = app; } +*/ TestCaseRunner& TestCaseRunner::getInstance() { @@ -35,26 +35,26 @@ TestCaseRunner& TestCaseRunner::getInstance() return instance; } -void TestCaseRunner::addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func) +void TestCaseRunner::addTestCase(const String& label, const String& tag, TestCase::TestCaseFunction func) { auto test_case = new TestCase(label, tag, func); mCases.push_back(test_case); } -void TestCaseRunner::markTestFailure(const std::string& line) +void TestCaseRunner::markTestFailure(const String& line) { sLastTestFailed = true; sFailureLine = line; } -bool TestCaseRunner::run(const std::vector& args) +bool TestCaseRunner::run(const Vector& args) { - std::string test_to_run; + String test_to_run; if (args.size() > 0 ) { test_to_run = args[0]; } - FileLogger::GetInstance().disable(); + //FileLogger::GetInstance().disable(); for (auto test_case : mCases) { if (!test_to_run.empty()) @@ -66,41 +66,22 @@ bool TestCaseRunner::run(const std::vector& args) } sLastTestFailed = false; - std::cout << "TestFramework: Running Test - " << test_case->getName() << std::endl; - - try - { - test_case->run(); - } - catch (const std::runtime_error& re) - { - std::cout << "Failed with runtime error: " << re.what() << std::endl; - mFailingTests.push_back(test_case->getName()); - } - catch (const std::exception& e) - { - std::cout << "Failed with exception: " << e.what() << std::endl; - mFailingTests.push_back(test_case->getName()); - } - catch(...) - { - std::cout << "Failed with unknown exception" << std::endl; - mFailingTests.push_back(test_case->getName()); - }; - + ConsoleLogger::logLine("TestFramework: Running Test - %s", test_case->getName().raw()); + test_case->run(); + if (sLastTestFailed) { - std::cout << "Failed at line: " << sFailureLine << std::endl; + ConsoleLogger::logLine("Failed at line %s", sFailureLine.raw()); mFailingTests.push_back(test_case->getName()); } } if (mFailingTests.size() > 0) { - std::cout << mFailingTests.size() << " failing tests: " << std::endl; + ConsoleLogger::logLine("%d failing tests", mFailingTests.size()); for(const auto& name : mFailingTests) { - std::cout << name << std::endl; + ConsoleLogger::logLine(name); } } diff --git a/test/test_utils/TestCaseRunner.h b/test/test_utils/TestCaseRunner.h index e44b20e..9b7135b 100644 --- a/test/test_utils/TestCaseRunner.h +++ b/test/test_utils/TestCaseRunner.h @@ -2,8 +2,8 @@ #include "TestCase.h" -#include -#include +#include "Vector.h" +#include "String.h" class TestUiApplication; @@ -16,20 +16,20 @@ public: ~TestCaseRunner(); - TestUiApplication* getTestApplication(); + //TestUiApplication* getTestApplication(); - void addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func); + void addTestCase(const String& label, const String& tag, TestCase::TestCaseFunction func); - void markTestFailure(const std::string& line); + void markTestFailure(const String& line); - bool run(const std::vector& args); + bool run(const Vector& args); - void setTestApplication(TestUiApplication* app); + //void setTestApplication(TestUiApplication* app); private: - TestUiApplication* mTestApplication{ nullptr }; - std::vector mFailingTests; + //TestUiApplication* mTestApplication{ nullptr }; + Vector mFailingTests; static bool sLastTestFailed; - static std::string sFailureLine; - std::vector mCases; + static String sFailureLine; + Vector mCases; }; diff --git a/test/test_utils/TestFramework.h b/test/test_utils/TestFramework.h index 7e86d06..68755ad 100644 --- a/test/test_utils/TestFramework.h +++ b/test/test_utils/TestFramework.h @@ -4,7 +4,7 @@ struct Holder { - Holder(const std::string& name, const std::string& tags, std::function func) + Holder(const String& name, const String& tags, std::function func) { TestCaseRunner::getInstance().addTestCase(name, tags, func); } @@ -19,8 +19,8 @@ struct Holder #define REQUIRE(predicate) \ if(!bool(predicate)) \ { \ - TestCaseRunner::getInstance().markTestFailure(std::to_string(__LINE__) + " with check: '" + std::string(#predicate) + "'"); \ - return; \ + const auto msg = String::to_string(__LINE__) + String(" with check: '") + String(#predicate) + String("'"); \ + TestCaseRunner::getInstance().markTestFailure(msg); \ } \ diff --git a/test/test_utils/TestUtils.h b/test/test_utils/TestUtils.h index 43e0ab8..d1d892d 100644 --- a/test/test_utils/TestUtils.h +++ b/test/test_utils/TestUtils.h @@ -1,6 +1,6 @@ #pragma once -#include "TestDataLocations.h" +//#include "TestDataLocations.h" #include diff --git a/test/windows/TestWaylandWindow.cpp b/test/windows/TestWaylandWindow.cpp index 861b1de..ac71c0a 100644 --- a/test/windows/TestWaylandWindow.cpp +++ b/test/windows/TestWaylandWindow.cpp @@ -16,5 +16,5 @@ TEST_CASE(TestWaylandWindow, "web") //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND); app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER); - app->run(); + //app->run(); }