Initial test bootstrap.

This commit is contained in:
jmsgrogan 2023-12-18 10:16:31 +00:00
parent 6c618749f1
commit 4b308f6c32
94 changed files with 2543 additions and 681 deletions

View file

@ -12,7 +12,7 @@ int main(int argc, char *argv[])
// Start the gui app // Start the gui app
auto app = NotesTk(std::move(args)); auto app = NotesTk(std::move(args));
//app.setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); app.setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER);
app.run(); app.run();
return 0; return 0;

20
bootstrap.sh Executable file
View file

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

View file

@ -0,0 +1,78 @@
#include "KScope.h"
#include <stdio.h>
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<Token> 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<Token>& 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();
}

View file

@ -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<Token>& tokens);
Token m_working_token;
};

View file

@ -33,8 +33,8 @@ public:
bool hitBufferFull() const; bool hitBufferFull() const;
private: private:
bool lookAheadSourceEmpty() const; bool lookAheadSourceEmpty() const;
unsigned char getSearchBufferItem(unsigned index) const; unsigned char getSearchBufferItem(unsigned index) const;
unsigned lookAheadForMatchingChars(unsigned searchIndex); unsigned lookAheadForMatchingChars(unsigned searchIndex);

View file

@ -40,8 +40,11 @@ list(APPEND SOURCES
Dictionary.cpp Dictionary.cpp
Color.cpp Color.cpp
CommandLineArgs.cpp CommandLineArgs.cpp
memory/Allocator.cpp
data_structures/RawTree.cpp data_structures/RawTree.cpp
data_structures/Tree.cpp data_structures/Tree.cpp
data_structures/Vector.cpp
data_structures/String.cpp
loggers/FileLogger.cpp loggers/FileLogger.cpp
file_utilities/Directory.cpp file_utilities/Directory.cpp
file_utilities/File.cpp file_utilities/File.cpp
@ -81,6 +84,7 @@ target_include_directories(${MODULE_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/memory ${CMAKE_CURRENT_SOURCE_DIR}/memory
${CMAKE_CURRENT_SOURCE_DIR}/streams ${CMAKE_CURRENT_SOURCE_DIR}/streams
${CMAKE_CURRENT_SOURCE_DIR}/http ${CMAKE_CURRENT_SOURCE_DIR}/http
${CMAKE_CURRENT_SOURCE_DIR}/base_types
${CMAKE_CURRENT_SOURCE_DIR}/data_structures ${CMAKE_CURRENT_SOURCE_DIR}/data_structures
${CMAKE_CURRENT_SOURCE_DIR}/serializers ${CMAKE_CURRENT_SOURCE_DIR}/serializers
${CMAKE_CURRENT_SOURCE_DIR}/xml ${CMAKE_CURRENT_SOURCE_DIR}/xml

View file

@ -34,6 +34,77 @@ std::unique_ptr<Color> Color::Create(unsigned char r, unsigned char g, unsigned
return std::make_unique<Color>(r, g, b, a); return std::make_unique<Color>(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<double>(alpha);
}
std::unique_ptr<Color> Color::Create(const Color& color) std::unique_ptr<Color> Color::Create(const Color& color)
{ {
return std::make_unique<Color>(color); return std::make_unique<Color>(color);

View file

@ -3,10 +3,20 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <string> #include <string>
#include <stdexcept>
class Color class Color
{ {
public: public:
enum class Format
{
GRAYSCALE,
GRAYSCALE_ALPHA,
LUT,
RGB,
ARGB,
RGBA
};
Color(const std::string& hexString); Color(const std::string& hexString);
Color(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, double a = 1.0); 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; std::string toString() const;
void setAlpha(float alpha) std::size_t getSize() const;
{
mAlpha = static_cast<double>(alpha); 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 bool operator==(const Color& rhs) const
{ {
@ -49,7 +64,10 @@ private:
unsigned char mR{0}; unsigned char mR{0};
unsigned char mG{0}; unsigned char mG{0};
unsigned char mB{0}; unsigned char mB{0};
unsigned char mValue{0};
double mAlpha{0.0}; double mAlpha{0.0};
unsigned mBitDepth{8};
Format mFormat{Format::RGBA};
}; };
using ColorPtr = std::shared_ptr<Color>; using ColorPtr = std::shared_ptr<Color>;

View file

@ -34,37 +34,37 @@ void CommandLineArgs::initialize(CommandLineArgs* args)
#endif #endif
} }
std::unique_ptr<CommandLineArgs> CommandLineArgs::Create() Ptr<CommandLineArgs> CommandLineArgs::Create()
{ {
return std::make_unique<CommandLineArgs>(); return Ptr<CommandLineArgs>::create();
} }
std::filesystem::path CommandLineArgs::getLaunchPath() FileSystemPath CommandLineArgs::getLaunchPath()
{ {
return mLaunchPath; return mLaunchPath;
} }
void CommandLineArgs::recordLaunchPath() void CommandLineArgs::recordLaunchPath()
{ {
mLaunchPath = std::filesystem::current_path(); mLaunchPath = FileSystemPath::current_dir();
} }
void CommandLineArgs::process(int argc, char *argv[]) void CommandLineArgs::process(int argc, char *argv[])
{ {
for(int idx=0; idx<argc; idx++) for(int idx=0; idx<argc; idx++)
{ {
mArugments.push_back(std::string(argv[idx])); mArugments.push_back(String(argv[idx]));
} }
} }
void CommandLineArgs::process(const std::vector<std::string>& args) void CommandLineArgs::process(const Vector<String>& args)
{ {
mArugments = args; mArugments = args;
} }
std::vector<std::string> CommandLineArgs::getUserArgs() const Vector<String> CommandLineArgs::getUserArgs() const
{ {
std::vector<std::string> user_args; Vector<String> user_args;
for(unsigned idx=1; idx<mArugments.size(); idx++) for(unsigned idx=1; idx<mArugments.size(); idx++)
{ {
user_args.push_back(mArugments[idx]); user_args.push_back(mArugments[idx]);
@ -72,7 +72,7 @@ std::vector<std::string> CommandLineArgs::getUserArgs() const
return user_args; return user_args;
} }
const std::vector<std::string> CommandLineArgs::getArgs() const const Vector<String> CommandLineArgs::getArgs() const
{ {
return mArugments; return mArugments;
} }

View file

@ -1,33 +1,31 @@
#pragma once #pragma once
#include <memory> #include "Pointer.h"
#include <vector> #include "Vector.h"
#include <string> #include "String.h"
#include <filesystem> #include "FileSystemPath.h"
class CommandLineArgs class CommandLineArgs
{ {
public: public:
CommandLineArgs(); CommandLineArgs();
static std::unique_ptr<CommandLineArgs> Create(); static Ptr<CommandLineArgs> Create();
std::filesystem::path getLaunchPath(); FileSystemPath getLaunchPath();
const std::vector<std::string> getArgs() const; const Vector<String> getArgs() const;
std::vector<std::string> getUserArgs() const; Vector<String> getUserArgs() const;
static void initialize(CommandLineArgs* args); static void initialize(CommandLineArgs* args);
void process(int argc, char *argv[]); void process(int argc, char *argv[]);
void process(const std::vector<std::string>& args); void process(const Vector<String>& args);
void recordLaunchPath(); void recordLaunchPath();
private: private:
std::vector<std::string> mArugments; Vector<String> mArugments;
std::filesystem::path mLaunchPath; FileSystemPath mLaunchPath;
}; };
using CommandLineArgsUPtr = std::unique_ptr<CommandLineArgs>;

View file

@ -0,0 +1,11 @@
#pragma once
#include <cstdint>
class Serializeable
{
public:
virtual std::size_t getSize() const = 0;
virtual uint8_t getByte(std::size_t index) const = 0;
};

View file

@ -0,0 +1,12 @@
#pragma once
#include "Vector.h"
#include <cstdint>
using Byte = uint8_t;
using VecBytes = Vector<Byte>;
using Word = uint16_t;
using DWord = uint32_t;
using QWord = uint64_t;

View file

@ -0,0 +1,11 @@
#include "Error.h"
Error::Error(const String& msg)
: m_message(msg)
{
}
const String& Error::msg() const
{
return m_message;
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -0,0 +1,19 @@
#pragma once
#include <cstdlib>
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};
};

View file

@ -0,0 +1,41 @@
#pragma once
#include "Error.h"
template<typename T>
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};
};

0
src/base/core/build.toml Normal file
View file

View file

@ -1,8 +1,6 @@
#pragma once #pragma once
#include <vector> #include "Vector.h"
#include <iostream>
template<typename T> template<typename T>
class CircleBuffer class CircleBuffer
@ -60,5 +58,5 @@ public:
private: private:
std::size_t mStartPointer{0}; std::size_t mStartPointer{0};
std::size_t mEndPointer{0}; std::size_t mEndPointer{0};
std::vector<T> mData; Vector<T> mData;
}; };

View file

@ -1,8 +1,7 @@
#pragma once #pragma once
#include <vector> #include "Error.h"
#include <string> #include "Vector.h"
#include <stdexcept>
class AbstractList class AbstractList
{ {
@ -20,7 +19,7 @@ public:
void initializeTo(std::size_t size, T value) void initializeTo(std::size_t size, T value)
{ {
mData = std::vector<T>(size, value); mData = Vector<T>(size, value);
} }
const T* getDataPtr() const const T* getDataPtr() const
@ -28,7 +27,7 @@ public:
return mData.data(); return mData.data();
} }
const std::vector<T>& getData() const const Vector<T>& getData() const
{ {
return mData; return mData;
} }
@ -46,7 +45,7 @@ public:
} }
} }
void setData(const std::vector<T>& data) void setData(const Vector<T>& data)
{ {
mData = data; mData = data;
} }
@ -65,5 +64,5 @@ public:
} }
private: private:
std::vector<T> mData; Vector<T> mData;
}; };

View file

@ -0,0 +1,6 @@
#pragma once
template<typename T, typename U>
class Map{
};

View file

@ -0,0 +1,29 @@
#pragma once
template<typename T>
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;
};

View file

@ -0,0 +1,27 @@
#pragma once
template<typename T, typename U>
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;
};

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <memory>
template<typename T> template<typename T>
class RawNode class RawNode
{ {

View file

@ -0,0 +1,232 @@
#include "String.h"
#include <stdio.h>
String::String()
{
m_data.push_back('\0');
}
String::String(const Vector<Byte>& 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<char>& String::data() const
{
return m_data;
}
bool String::empty() const
{
return m_data.empty() || m_data[0] == '\0';
}
void String::append(const Vector<Byte>& 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<char>(c));
}
}
m_data.push_back('\0');
}
Pair<String, String> 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<char>(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<unsigned>(log10(double(idx))) + 1;
char body[num_digits+1];
snprintf(body, num_digits+1, "%d", static_cast<int>(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;
}

View file

@ -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<Byte>& data);
String(const char* data);
const Vector<char>& data() const;
bool empty() const;
const char* raw() const;
Pair<String, String> 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<Byte>& data);
void append(const char* data);
Vector<char> m_data;
};

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <memory> #include "Pointer.h"
template<typename T> template<typename T>
class Node class Node
@ -10,7 +10,7 @@ public:
: mData(data) : mData(data)
{} {}
void addChild(std::unique_ptr<Node> child) void addChild(Ptr<Node> child)
{ {
if(!mLeftChild) if(!mLeftChild)
{ {
@ -45,12 +45,12 @@ public:
private: private:
T mData; T mData;
unsigned char mTag{0}; unsigned char mTag{0};
std::unique_ptr<Node> mLeftChild; Ptr<Node> mLeftChild;
std::unique_ptr<Node> mRightChild; Ptr<Node> mRightChild;
}; };
template<typename T> template<typename T>
using NodePtr = std::unique_ptr<Node<T> >; using NodePtr = Ptr<Node<T> >;
template<typename T> template<typename T>
class Tree class Tree

View file

View file

@ -0,0 +1,233 @@
#pragma once
#include "Allocator.h"
#include <stdio.h>
template<typename T>
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<slice_idx;idx++)
{
v.m_data[idx] = m_data[idx];
}
v.m_size = slice_idx;
return true;
}
bool slice(std::size_t slice_start, std::size_t slice_end, Vector& v) const
{
if (slice_end >= m_size)
{
return false;
}
v.resize(slice_end - slice_start);
for(std::size_t idx=slice_start; idx<slice_end;idx++)
{
v.m_data[idx] = m_data[idx];
}
v.m_size = slice_end;
return true;
}
std::size_t size() const
{
return m_size;
}
std::size_t capacity() const
{
return m_capacity;
}
bool empty() const
{
return m_size == 0;
}
void clear()
{
if (has_allocated())
{
m_allocator.delete_array(m_data);
m_data = nullptr;
m_capacity = 0;
m_size = 0;
}
}
void resize(std::size_t size)
{
resize_capacity(size);
}
void resize(std::size_t size, const T& value)
{
resize_capacity(size);
fill_with(value);
}
void extend(const Vector& other)
{
resize(m_size + other.m_size);
for(std::size_t idx=0;idx<other.m_size;idx++)
{
m_data[idx + m_size] = other[idx];
}
m_size = m_size + other.m_size;
}
T pop_back()
{
const auto last = m_data[size() - 1];
m_data[size() - 1] = T();
m_size--;
return last;
}
void push_back(const T& item)
{
if (!has_allocated())
{
resize_capacity(10);
}
else if (m_size >= 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<T>& operator=(const Vector<T>& v)
{
resize(v.size());
for(std::size_t idx=0; idx<v.size(); idx++)
{
m_data[idx] = v.m_data[idx];
}
m_size = v.size();
return *this;
}
bool operator ==(const Vector<T>& other) const
{
if (m_size != other.m_size)
{
return false;
}
for(std::size_t idx=0; idx<m_size; idx++)
{
if (m_data[idx] != other[idx])
{
return false;
}
}
return true;
}
private:
void fill_with(const T& value)
{
for(std::size_t idx = 0; idx<m_size; idx++)
{
m_data[idx] = value;
}
}
bool has_allocated() const
{
return m_capacity > 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<new_capacity; idx++)
{
temp[idx] = m_data[idx];
}
auto old_size = m_size;
clear();
m_data = temp;
m_capacity = new_capacity;
m_size = old_size;
if (old_size > m_capacity)
{
m_size = m_capacity;
}
}
else if(m_size != m_capacity)
{
m_size = m_capacity;
}
}
T* m_data{nullptr};
Allocator<T> m_allocator;
std::size_t m_size{0};
std::size_t m_capacity{0};
};

View file

@ -1,44 +1,40 @@
#pragma once #pragma once
#include "ByteTypes.h"
#include "String.h"
#include <cstring> #include <cstring>
#include <stdint.h>
#include <string>
class ByteUtils class ByteUtils
{ {
public: public:
using Word = int16_t; static bool MostSignificantBitIsOne(Byte c);
using DWord = int32_t;
using QWord = int64_t;
static bool MostSignificantBitIsOne(char c);
static Word GetWordFirstBit(const Word word); static Word GetWordFirstBit(const Word word);
static Word GetWordLastByte(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<typename T> template<typename T>
static T ToType(char* buffer, bool reverse = true) static T ToType(Byte* buffer, bool reverse = true)
{ {
T result {0}; T result {0};
if(reverse) if(reverse)
@ -54,17 +50,17 @@ public:
return result; 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 int BYTE_FIRST_BIT = 0x40; // 1000 0000
static const Word WORD_FIRST_BIT = static_cast<Word>(0x8000); // 1000 0000 - 0000 0000 static const Word WORD_FIRST_BIT = static_cast<Word>(0x8000); // 1000 0000 - 0000 0000

View file

@ -0,0 +1,35 @@
#include "CharUtils.h"
bool CharUtils::is_alpha_upper(char c)
{
const auto unsigned_c = static_cast<unsigned char>(c);
return unsigned_c >= 65 && unsigned_c <= 90;
}
bool CharUtils::is_alpha_lower(char c)
{
const auto unsigned_c = static_cast<unsigned char>(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<unsigned char>(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';
}

View file

@ -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);
};

View file

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "ByteTypes.h"
#include <string> #include <string>
#include <vector> #include <vector>

View file

@ -1,30 +1,84 @@
#include "Directory.h" #include "Directory.h"
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
std::vector<Path> Directory::getFilesWithExtension(const Path& path, const std::string& extension, bool recursive) Vector<FileSystemPath> Directory::getSubdirectories(const FileSystemPath& path)
{ {
std::vector<Path> paths; Vector<FileSystemPath> ret;
if (std::filesystem::is_directory(path)) 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;
{
paths.push_back(entry.path());
} }
else if(recursive && std::filesystem::is_directory(entry))
auto full_path = path.join(rel_path);
struct stat sb;
auto rc = lstat(full_path.as_string().raw(), &sb);
if (rc == -1)
{ {
const auto child_paths = getFilesWithExtension(entry, extension, recursive); printf("Got error");
paths.insert(paths.end(), child_paths.begin(), child_paths.end()); }
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<FileSystemPath> Directory::getFiles(const FileSystemPath& path, bool recursive)
{
Vector<FileSystemPath> paths;
if (path.is_directory())
{
for (const auto& entry : getSubdirectories(path))
{
if (entry.is_regular_file())
{
paths.push_back(entry);
}
else if(recursive && entry.is_directory())
{
const auto child_paths = getFiles(entry, recursive);
paths.extend(child_paths);
} }
} }
} }
return paths; return paths;
} }
void Directory::createIfNotExisting(const Path& path) Vector<FileSystemPath> Directory::getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive)
{ {
Path working_path; Vector<FileSystemPath> paths;
if (std::filesystem::is_directory(path)) 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; working_path = path;
} }
@ -33,8 +87,8 @@ void Directory::createIfNotExisting(const Path& path)
working_path = path.parent_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);
} }
} }

View file

@ -1,14 +1,16 @@
#pragma once #pragma once
#include <vector> #include "Vector.h"
#include <filesystem> #include "FileSystemPath.h"
using Path = std::filesystem::path;
class Directory class Directory
{ {
public: public:
static void createIfNotExisting(const Path& path); static Vector<FileSystemPath> getSubdirectories(const FileSystemPath& path);
static std::vector<Path> getFilesWithExtension(const Path& path, const std::string& extension, bool recursive=false); static void create(const FileSystemPath& path, bool existsOK = false);
static Vector<FileSystemPath> getFiles(const FileSystemPath& path, bool recursive=false);
static Vector<FileSystemPath> getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive=false);
}; };

View file

@ -1,17 +1,116 @@
#include "File.h" #include "File.h"
#include "FileLogger.h" //#include "FileLogger.h"
#include "ByteUtils.h" #include "ByteUtils.h"
#include "Directory.h"
#include "Result.h"
#include <streambuf> #include <fcntl.h>
#include <sstream> #include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
File::File(std::filesystem::path path) class FileImpl
: mFullPath(path),
mInHandle(),
mOutHandle()
{ {
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<std::size_t> 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<std::size_t>(Error(msg));
}
return Result<std::size_t>(rc);
}
std::size_t do_write(const VecBytes& bytes)
{
return ::write(m_fd, bytes.data(), bytes.size());
}
std::size_t do_write(const Vector<char>& 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<FileImpl>::create()),
m_path(path)
{
} }
File::~File() File::~File()
@ -19,145 +118,149 @@ File::~File()
close(); 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); open(AccessMode::Read);
std::stringstream sstr; String sstr;
sstr << "Count | Binary | Decimal | ASCII \n"; sstr << "Count | Binary | Decimal | Hex | ASCII \n";
VecBytes buffer;
readBinary(buffer);
unsigned count = 0; unsigned count = 0;
while(mInHandle->peek() != EOF) /*
for(const auto byte : buffer)
{ {
const unsigned char val = static_cast<unsigned char>(mInHandle->get()); const auto ascii_val = std::isalpha(byte) ? byte : '.';
const unsigned char ascii_val = std::isalpha(val) ? val : '.'; String hex_sstr;
sstr << count << " | " << ByteUtils::toString(val) << " | " << static_cast<int>(val) << " | " << ascii_val << '\n'; hex_sstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(byte);
sstr << count << " | " << ByteUtils::toString(byte) << " | " << static_cast<int>(byte) << " | " << hex_sstr.str() << " | " << ascii_val << '\n';
if (count % 10 == 0) if (count % 10 == 0)
{ {
sstr << "\n"; sstr << "\n";
} }
count++; count++;
} }
const auto out = sstr.str(); */
close(); close();
return out; return sstr;
} }
std::ifstream* File::getInHandle() const Optional<Byte> File::readNextByte()
{
return mInHandle.get();
}
std::ofstream* File::getOutHandle() const
{
return mOutHandle.get();
}
std::optional<unsigned char> 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 else
{ {
return val; return buffer[0];
} }
} }
else 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) m_impl->do_open(m_path, accessMode);
{
auto flags = std::ifstream::in;
mInHandle = std::make_unique<std::ifstream>();
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<std::ofstream>();
mOutHandle->open(mFullPath, flags);
if (!mOutHandle->is_open())
{
MLOG_ERROR("Failed to open file at :" << mFullPath);
return false;
}
}
return true; return true;
} }
void File::close() void File::close()
{ {
if(mOutHandle) m_impl->do_close();
{
mOutHandle->close();
}
if(mInHandle)
{
mInHandle->close();
}
} }
FileFormat::Format File::inferFormat() const FileFormat::Format File::inferFormat() const
{ {
const auto extension = getExtension(); //const auto extension = getExtension();
return FileFormat::inferFormat(extension); //return FileFormat::inferFormat(extension);
return {};
} }
void File::writeText(const std::string& text) void File::writeText(const String& text)
{ {
bool had_to_open{false}; bool had_to_open{false};
if (!mOutHandle) if (!m_impl->is_open_for_write())
{ {
had_to_open = true; had_to_open = true;
if (!open(File::AccessMode::Write)) m_impl->do_open(m_path, File::AccessMode::Write);
{
return;
}
} }
(*mOutHandle) << text; m_impl->do_write(text.data(), text.data().size() - 1);
if (had_to_open) if (had_to_open)
{ {
close(); m_impl->do_close();
} }
} }
std::vector<std::string> File::readLines() Vector<String> File::readLines()
{ {
std::vector<std::string> content; Vector<String> content;
/*
if (!pathExists()) if (!pathExists())
{ {
return {}; return {};
@ -168,18 +271,20 @@ std::vector<std::string> File::readLines()
return {}; return {};
} }
std::string str; String str;
while(std::getline(*mInHandle, str)) while(std::getline(*mInHandle, str))
{ {
content.push_back(str); content.push_back(str);
} }
close(); close();
*/
return content; return content;
} }
std::string File::read() String File::read()
{ {
/*
if (!pathExists()) if (!pathExists())
{ {
return {}; return {};
@ -190,31 +295,16 @@ std::string File::read()
return {}; return {};
} }
std::stringstream buffer; String buffer;
buffer << mInHandle->rdbuf(); buffer << mInHandle->rdbuf();
close(); close();
return buffer.str(); */
} String buffer;
return buffer;
std::string File::readText()
{
if (!pathExists())
{
return {};
}
if(!open(AccessMode::Read))
{
return {};
}
std::string str((std::istreambuf_iterator<char>(*mInHandle)),
std::istreambuf_iterator<char>());
return str;
} }
bool File::pathExists() const bool File::pathExists() const
{ {
return std::filesystem::exists(mFullPath); return m_path.exists();
} }

View file

@ -1,57 +1,53 @@
#pragma once #pragma once
#include "FileFormats.h" #include "FileFormats.h"
#include "FileSystemPath.h"
#include "Optional.h"
#include "String.h"
#include "ByteTypes.h"
#include "Pointer.h"
#include <filesystem> class FileImpl;
#include <string>
#include <fstream>
#include <memory>
#include <vector>
#include <optional>
using Path = std::filesystem::path;
class File class File
{ {
public: public:
enum class AccessMode{ enum class AccessMode{
Read, Read,
Write Write,
ReadWrite
}; };
public: public:
File(std::filesystem::path fullPath); File(const FileSystemPath& path);
~File(); ~File();
void close(); void close();
std::string dumpBinary(); String dumpBinary();
std::string getExtension() const; String getExtension() const;
std::ifstream* getInHandle() const;
std::ofstream* getOutHandle() const;
FileFormat::Format inferFormat() const; FileFormat::Format inferFormat() const;
std::string readText(); String readText();
std::vector<std::string> readLines(); Vector<String> readLines();
std::string read(); String read();
bool pathExists() const; bool pathExists() const;
bool open(AccessMode mode); bool open(AccessMode mode, bool binary = false);
std::optional<unsigned char> readNextByte(); bool readBinary(VecBytes& bytes);
void writeText(const std::string& text); Optional<Byte> readNextByte();
void writeText(const String& text);
private: private:
std::filesystem::path mFullPath; Ptr<FileImpl> m_impl;
std::unique_ptr<std::ifstream> mInHandle; FileSystemPath m_path;
std::unique_ptr<std::ofstream> mOutHandle;
}; };

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <map> #include "Map.h"
#include <string> #include "String.h"
class FileFormat{ class FileFormat{
@ -24,13 +24,13 @@ public:
Unknown Unknown
}; };
using ExtensionMap = std::map<Format, std::string>; using ExtensionMap = Map<Format, String>;
public: 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: private:
static ExtensionMap mExtensions; static ExtensionMap mExtensions;

View file

@ -0,0 +1,114 @@
#include "FileSystemPath.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
FileSystemPath::FileSystemPath(const String& path)
: m_path(path)
{
}
const String& FileSystemPath::as_string() const
{
return m_path;
}
Result<bool> 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<size_t> 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<char> 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;
}

View file

@ -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<bool> is_empty() const;
Result<size_t> 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;
};

View file

@ -0,0 +1,17 @@
#include "ConsoleLogger.h"
#include <stdio.h>
#include <stdarg.h>
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);
}

View file

@ -0,0 +1,11 @@
#pragma once
#include "String.h"
class ConsoleLogger
{
public:
static void logLine(const String& msg);
static void logLine(const char* fmt, ...);
};

View file

@ -1,9 +1,20 @@
#include "FileLogger.h" #include "FileLogger.h"
#include <time.h> #include <time.h>
#include <iomanip>
#include <iostream> FileLogger::FileLogger()
#include <filesystem> :mWorkDirectory(),
mFileName("MT_Log.txt")
{
}
FileLogger& FileLogger::GetInstance()
{
static FileLogger instance;
return instance;
}
FileLogger::~FileLogger() FileLogger::~FileLogger()
{ {

View file

@ -1,33 +1,21 @@
#pragma once #pragma once
#define MLOG_ALL(msg, level) {std::ostringstream mt_logstream;\ #define MLOG_ALL(msg, level) {String mt_logstream;\
mt_logstream << msg; \ mt_logstream << msg; \
FileLogger::GetInstance().LogLine(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);}; FileLogger::GetInstance().LogLine(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);};
#define MLOG_INFO(msg) MLOG_ALL(msg, "Info"); #define MLOG_INFO(msg) MLOG_ALL(msg, "Info");
#define MLOG_ERROR(msg) MLOG_ALL(msg, "Error"); #define MLOG_ERROR(msg) MLOG_ALL(msg, "Error");
#include <memory> #include "Pointer.h"
#include <string> #include "String.h"
#include <fstream>
#include <sstream>
class FileLogger class FileLogger
{ {
FileLogger() FileLogger();
:mWorkDirectory(),
mFileName("MT_Log.txt"),
mFileStream()
{
}
public: public:
static FileLogger& GetInstance() static FileLogger& GetInstance();
{
static FileLogger instance;
return instance;
}
FileLogger(FileLogger const&) = delete; FileLogger(FileLogger const&) = delete;
void operator=(FileLogger const&) = delete; void operator=(FileLogger const&) = delete;
@ -36,22 +24,19 @@ public:
void disable(); 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 Open();
void Close(); 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: private:
bool mDisabled{false}; bool mDisabled{false};
std::string mWorkDirectory; String mWorkDirectory;
std::string mFileName; String mFileName;
std::ofstream mFileStream;
}; };
using FileLoggerPtr = std::shared_ptr<FileLogger>;

View file

View file

@ -0,0 +1,29 @@
#pragma once
//#include <cstddef>
#include <stdlib.h>
template<typename T>
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;
}
};

View file

@ -0,0 +1,61 @@
#pragma once
#include "Allocator.h"
#include <utility>
template<typename T>
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<T> m_allocator;
T* m_raw{nullptr};
};

View file

@ -2,15 +2,12 @@
#include "ByteUtils.h" #include "ByteUtils.h"
#include <sstream>
#include <iostream>
BitStream::~BitStream() BitStream::~BitStream()
{ {
} }
unsigned char BitStream::getCurrentByte() Byte BitStream::getCurrentByte()
{ {
if (mByteOffset < 0) if (mByteOffset < 0)
{ {
@ -19,19 +16,18 @@ unsigned char BitStream::getCurrentByte()
return mCurrentByte; return mCurrentByte;
} }
void BitStream::write(uint32_t data) void BitStream::write(DWord data)
{ {
unsigned num_bytes = sizeof(uint32_t); for(std::size_t idx=0; idx<sizeof(DWord); idx++)
for(unsigned idx=0; idx<num_bytes;idx++)
{ {
writeByte(ByteUtils::getByteN(data, idx)); writeByte(ByteUtils::getByteN(data, idx));
} }
} }
void BitStream::writeWord(uint16_t data) void BitStream::writeWord(Word data)
{ {
const auto byte0 = static_cast<unsigned char>(data >> 8); const auto byte0 = static_cast<Byte>(data >> 8);
const auto byte1 = static_cast<unsigned char>((data << 8) >> 8); const auto byte1 = static_cast<Byte>((data << 8) >> 8);
writeByte(byte0); writeByte(byte0);
writeByte(byte1); writeByte(byte1);
} }
@ -41,24 +37,26 @@ int BitStream::getCurrentByteOffset() const
return mByteOffset; return mByteOffset;
} }
unsigned BitStream::getCurrentBitOffset() const std::size_t BitStream::getCurrentBitOffset() const
{ {
return mBitOffset; return mBitOffset;
} }
std::string BitStream::logLocation() String BitStream::logLocation()
{ {
std::stringstream sstr; String ret;
sstr << "Byte offset " << mByteOffset<< " | Bit offset " << mBitOffset; ret << "Byte offset " << mByteOffset<< " | Bit offset " << mBitOffset;
sstr << " | Working byte " << ByteUtils::toString(getCurrentByte()) << '\n'; ret << " | Working byte " << ByteUtils::toString(getCurrentByte()) << '\n';
return sstr.str(); return ret;
} }
std::string BitStream::logNextNBytes(unsigned n) const String BitStream::logNextNBytes(std::size_t n) const
{ {
std::stringstream sstr; std::stringstream sstr;
unsigned count{0}; std::size_t count{0};
for(auto byte : peekNextNBytes(n)) VecBytes bytes;
peekNextNBytes(n, bytes);
for(auto byte : bytes)
{ {
sstr << mByteOffset + count << " | " << ByteUtils::toString(byte) + '\n'; sstr << mByteOffset + count << " | " << ByteUtils::toString(byte) + '\n';
count++; count++;
@ -66,28 +64,28 @@ std::string BitStream::logNextNBytes(unsigned n) const
return sstr.str(); 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 auto num_left = 8 - mBitOffset;
const int overshoot = length - num_left; const int overshoot = length - num_left;
if (overshoot > 0) if (overshoot > 0)
{ {
unsigned char lower_bits = ByteUtils::getLowerNBits(data, num_left); Byte lower_bits = ByteUtils::getLowerNBits(data, num_left);
mCurrentByte |= lower_bits << mBitOffset; mCurrentByte |= lower_bits << mBitOffset;
writeByte(mCurrentByte, false); writeByte(mCurrentByte, false);
unsigned num_bytes = overshoot / 8; std::size_t num_bytes = overshoot / 8;
for (unsigned idx=0; idx< num_bytes; idx++) for (std::size_t idx=0; idx< num_bytes; idx++)
{ {
mCurrentByte = ByteUtils::getMBitsAtN(static_cast<unsigned char>(data), overshoot, idx*8 + num_left); mCurrentByte = ByteUtils::getMBitsAtN(static_cast<Byte>(data), overshoot, idx*8 + num_left);
writeByte(mCurrentByte, false); writeByte(mCurrentByte, false);
} }
if (const auto remainder = overshoot % 8; remainder > 0) if (const auto remainder = overshoot % 8; remainder > 0)
{ {
mCurrentByte = ByteUtils::getMBitsAtN(static_cast<unsigned char>(data), remainder, num_bytes*8 + num_left); mCurrentByte = ByteUtils::getMBitsAtN(static_cast<Byte>(data), remainder, num_bytes*8 + num_left);
mBitOffset = remainder; mBitOffset = remainder;
} }
else else
@ -98,7 +96,7 @@ void BitStream::writeNBits(uint32_t data, unsigned length)
} }
else else
{ {
mCurrentByte |= (static_cast<unsigned char>(data) << mBitOffset); mCurrentByte |= (static_cast<Byte>(data) << mBitOffset);
mBitOffset += length; mBitOffset += length;
if (mBitOffset == 8) if (mBitOffset == 8)
{ {
@ -107,10 +105,9 @@ void BitStream::writeNBits(uint32_t data, unsigned length)
mBitOffset = 0; mBitOffset = 0;
} }
} }
} }
bool BitStream::readNextNBits(unsigned n, unsigned char& buffer) bool BitStream::readNextNBits(std::size_t n, Byte& buffer)
{ {
if (mByteOffset < 0) if (mByteOffset < 0)
{ {
@ -123,15 +120,15 @@ bool BitStream::readNextNBits(unsigned n, unsigned char& buffer)
int overshoot = n + mBitOffset - 8; int overshoot = n + mBitOffset - 8;
if (overshoot > 0) if (overshoot > 0)
{ {
unsigned char last_byte = mCurrentByte; const auto last_byte = mCurrentByte;
if (!readNextByte()) if (!readNextByte())
{ {
return false; return false;
} }
auto num_lower = 8 - mBitOffset; auto num_lower = 8 - mBitOffset;
char lower_bits = ByteUtils::getHigherNBits(last_byte, num_lower); const auto lower_bits = ByteUtils::getHigherNBits(last_byte, num_lower);
char higher_bits = ByteUtils::getLowerNBits(mCurrentByte, overshoot); const auto higher_bits = ByteUtils::getLowerNBits(mCurrentByte, overshoot);
buffer = (higher_bits << num_lower) | lower_bits; buffer = (higher_bits << num_lower) | lower_bits;
@ -145,3 +142,44 @@ bool BitStream::readNextNBits(unsigned n, unsigned char& buffer)
return true; 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<Byte, std::size_t> BitStream::getRemainingBits() const
{
return {mEndByte, mEndBitOffset};
}
void BitStream::setChecksumCalculator(AbstractChecksumCalculator* calc)
{
mChecksumCalculator = calc;
}
void BitStream::clearChecksumCalculator()
{
mChecksumCalculator = nullptr;
}

View file

@ -1,92 +1,63 @@
#pragma once #pragma once
#include "AbstractChecksumCalculator.h" #include "AbstractChecksumCalculator.h"
#include "ByteTypes.h"
#include <vector> #include "String.h"
#include <string> #include "Optional.h"
#include <optional> #include "Pair.h"
class BitStream class BitStream
{ {
public: public:
virtual ~BitStream(); virtual ~BitStream();
unsigned char getCurrentByte(); Byte getCurrentByte();
int getCurrentByteOffset() const; int getCurrentByteOffset() const;
unsigned getCurrentBitOffset() const; std::size_t getCurrentBitOffset() const;
virtual bool isFinished() const = 0; 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<unsigned char> 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<unsigned char> readNextByte() = 0; virtual Optional<Byte> 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<unsigned char> data) = 0; virtual void writeBytes(const VecBytes& data) = 0;
void resetOffsets() void resetOffsets();
{
mEndByteOffset = mByteOffset;
mEndBitOffset = mBitOffset;
mEndByte = mCurrentByte;
mCurrentByte = 0; virtual void reset();
mByteOffset = -1;
mBitOffset = 0;
}
virtual void reset() void flushRemainingBits();
{
resetOffsets();
mCurrentByte = 0;
}
void flushRemainingBits() Pair<Byte, std::size_t> getRemainingBits() const;
{
if (mBitOffset > 0)
{
writeByte(mCurrentByte, false);
mBitOffset = 0;
}
}
std::pair<unsigned char, unsigned> getRemainingBits() const void setChecksumCalculator(AbstractChecksumCalculator* calc);
{
return {mEndByte, mEndBitOffset};
}
void setChecksumCalculator(AbstractChecksumCalculator* calc) void clearChecksumCalculator();
{
mChecksumCalculator = calc;
}
void clearChecksumCalculator()
{
mChecksumCalculator = nullptr;
}
protected: protected:
int mByteOffset{-1}; int mByteOffset{-1};
unsigned mBitOffset{0}; std::size_t mBitOffset{0};
unsigned char mCurrentByte{0}; Byte mCurrentByte{0};
int mEndByteOffset{-1}; int mEndByteOffset{-1};
unsigned mEndBitOffset{0}; std::size_t mEndBitOffset{0};
unsigned char mEndByte{0}; Byte mEndByte{0};
AbstractChecksumCalculator* mChecksumCalculator{nullptr}; AbstractChecksumCalculator* mChecksumCalculator{nullptr};
}; };

View file

@ -9,10 +9,10 @@ bool BufferBitStream::isFinished() const
return mByteOffset == static_cast<int>(mBuffer.size()) - 1; return mByteOffset == static_cast<int>(mBuffer.size()) - 1;
} }
std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const void BufferBitStream::peekNextNBytes(std::size_t n, VecBytes& ret) const
{ {
std::vector<unsigned char> ret (n, 0); ret.resize(n, 0);
unsigned count = 0; std::size_t count = 0;
int start = mByteOffset; int start = mByteOffset;
if (start<0) if (start<0)
@ -30,10 +30,9 @@ std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const
ret[count] = mBuffer[idx]; ret[count] = mBuffer[idx];
count++; count++;
} }
return ret;
} }
std::optional<unsigned char> BufferBitStream::readNextByte() std::optional<uint8_t> BufferBitStream::readNextByte()
{ {
if (mByteOffset + 1 == static_cast<int>(mBuffer.size())) if (mByteOffset + 1 == static_cast<int>(mBuffer.size()))
{ {
@ -47,14 +46,14 @@ std::optional<unsigned char> BufferBitStream::readNextByte()
} }
} }
void BufferBitStream::setBuffer(const std::vector<unsigned char>& data) void BufferBitStream::setBuffer(const VecBytes& data)
{ {
mBuffer = 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) if (checkOverflow && mBitOffset > 0)
{ {
out_byte = ByteUtils::getLowerNBits(mCurrentByte, mBitOffset); out_byte = ByteUtils::getLowerNBits(mCurrentByte, mBitOffset);
@ -76,12 +75,12 @@ void BufferBitStream::writeByte(unsigned char data, bool checkOverflow)
} }
void BufferBitStream::writeBytes(const std::vector<unsigned char> data) void BufferBitStream::writeBytes(const VecBytes& data)
{ {
std::copy(data.begin(), data.end(), std::back_inserter(mBuffer)); std::copy(data.begin(), data.end(), std::back_inserter(mBuffer));
} }
const std::vector<unsigned char>& BufferBitStream::getBuffer() const const VecBytes& BufferBitStream::getBuffer() const
{ {
return mBuffer; return mBuffer;
} }

View file

@ -2,28 +2,25 @@
#include "BitStream.h" #include "BitStream.h"
#include <vector>
#include <iterator>
class BufferBitStream : public BitStream class BufferBitStream : public BitStream
{ {
public: public:
const std::vector<unsigned char>& getBuffer() const; const VecBytes& getBuffer() const;
bool isFinished() const override; bool isFinished() const override;
std::vector<unsigned char> peekNextNBytes(unsigned n) const override; void peekNextNBytes(std::size_t n, VecBytes& bytes) const override;
std::optional<unsigned char> readNextByte() override; std::optional<uint8_t> readNextByte() override;
void reset() override; void reset() override;
void setBuffer(const std::vector<unsigned char>& 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<unsigned char> data) override; void writeBytes(const VecBytes& data) override;
private: private:
std::vector<unsigned char> mBuffer; VecBytes mBuffer;
}; };

View file

@ -12,16 +12,15 @@ bool InputBitStream::isFinished() const
return mStream->good(); return mStream->good();
} }
std::vector<unsigned char> InputBitStream::peekNextNBytes(unsigned) const void InputBitStream::peekNextNBytes(std::size_t, VecBytes&) const
{ {
return {};
} }
std::optional<unsigned char> InputBitStream::readNextByte() std::optional<Byte> InputBitStream::readNextByte()
{ {
if (mStream->good()) if (mStream->good())
{ {
return static_cast<unsigned char>(mStream->get()); return static_cast<Byte>(mStream->get());
} }
else else
{ {
@ -29,7 +28,7 @@ std::optional<unsigned char> InputBitStream::readNextByte()
} }
} }
void InputBitStream::writeByte(unsigned char, bool) void InputBitStream::writeByte(Byte, bool)
{ {
} }

View file

@ -10,13 +10,13 @@ class InputBitStream : public BitStream
bool isFinished() const override; bool isFinished() const override;
std::vector<unsigned char> peekNextNBytes(unsigned n) const override; void peekNextNBytes(std::size_t n, VecBytes& bytes) const override;
std::optional<unsigned char> readNextByte() override; std::optional<Byte> readNextByte() override;
void writeByte(unsigned char data, bool checkOverflow = true) override; void writeByte(Byte data, bool checkOverflow = true) override;
void writeBytes(const std::vector<unsigned char>) override void writeBytes(const VecBytes&) override
{ {
} }

View file

@ -12,22 +12,22 @@ bool OutputBitStream::isFinished() const
return true; return true;
} }
std::vector<unsigned char> OutputBitStream::peekNextNBytes(unsigned) const void OutputBitStream::peekNextNBytes(std::size_t, VecBytes&) const
{ {
return {};
} }
std::optional<unsigned char> OutputBitStream::readNextByte() std::optional<uint8_t> OutputBitStream::readNextByte()
{ {
return std::nullopt; return std::nullopt;
} }
void OutputBitStream::writeByte(unsigned char data, bool) void OutputBitStream::writeByte(uint8_t data, bool)
{ {
(*mStream) << data; (*mStream) << data;
} }
void OutputBitStream::writeBytes(const std::vector<unsigned char> data) void OutputBitStream::writeBytes(const VecBytes& data)
{ {
for(auto byte : data) for(auto byte : data)
{ {

View file

@ -11,13 +11,13 @@ public:
bool isFinished() const override; bool isFinished() const override;
std::vector<unsigned char> peekNextNBytes(unsigned n) const override; void peekNextNBytes(std::size_t n, VecBytes& bytes) const override;
std::optional<unsigned char> readNextByte() override; std::optional<Byte> readNextByte() override;
void writeByte(unsigned char data, bool checkOverflow = true) override; void writeByte(Byte data, bool checkOverflow = true) override;
void writeBytes(const std::vector<unsigned char> data) override; void writeBytes(const VecBytes& data) override;
private: private:
std::basic_ostream<char>* mStream{nullptr}; std::basic_ostream<char>* mStream{nullptr};

View file

@ -12,7 +12,7 @@ public:
this->mData->initializeTo(numPointsX * numPointsY * numPointsZ, T()); 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)); return this->mData->getItem(getOffset(idx, jdx, kdx));
} }
@ -37,3 +37,40 @@ public:
return this->mData->getLength(); return this->mData->getLength();
} }
}; };
template<typename T>
class SerializeableGrid : public Grid<T>
{
public:
SerializeableGrid(std::size_t itemSize, const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ = 1)
: Grid<T>(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};
};

View file

@ -5,6 +5,7 @@ list(APPEND HEADERS
BasicWebApp.h) BasicWebApp.h)
list(APPEND SOURCES list(APPEND SOURCES
TermInfo.cpp
BasicWebApp.cpp BasicWebApp.cpp
MainApplication.cpp) MainApplication.cpp)

111
src/console/TermInfo.cpp Normal file
View file

@ -0,0 +1,111 @@
#include "TermInfo.h"
#include <vector>
#include "File.h"
#include <stdexcept>
#include <iostream>
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<unsigned char> content;
file.readBinary(content);
short header_size = 12;
if (content.size() < static_cast<std::size_t>(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<std::size_t>(header_size + name_size);
if (content.size() < bool_offset)
{
std::cerr << "unexpected terminfo size" << std::endl;
}
std::vector<std::string> names;
std::string working_name;
for(std::size_t idx=header_size; idx<bool_offset; idx++)
{
const auto c = content[idx];
if (c == '|')
{
names.push_back(working_name);
//std::cout << "got name: " << working_name << std::endl;
}
else
{
working_name += c;
}
}
return true;
}
void TermInfo::load()
{
const auto term = std::getenv("TERM");
if (!term || std::string(term).empty())
{
throw std::runtime_error("TERM environment variable not set or empty - can't proceed.");
}
const auto terminfo = std::getenv("TERMINFO");
if (terminfo)
{
if (load_terminfo(terminfo, term))
{
return;
}
}
std::vector<std::string> 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;
}

17
src/console/TermInfo.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include <string>
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();
};

43
src/main.cpp Normal file
View file

@ -0,0 +1,43 @@
#include "Vector.h"
#include "String.h"
#include "FileSystemPath.h"
#include "Directory.h"
#include "File.h"
#include <stdio.h>
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;
}

View file

@ -4,6 +4,7 @@ set(platform_LIB_INCLUDES)
list(APPEND image_HEADERS list(APPEND image_HEADERS
Image.h Image.h
Pixel.h
IImageWriter.h IImageWriter.h
PlatformImage.h PlatformImage.h
PlatformImageWriter.h PlatformImageWriter.h
@ -14,6 +15,7 @@ list(APPEND image_HEADERS
list(APPEND image_LIB_INCLUDES list(APPEND image_LIB_INCLUDES
Image.cpp Image.cpp
Pixel.cpp
ImageBitStream.cpp ImageBitStream.cpp
PlatformImage.cpp PlatformImage.cpp
png/BasicPngWriter.cpp png/BasicPngWriter.cpp
@ -21,6 +23,7 @@ list(APPEND image_LIB_INCLUDES
png/PngReader.cpp png/PngReader.cpp
png/PngHeader.cpp png/PngHeader.cpp
png/PngInfo.cpp png/PngInfo.cpp
png/PngFilter.cpp
) )
if(WIN32) if(WIN32)

View file

@ -3,14 +3,16 @@
#include "Color.h" #include "Color.h"
#include "Grid.h" #include "Grid.h"
#include <cassert>
#ifdef _WIN32 #ifdef _WIN32
#include "Win32WicImage.h" #include "Win32WicImage.h"
#endif #endif
Image::Image(unsigned width, unsigned height, DataType dataType) Image::Image(unsigned width, unsigned height, Color::Format format)
: mWidth(width), : mWidth(width),
mHeight(height), mHeight(height),
mDataType(dataType) mFormat(format)
{ {
initialize(); initialize();
} }
@ -20,49 +22,37 @@ Image::~Image()
} }
std::unique_ptr<Image> Image::Create(unsigned width, unsigned height, DataType dataType) std::unique_ptr<Image> Image::Create(unsigned width, unsigned height, Color::Format format)
{ {
return std::make_unique<Image>(width, height, dataType); return std::make_unique<Image>(width, height, format);
} }
void Image::initialize() void Image::initialize()
{ {
Bounds bounds(0.0, mWidth, 0.0, mHeight); Bounds bounds(0.0, mWidth, 0.0, mHeight);
if (mDataType == DataType::UCHAR) const auto pixel_size = Color::getSize(mFormat, mBitDepth);
{ mGrid = std::make_unique<SerializeableGrid<Pixel> >(pixel_size, bounds, mWidth, mHeight);
mData = std::make_unique<Grid<unsigned char> >(bounds, mWidth, mHeight, mNumChannels);
}
else
{
mData = std::make_unique<Grid<uint8_t> >(bounds, mWidth, mHeight, mNumChannels);
}
} }
void Image::setPixelValues(const Indices& indices, const std::vector<Color>& colors) void Image::setPixelValues(const Indices& indices, const std::vector<Color>& colors)
{ {
if (!mData) if (!mGrid)
{ {
initialize(); initialize();
} }
if (mDataType == DataType::UCHAR) assert(indices.size() == colors.size());
{
auto grid = getGridT<unsigned char>();
for (std::size_t idx=0; idx< indices.size(); idx++) for (std::size_t idx=0; idx< indices.size(); idx++)
{ {
auto id = indices[idx]; const auto id = indices[idx];
auto color = colors[idx]; mGrid->getItem(id.first, id.second).setColor(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());
}
} }
} }
unsigned Image::getBytesPerRow() const unsigned Image::getBytesPerRow() const
{ {
const auto bitsPerEntry = mBitDepth <= 8 ? 1 : 2; return mWidth * Color::getSize(mFormat, mBitDepth);
return mWidth * mNumChannels * bitsPerEntry;
} }
unsigned Image::getWidth() const unsigned Image::getWidth() const
@ -91,25 +81,29 @@ PlatformImage* Image::getPlatformImage()
return mPlatformImage.get(); return mPlatformImage.get();
} }
AbstractGrid* Image::getGrid() const SerializeableGrid<Pixel>* Image::getGrid() const
{ {
return mData.get(); return mGrid.get();
} }
template<typename T> uint8_t Image::getByte(std::size_t index) const
Grid<T>* Image::getGridT() const
{ {
return dynamic_cast<Grid<T>*>(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 unsigned Image::getNumChannels() const
{ {
return mNumChannels; return Color::getNumChannels(mFormat);
} }
void Image::setWidth(unsigned width) void Image::setWidth(unsigned width)
@ -127,8 +121,8 @@ void Image::setBitDepth(unsigned bitDepth)
mBitDepth = bitDepth; mBitDepth = bitDepth;
} }
void Image::setNumChannels(unsigned numChannels) void Image::setFormat(Color::Format format)
{ {
mNumChannels = numChannels; mFormat = format;
} }

View file

@ -1,30 +1,25 @@
#pragma once #pragma once
#include "PlatformImage.h" #include "PlatformImage.h"
#include "Pixel.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
class Color; class Color;
class AbstractGrid;
template<typename T> template<typename T>
class Grid; class SerializeableGrid;
class Image class Image
{ {
public: public:
enum class DataType
{
UCHAR
};
using Index = std::pair<std::size_t, std::size_t>; using Index = std::pair<std::size_t, std::size_t>;
using Indices = std::vector<Index>; using Indices = std::vector<Index>;
Image(unsigned width, unsigned height, DataType dataType = DataType::UCHAR); Image(unsigned width, unsigned height, Color::Format format = Color::Format::RGBA);
~Image(); ~Image();
static std::unique_ptr<Image> Create(unsigned width, unsigned height, DataType dataType = DataType::UCHAR); static std::unique_ptr<Image> Create(unsigned width, unsigned height, Color::Format format = Color::Format::RGBA);
unsigned getBytesPerRow() const; unsigned getBytesPerRow() const;
unsigned getWidth() const; unsigned getWidth() const;
@ -32,28 +27,27 @@ public:
unsigned getBitDepth() const; unsigned getBitDepth() const;
unsigned getNumChannels() const; unsigned getNumChannels() const;
AbstractGrid* getGrid() const; uint8_t getByte(std::size_t index) const;
SerializeableGrid<Pixel>* getGrid() const;
template<typename T> Color::Format getFormat() const;
Grid<T>* getGridT() const;
DataType getType() const;
PlatformImage* getPlatformImage(); PlatformImage* getPlatformImage();
void setPixelValues(const Indices& indices, const std::vector<Color>& colors); void setPixelValues(const Indices& indices, const std::vector<Color>& colors);
void setWidth(unsigned width); void setWidth(unsigned width);
void setHeight(unsigned height); void setHeight(unsigned height);
void setBitDepth(unsigned bitDepth); void setBitDepth(unsigned bitDepth);
void setNumChannels(unsigned numChannels); void setFormat(Color::Format format);
void toBuffer(uint8_t* buffer, std::size_t bufferMaxSize);
private: private:
void initialize(); void initialize();
unsigned mWidth{1}; unsigned mWidth{1};
unsigned mHeight{1}; unsigned mHeight{1};
unsigned mBitDepth{8}; unsigned mBitDepth{8};
unsigned mNumChannels{4}; Color::Format mFormat{Color::Format::RGBA};
DataType mDataType; std::unique_ptr<SerializeableGrid<Pixel> > mGrid;
std::unique_ptr<AbstractGrid> mData;
std::unique_ptr<PlatformImage> mPlatformImage; std::unique_ptr<PlatformImage> mPlatformImage;
}; };

View file

@ -1,6 +1,7 @@
#include "ImageBitStream.h" #include "ImageBitStream.h"
#include "AbstractGrid.h" #include "Grid.h"
#include "Pixel.h"
ImageBitStream::ImageBitStream(Image* image) ImageBitStream::ImageBitStream(Image* image)
: BitStream(), : BitStream(),
@ -14,25 +15,22 @@ bool ImageBitStream::isFinished() const
return mByteOffset == static_cast<int>(mImage->getGrid()->getDataSize()); return mByteOffset == static_cast<int>(mImage->getGrid()->getDataSize());
} }
std::vector<unsigned char> ImageBitStream::peekNextNBytes(unsigned) const std::vector<uint8_t> ImageBitStream::peekNextNBytes(std::size_t) const
{ {
return {}; return {};
} }
std::optional<unsigned char> ImageBitStream::readNextByte() std::optional<uint8_t> ImageBitStream::readNextByte()
{ {
mByteOffset++; mByteOffset++;
if (isFinished() ) if (isFinished() )
{ {
return std::nullopt; return std::nullopt;
} }
//const auto val = mImage->getData()->getAsUnsignedChar(mByteOffset); return mImage->getByte(mByteOffset);
//return val;
return {};
} }
void ImageBitStream::writeByte(unsigned char, bool ) void ImageBitStream::writeByte(uint8_t, bool )
{ {
mByteOffset++; mByteOffset++;

View file

@ -4,6 +4,8 @@
#include "Image.h" #include "Image.h"
#include <cstdint>
class ImageBitStream : public BitStream class ImageBitStream : public BitStream
{ {
public: public:
@ -11,13 +13,13 @@ public:
bool isFinished() const override; bool isFinished() const override;
std::vector<unsigned char> peekNextNBytes(unsigned n) const override; std::vector<uint8_t> peekNextNBytes(std::size_t n) const override;
std::optional<unsigned char> readNextByte() override; std::optional<uint8_t> 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<unsigned char>) override void writeBytes(const std::vector<uint8_t>&) override
{ {
} }

View file

26
src/media/image/Pixel.h Normal file
View file

@ -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;
};

View file

@ -88,13 +88,13 @@ void BasicPngWriter::writeHeader()
auto crc = mPngHeader.getCrc(); auto crc = mPngHeader.getCrc();
//std::cout << mPngHeader.toString() << "*********" << std::endl; std::cout << mPngHeader.toString() << "*********" << std::endl;
mOutStream->write(crc); mOutStream->write(crc);
} }
void BasicPngWriter::writeEndChunk() void BasicPngWriter::writeEndChunk()
{ {
//std::cout << "Start writing end chunk" << std::endl; std::cout << "Start writing end chunk" << std::endl;
unsigned length{ 0 }; unsigned length{ 0 };
mOutStream->write(length); mOutStream->write(length);
@ -109,7 +109,7 @@ void BasicPngWriter::writeEndChunk()
auto crc = crc_check.getChecksum(); auto crc = crc_check.getChecksum();
mOutStream->write(crc); mOutStream->write(crc);
//std::cout << "Writing end chunk" << std::endl; std::cout << "Finishe Writing end chunk" << std::endl;
} }
void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer) void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
@ -128,7 +128,7 @@ void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
} }
(void)length; (void)length;
//std::cout << "Writing idat length " << num_bytes << std::endl; std::cout << "Writing idat length " << num_bytes << std::endl;
mOutStream->write(static_cast<uint32_t>(num_bytes)); mOutStream->write(static_cast<uint32_t>(num_bytes));
std::vector<unsigned char> char_data = StringUtils::toBytes("IDAT"); std::vector<unsigned char> char_data = StringUtils::toBytes("IDAT");
@ -148,7 +148,7 @@ void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
} }
auto crc = crc_check.getChecksum(); auto crc = crc_check.getChecksum();
//std::cout << "Writing idat crc" << crc << std::endl; std::cout << "Writing idat crc: " << crc << std::endl;
mOutStream->write(crc); mOutStream->write(crc);
//std::cout << "Finished Writing idat crc" << crc << std::endl; //std::cout << "Finished Writing idat crc" << crc << std::endl;
} }
@ -158,7 +158,7 @@ void BasicPngWriter::write(const Path& path, Image* image)
{ {
std::unique_ptr<File> out_file; std::unique_ptr<File> out_file;
if (path.empty()) if (!path.empty())
{ {
out_file = std::make_unique<File>(path); out_file = std::make_unique<File>(path);
out_file->open(File::AccessMode::Write); out_file->open(File::AccessMode::Write);

View file

@ -22,7 +22,9 @@ public:
virtual ~BasicPngWriter(); virtual ~BasicPngWriter();
static std::unique_ptr<BasicPngWriter> Create(); using Ptr = std::unique_ptr<BasicPngWriter>;
static BasicPngWriter::Ptr Create();
void setCompressionMethod(Deflate::CompressionMethod method); void setCompressionMethod(Deflate::CompressionMethod method);
@ -44,7 +46,7 @@ private:
std::unique_ptr<BitStream> mInStream; std::unique_ptr<BitStream> mInStream;
std::unique_ptr<BitStream> mOutStream; std::unique_ptr<BitStream> mOutStream;
unsigned mPngInfoUserSet{ false }; bool mPngInfoUserSet{ false };
PngInfo mPngInfo; PngInfo mPngInfo;
PngHeader mPngHeader; PngHeader mPngHeader;

View file

@ -0,0 +1,77 @@
#include "PngFilter.h"
#include <iostream>
PngFilter::PngFilter(BitStream* inputStream, BitStream* outputStream)
: mInputStream(inputStream),
mOutputStream(outputStream)
{
}
void PngFilter::encode()
{
auto image_stream = dynamic_cast<ImageBitStream*>(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<ImageBitStream*>(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<FilterType>(*byte);
}
else
{
if (working_filter_type == FilterType::NONE)
{
image_stream->writeByte(*byte);
}
else
{
//std::cout << "Got filter type " << static_cast<int>(working_filter_type) << std::endl;
}
}
count++;
}
}

View file

@ -19,83 +19,13 @@ public:
PAETH PAETH
}; };
PngFilter(BitStream* inputStream, BitStream* outputStream) PngFilter(BitStream* inputStream, BitStream* outputStream);
: mInputStream(inputStream),
mOutputStream(outputStream)
{ void encode();
} void decode();
void encode()
{
auto image_stream = dynamic_cast<ImageBitStream*>(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<ImageBitStream*>(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<FilterType>(*byte);
}
else
{
if (working_filter_type == FilterType::NONE)
{
image_stream->writeByte(*byte);
}
else
{
//std::cout << "Got filter type " << static_cast<int>(working_filter_type) << std::endl;
}
}
count++;
}
}
private: private:
FilterType mFilterType{FilterType::NONE}; FilterType mFilterType{FilterType::NONE};
BitStream* mInputStream{nullptr}; BitStream* mInputStream{nullptr};
BitStream* mOutputStream{nullptr}; BitStream* mOutputStream{nullptr};

View file

@ -10,26 +10,46 @@ std::string PngHeader::toString() const
sstr << "PngHeader" << "\n"; sstr << "PngHeader" << "\n";
sstr << "width: " << mWidth << "\n"; sstr << "width: " << mWidth << "\n";
sstr << "height: " << mHeight << "\n"; sstr << "height: " << mHeight << "\n";
sstr << "bitDepth: " << (int)mBitDepth << "\n"; sstr << "bitDepth: " << static_cast<int>(mBitDepth) << "\n";
sstr << "cached CRC: " << mCachedCrc << "\n"; sstr << "cached CRC: " << mCachedCrc << "\n";
sstr << mPngInfo.toString(); sstr << mPngInfo.toString();
return sstr.str(); 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; return 13;
} }
unsigned char PngHeader::getHighBitCheck() const Byte PngHeader::getHighBitCheck() const
{ {
return 0x89; return 0x89;
} }
std::vector<unsigned char> PngHeader::getSignature() const void PngHeader::getSignature(VecBytes& sig) const
{ {
return {13, 10, 26, 10}; sig = {13, 10, 26, 10};
} }
std::string PngHeader::getFileName() const std::string PngHeader::getFileName() const
@ -42,7 +62,7 @@ const std::string& PngHeader::getChunkName() const
return mName; return mName;
} }
const std::vector<unsigned char>& PngHeader::getData() const const VecBytes& PngHeader::getData() const
{ {
return mData; return mData;
} }
@ -50,9 +70,9 @@ const std::vector<unsigned char>& PngHeader::getData() const
void PngHeader::updateData() void PngHeader::updateData()
{ {
mData.clear(); mData.clear();
unsigned num_bytes = sizeof(uint32_t); const auto num_bytes = sizeof(DWord);
for(unsigned idx=0; idx<num_bytes;idx++) for(std::size_t idx=0; idx<num_bytes;idx++)
{ {
mData.push_back(ByteUtils::getByteN(mWidth, idx)); mData.push_back(ByteUtils::getByteN(mWidth, idx));
} }
@ -62,13 +82,13 @@ void PngHeader::updateData()
mData.push_back(ByteUtils::getByteN(mHeight, idx)); mData.push_back(ByteUtils::getByteN(mHeight, idx));
} }
mData.push_back(mBitDepth); mData.push_back(mBitDepth);
mData.push_back(static_cast<unsigned char>(mPngInfo.mColorType)); mData.push_back(static_cast<Byte>(mPngInfo.mColorType));
mData.push_back(static_cast<unsigned char>(mPngInfo.mCompressionMethod)); mData.push_back(static_cast<Byte>(mPngInfo.mCompressionMethod));
mData.push_back(static_cast<unsigned char>(mPngInfo.mFilterMethod)); mData.push_back(static_cast<Byte>(mPngInfo.mFilterMethod));
mData.push_back(static_cast<unsigned char>(mPngInfo.mInterlaceMethod)); mData.push_back(static_cast<Byte>(mPngInfo.mInterlaceMethod));
} }
uint32_t PngHeader::getCrc() DWord PngHeader::getCrc()
{ {
CyclicRedundancyChecker crc_check; CyclicRedundancyChecker crc_check;
std::vector<unsigned char> char_data = StringUtils::toBytes(mName); std::vector<unsigned char> char_data = StringUtils::toBytes(mName);

View file

@ -8,35 +8,23 @@
class PngHeader class PngHeader
{ {
public: public:
uint32_t getLength() const; DWord getLength() const;
uint32_t getCrc(); DWord getCrc();
const std::vector<unsigned char>& getData() const; const VecBytes& getData() const;
uint32_t getWidth() const DWord getWidth() const;
{
return mWidth;
}
uint32_t getHeight() const DWord getHeight() const;
{
return mHeight;
}
unsigned char getBitDepth() const Byte getBitDepth() const;
{
return mBitDepth;
}
const PngInfo& getPngInfo() const const PngInfo& getPngInfo() const;
{
return mPngInfo;
}
unsigned char getHighBitCheck() const; Byte getHighBitCheck() const;
std::vector<unsigned char> getSignature() const; void getSignature(VecBytes& sig) const;
std::string getFileName() const; std::string getFileName() const;
@ -44,20 +32,20 @@ public:
void setPngInfo(const PngInfo& info); 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; std::string toString() const;
void updateData(); void updateData();
private: private:
uint32_t mWidth{0}; DWord mWidth{0};
uint32_t mHeight{0}; DWord mHeight{0};
unsigned char mBitDepth{0}; Byte mBitDepth{0};
PngInfo mPngInfo; PngInfo mPngInfo;
std::string mName{"IHDR"}; std::string mName{"IHDR"};
uint32_t mCachedCrc{0}; DWord mCachedCrc{0};
std::vector<unsigned char> mData; VecBytes mData;
}; };

View file

@ -19,23 +19,9 @@ std::string PngInfo::toString(ColorType colorType) const
} }
} }
unsigned PngInfo::getNumChannels() const ColorType PngInfo::ColorType() const
{ {
switch(mColorType) return 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;
}
} }
std::string PngInfo::toString(CompressionMethod method) const 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) 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; return method == 0;
} }
bool PngInfo::filterMethodIsValid(unsigned char method) bool PngInfo::filterMethodIsValid(Byte method)
{ {
return method == 0; return method == 0;
} }

View file

@ -1,12 +1,14 @@
#pragma once #pragma once
#include "ByteTypes.h"
#include <string> #include <string>
#include <sstream> #include <sstream>
class PngInfo class PngInfo
{ {
public: public:
enum class ColorType : unsigned char enum class ColorType : Byte
{ {
GREYSCALE = 0, GREYSCALE = 0,
RGB = 2, RGB = 2,
@ -15,23 +17,23 @@ public:
RGB_ALPHA = 6 RGB_ALPHA = 6
}; };
enum class CompressionMethod : unsigned char enum class CompressionMethod : Byte
{ {
DEFLATE = 0 DEFLATE = 0
}; };
enum class FilterMethod : unsigned char enum class FilterMethod : Byte
{ {
ADAPTIVE = 0 ADAPTIVE = 0
}; };
enum class InterlaceMethod : unsigned char enum class InterlaceMethod : Byte
{ {
NONE = 0, NONE = 0,
ADAM7 = 1 ADAM7 = 1
}; };
unsigned getNumChannels() const; ColorType getColorType() const;
std::string toString(ColorType colorType) const; std::string toString(ColorType colorType) const;
@ -41,11 +43,11 @@ public:
std::string toString(InterlaceMethod method) const; 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; std::string toString() const;

View file

@ -26,6 +26,15 @@ std::unique_ptr<PngWriter> PngWriter::Create()
return std::make_unique<PngWriter>(); return std::make_unique<PngWriter>();
} }
void PngWriter::setCompressionMethod(Deflate::CompressionMethod method)
{
#ifdef _WIN32
(void)method;
#else
dynamic_cast<BasicPngWriter*>(mWriterImpl.get())->setCompressionMethod(method);
#endif
}
void PngWriter::write(const Path& path, Image* image) void PngWriter::write(const Path& path, Image* image)
{ {
mWriterImpl->write(path, image); mWriterImpl->write(path, image);

View file

@ -2,6 +2,7 @@
#include "Image.h" #include "Image.h"
#include "IImageWriter.h" #include "IImageWriter.h"
#include "DeflateElements.h"
#include <memory> #include <memory>
#include <string> #include <string>
@ -14,6 +15,8 @@ public:
static std::unique_ptr<PngWriter> Create(); static std::unique_ptr<PngWriter> Create();
void setCompressionMethod(Deflate::CompressionMethod method);
void write(const Path& path, Image* image) override; void write(const Path& path, Image* image) override;
private: private:

View file

@ -12,6 +12,7 @@
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <iostream>
void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry *registry, void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version) 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) void WaylandInterface::registryHandleGlobalRemoveEvent(void *data, struct wl_registry *registry, uint32_t name)
{ {
std::cout << "remove handler called " << std::endl;
(void)data; (void)data;
(void)registry; (void)registry;
(void)name; (void)name;

View file

@ -6,6 +6,8 @@
#include "DrawingContext.h" #include "DrawingContext.h"
#include "FontsManager.h" #include "FontsManager.h"
#include <iostream>
void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, FontsManager* fontsManager, WaylandEglInterface* eglInterface) void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, FontsManager* fontsManager, WaylandEglInterface* eglInterface)
{ {
auto wayland_window = std::make_unique<WaylandSurface>(window, compositor, xdg_wm_base, buffer, eglInterface); auto wayland_window = std::make_unique<WaylandSurface>(window, compositor, xdg_wm_base, buffer, eglInterface);
@ -78,7 +80,7 @@ void WaylandSurface::initialize()
void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial) void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial)
{ {
xdg_surface_ack_configure(xdg_surface, serial); xdg_surface_ack_configure(xdg_surface, serial);
beforePaint(nullptr); mWindow->doPaint(nullptr);
} }
void WaylandSurface::beforePaint(mt::Screen* screen) void WaylandSurface::beforePaint(mt::Screen* screen)
@ -124,21 +126,30 @@ void WaylandSurface::beforePaintSoftware()
const auto height = mWindow->getHeight(); const auto height = mWindow->getHeight();
const int stride = width * mWorkingBitDepth; const int stride = width * mWorkingBitDepth;
std::cout << "before paint" << std::endl;
const int shm_pool_size = getImageBufferSize(); const int shm_pool_size = getImageBufferSize();
mBuffer->initializeSharedBuffer(shm_pool_size); mBuffer->initializeSharedBuffer(shm_pool_size);
mBuffer->setUpPool(shm_pool_size, width, height, stride); 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); //ImagePrimitives::drawCheckerboard(mBuffer->getPoolData(), width, height, offset);
std::cout << "checkerboard drawn" << std::endl;
} }
void WaylandSurface::afterPaintSoftware() void WaylandSurface::afterPaintSoftware()
{ {
std::cout << "after paint" << std::endl;
const int shm_pool_size = getImageBufferSize(); const int shm_pool_size = getImageBufferSize();
mBuffer->tearDownPool(shm_pool_size); mBuffer->tearDownPool(shm_pool_size);
wl_surface_attach(mSurface, mBuffer->getWorkingBuffer(), 0, 0); 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); wl_surface_commit(mSurface);
} }

View file

@ -53,7 +53,7 @@ private:
unsigned getImageBufferSize() const; unsigned getImageBufferSize() const;
mt::Window* mWindow{nullptr}; //mt::Window* mWindow{nullptr};
wl_compositor* mCompositor{nullptr}; wl_compositor* mCompositor{nullptr};
xdg_wm_base* mXdgWmBase{nullptr}; xdg_wm_base* mXdgWmBase{nullptr};

View file

@ -4,6 +4,7 @@ set(UNIT_TEST_TARGETS)
set(INTEGRATION_TEST_TARGETS) set(INTEGRATION_TEST_TARGETS)
add_subdirectory(core) add_subdirectory(core)
#add_subdirectory(console)
add_subdirectory(database) add_subdirectory(database)
add_subdirectory(fonts) add_subdirectory(fonts)
add_subdirectory(geometry) add_subdirectory(geometry)
@ -18,6 +19,7 @@ set(TEST_MODULES
audio audio
compiler compiler
compression compression
console
image image
ipc ipc
mesh mesh

23
test/bootstrap_tests.sh Executable file
View file

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

View file

@ -0,0 +1,9 @@
include(TestTargets)
unit_tests(
MODULE_NAME console
FILES
TestConsoleApp.cpp
DEPENDENCIES
console
)

View file

@ -0,0 +1,93 @@
#include "TestFramework.h"
#include "TestUtils.h"
#include "TermInfo.h"
#include <iostream>
#include <cstdlib>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
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<char> 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);
}

View file

@ -1,8 +1,43 @@
#include "StringUtils.h" #include "String.h"
#include "TestFramework.h" #include "TestFramework.h"
#include "TestUtils.h" //#include "TestUtils.h"
#include <iostream>
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") TEST_CASE(TestStringUtils_StripSurroundingWhitepsace, "core")
{ {
std::string input = " super() "; std::string input = " super() ";
@ -28,3 +63,5 @@ TEST_CASE(TestStringUtils_startsWith, "core")
starts_with = StringUtils::startsWith(input, "```", ignore_whitespace); starts_with = StringUtils::startsWith(input, "```", ignore_whitespace);
REQUIRE(starts_with); REQUIRE(starts_with);
} }
*/

18
test/core/TestVector.cpp Normal file
View file

@ -0,0 +1,18 @@
#include "Vector.h"
#include "TestFramework.h"
#include <stdio.h>
TEST_CASE(TestVectorOps, "core")
{
Vector<size_t> 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);
}
}

View file

@ -11,7 +11,7 @@
#include "TestUtils.h" #include "TestUtils.h"
#include <iostream> #include <iostream>
TEST_CASE(TestCompressedPng, "image") TEST_CASE(TestUncompressedPng, "image")
{ {
unsigned width = 20; unsigned width = 20;
unsigned height = 20; unsigned height = 20;
@ -30,13 +30,14 @@ TEST_CASE(TestCompressedPng, "image")
image->getGridT<unsigned char>()->setData(data); image->getGridT<unsigned char>()->setData(data);
PngWriter writer; PngWriter writer;
//writer.setCompressionMethod(Deflate::CompressionMethod::NONE); writer.setCompressionMethod(Deflate::CompressionMethod::NONE);
writer.write(TestUtils::getTestOutputDir() / "test_compressed.png", image.get()); writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_uncompressed.png", image.get());
return; File test_file(TestUtils::getTestOutputDir(__FILE__) / "test_uncompressed.png");
File test_file(TestUtils::getTestOutputDir() / "test_compressed.png");
test_file.open(File::AccessMode::Read); test_file.open(File::AccessMode::Read);
std::cout << test_file.dumpBinary();
return;
while(auto byte = test_file.readNextByte()) while(auto byte = test_file.readNextByte())
{ {
//std::cout << static_cast<unsigned>(*byte) << std::endl; //std::cout << static_cast<unsigned>(*byte) << std::endl;
@ -63,13 +64,8 @@ TEST_CASE(TestFixedPng, "image")
image->getGridT<unsigned char>()->setData(data); image->getGridT<unsigned char>()->setData(data);
PngWriter writer; PngWriter writer;
//writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN); writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN);
writer.write(TestUtils::getTestOutputDir() / "test_fixed.png", image.get()); writer.write(TestUtils::getTestOutputDir(__FILE__) / "test_fixed.png", image.get());
//return;
File test_file(TestUtils::getTestOutputDir() / "test_fixed.png");
//std::cout << test_file.dumpBinary();
} }
TEST_CASE(TestDynamicCompressedPng, "image") TEST_CASE(TestDynamicCompressedPng, "image")
@ -93,9 +89,9 @@ TEST_CASE(TestDynamicCompressedPng, "image")
PngWriter writer; PngWriter writer;
//writer.setPath(TestUtils::getTestOutputDir() / "test_dynamic.png"); //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; //return;
File test_file(TestUtils::getTestOutputDir() / "test_dynamic.png"); File test_file(TestUtils::getTestOutputDir(__FILE__) / "test_dynamic.png");
//std::cout << test_file.dumpBinary(); //std::cout << test_file.dumpBinary();
} }

View file

@ -1,6 +1,7 @@
#include "TestFramework.h" #include "TestFramework.h"
#include "CommandLineArgs.h" #include "CommandLineArgs.h"
#include "ConsoleLogger.h"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
@ -13,10 +14,12 @@ int main(int argc, char *argv[])
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
#endif #endif
auto args = CommandLineArgs::Create(); CommandLineArgs args;
args->process(argc, argv); 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 #ifdef _WIN32
CoUninitialize(); CoUninitialize();

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <memory> #include "String.h"
#include <string> #include "Pointer.h"
#include <functional> #include <functional>
class TestCase class TestCase
@ -9,7 +9,7 @@ class TestCase
public: public:
using TestCaseFunction = std::function<void()>; using TestCaseFunction = std::function<void()>;
TestCase(const std::string& name, const std::string& tags, TestCaseFunction func) TestCase(const String& name, const String& tags, TestCaseFunction func)
: mTestFunction(func), : mTestFunction(func),
mName(name), mName(name),
mTags(tags) mTags(tags)
@ -19,12 +19,12 @@ public:
virtual ~TestCase() = default; virtual ~TestCase() = default;
const std::string& getName() const const String& getName() const
{ {
return mName; return mName;
} }
const std::string& getTags() const const String& getTags() const
{ {
return mTags; return mTags;
} }
@ -38,8 +38,8 @@ public:
TestCaseFunction mTestFunction{nullptr}; TestCaseFunction mTestFunction{nullptr};
private: private:
std::string mName; String mName;
std::string mTags; String mTags;
}; };
using TestCasePtr = std::unique_ptr<TestCase>; using TestCasePtr = Ptr<TestCase>;

View file

@ -1,13 +1,11 @@
#include "TestCaseRunner.h" #include "TestCaseRunner.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "TestUiApplication.h" #include "ConsoleLogger.h"
//#include "TestUiApplication.h"
#include <vector>
#include <iostream>
bool TestCaseRunner::sLastTestFailed = false; bool TestCaseRunner::sLastTestFailed = false;
std::string TestCaseRunner::sFailureLine = {}; String TestCaseRunner::sFailureLine = {};
TestCaseRunner::TestCaseRunner() TestCaseRunner::TestCaseRunner()
{ {
@ -19,6 +17,7 @@ TestCaseRunner::~TestCaseRunner()
} }
/*
TestUiApplication* TestCaseRunner::getTestApplication() TestUiApplication* TestCaseRunner::getTestApplication()
{ {
return mTestApplication; return mTestApplication;
@ -28,6 +27,7 @@ void TestCaseRunner::setTestApplication(TestUiApplication* app)
{ {
mTestApplication = app; mTestApplication = app;
} }
*/
TestCaseRunner& TestCaseRunner::getInstance() TestCaseRunner& TestCaseRunner::getInstance()
{ {
@ -35,26 +35,26 @@ TestCaseRunner& TestCaseRunner::getInstance()
return instance; 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); auto test_case = new TestCase(label, tag, func);
mCases.push_back(test_case); mCases.push_back(test_case);
} }
void TestCaseRunner::markTestFailure(const std::string& line) void TestCaseRunner::markTestFailure(const String& line)
{ {
sLastTestFailed = true; sLastTestFailed = true;
sFailureLine = line; sFailureLine = line;
} }
bool TestCaseRunner::run(const std::vector<std::string>& args) bool TestCaseRunner::run(const Vector<String>& args)
{ {
std::string test_to_run; String test_to_run;
if (args.size() > 0 ) if (args.size() > 0 )
{ {
test_to_run = args[0]; test_to_run = args[0];
} }
FileLogger::GetInstance().disable(); //FileLogger::GetInstance().disable();
for (auto test_case : mCases) for (auto test_case : mCases)
{ {
if (!test_to_run.empty()) if (!test_to_run.empty())
@ -66,41 +66,22 @@ bool TestCaseRunner::run(const std::vector<std::string>& args)
} }
sLastTestFailed = false; sLastTestFailed = false;
std::cout << "TestFramework: Running Test - " << test_case->getName() << std::endl; ConsoleLogger::logLine("TestFramework: Running Test - %s", test_case->getName().raw());
try
{
test_case->run(); 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());
};
if (sLastTestFailed) if (sLastTestFailed)
{ {
std::cout << "Failed at line: " << sFailureLine << std::endl; ConsoleLogger::logLine("Failed at line %s", sFailureLine.raw());
mFailingTests.push_back(test_case->getName()); mFailingTests.push_back(test_case->getName());
} }
} }
if (mFailingTests.size() > 0) if (mFailingTests.size() > 0)
{ {
std::cout << mFailingTests.size() << " failing tests: " << std::endl; ConsoleLogger::logLine("%d failing tests", mFailingTests.size());
for(const auto& name : mFailingTests) for(const auto& name : mFailingTests)
{ {
std::cout << name << std::endl; ConsoleLogger::logLine(name);
} }
} }

View file

@ -2,8 +2,8 @@
#include "TestCase.h" #include "TestCase.h"
#include <vector> #include "Vector.h"
#include <string> #include "String.h"
class TestUiApplication; class TestUiApplication;
@ -16,20 +16,20 @@ public:
~TestCaseRunner(); ~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<std::string>& args); bool run(const Vector<String>& args);
void setTestApplication(TestUiApplication* app); //void setTestApplication(TestUiApplication* app);
private: private:
TestUiApplication* mTestApplication{ nullptr }; //TestUiApplication* mTestApplication{ nullptr };
std::vector<std::string> mFailingTests; Vector<String> mFailingTests;
static bool sLastTestFailed; static bool sLastTestFailed;
static std::string sFailureLine; static String sFailureLine;
std::vector<TestCase*> mCases; Vector<TestCase*> mCases;
}; };

View file

@ -4,7 +4,7 @@
struct Holder struct Holder
{ {
Holder(const std::string& name, const std::string& tags, std::function<void()> func) Holder(const String& name, const String& tags, std::function<void()> func)
{ {
TestCaseRunner::getInstance().addTestCase(name, tags, func); TestCaseRunner::getInstance().addTestCase(name, tags, func);
} }
@ -19,8 +19,8 @@ struct Holder
#define REQUIRE(predicate) \ #define REQUIRE(predicate) \
if(!bool(predicate)) \ if(!bool(predicate)) \
{ \ { \
TestCaseRunner::getInstance().markTestFailure(std::to_string(__LINE__) + " with check: '" + std::string(#predicate) + "'"); \ const auto msg = String::to_string(__LINE__) + String(" with check: '") + String(#predicate) + String("'"); \
return; \ TestCaseRunner::getInstance().markTestFailure(msg); \
} \ } \

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "TestDataLocations.h" //#include "TestDataLocations.h"
#include <filesystem> #include <filesystem>

View file

@ -16,5 +16,5 @@ TEST_CASE(TestWaylandWindow, "web")
//app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND); //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND);
app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER); app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER);
app->run(); //app->run();
} }