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
auto app = NotesTk(std::move(args));
//app.setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER);
app.setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER);
app.run();
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;
private:
bool lookAheadSourceEmpty() const;
unsigned char getSearchBufferItem(unsigned index) const;
unsigned lookAheadForMatchingChars(unsigned searchIndex);

View file

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

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);
}
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)
{
return std::make_unique<Color>(color);

View file

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

View file

@ -34,37 +34,37 @@ void CommandLineArgs::initialize(CommandLineArgs* args)
#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;
}
void CommandLineArgs::recordLaunchPath()
{
mLaunchPath = std::filesystem::current_path();
mLaunchPath = FileSystemPath::current_dir();
}
void CommandLineArgs::process(int argc, char *argv[])
{
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;
}
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++)
{
user_args.push_back(mArugments[idx]);
@ -72,7 +72,7 @@ std::vector<std::string> CommandLineArgs::getUserArgs() const
return user_args;
}
const std::vector<std::string> CommandLineArgs::getArgs() const
const Vector<String> CommandLineArgs::getArgs() const
{
return mArugments;
}

View file

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

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
#include <vector>
#include <iostream>
#include "Vector.h"
template<typename T>
class CircleBuffer
@ -60,5 +58,5 @@ public:
private:
std::size_t mStartPointer{0};
std::size_t mEndPointer{0};
std::vector<T> mData;
Vector<T> mData;
};

View file

@ -1,8 +1,7 @@
#pragma once
#include <vector>
#include <string>
#include <stdexcept>
#include "Error.h"
#include "Vector.h"
class AbstractList
{
@ -20,7 +19,7 @@ public:
void initializeTo(std::size_t size, T value)
{
mData = std::vector<T>(size, value);
mData = Vector<T>(size, value);
}
const T* getDataPtr() const
@ -28,7 +27,7 @@ public:
return mData.data();
}
const std::vector<T>& getData() const
const Vector<T>& getData() const
{
return mData;
}
@ -46,7 +45,7 @@ public:
}
}
void setData(const std::vector<T>& data)
void setData(const Vector<T>& data)
{
mData = data;
}
@ -65,5 +64,5 @@ public:
}
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
#include <memory>
template<typename T>
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
#include <memory>
#include "Pointer.h"
template<typename T>
class Node
@ -10,7 +10,7 @@ public:
: mData(data)
{}
void addChild(std::unique_ptr<Node> child)
void addChild(Ptr<Node> child)
{
if(!mLeftChild)
{
@ -45,12 +45,12 @@ public:
private:
T mData;
unsigned char mTag{0};
std::unique_ptr<Node> mLeftChild;
std::unique_ptr<Node> mRightChild;
Ptr<Node> mLeftChild;
Ptr<Node> mRightChild;
};
template<typename T>
using NodePtr = std::unique_ptr<Node<T> >;
using NodePtr = Ptr<Node<T> >;
template<typename T>
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
#include "ByteTypes.h"
#include "String.h"
#include <cstring>
#include <stdint.h>
#include <string>
class ByteUtils
{
public:
using Word = int16_t;
using DWord = int32_t;
using QWord = int64_t;
static bool MostSignificantBitIsOne(char c);
static bool MostSignificantBitIsOne(Byte c);
static Word GetWordFirstBit(const Word word);
static Word GetWordLastByte(const Word word);
static unsigned char getByteN(uint32_t input, unsigned n);
static Byte getByteN(DWord input, std::size_t n);
static unsigned char getHigherNBits(unsigned char input, unsigned num);
static Byte getHigherNBits(Byte input, std::size_t num);
static unsigned char getLowerNBits(uint32_t input, unsigned num);
static Byte getLowerNBits(DWord input, std::size_t num);
static unsigned char getTwoBitsAtN(unsigned char input, unsigned n);
static Byte getTwoBitsAtN(Byte input, std::size_t n);
static unsigned char getMBitsAtN(unsigned char input, unsigned m, unsigned n);
static Byte getMBitsAtN(Byte input, std::size_t m, std::size_t n);
static bool getBitN(uint32_t input, unsigned n);
static bool getBitN(DWord input, std::size_t n);
static unsigned char getFromString(const std::string& string);
static Byte getFromString(const String& string);
static std::string toString(uint32_t input, unsigned length = 8);
static String toString(DWord input, std::size_t length = 8);
static uint32_t mirror(uint32_t input, unsigned length=0);
static DWord mirror(DWord input, std::size_t length=0);
static void ReverseBuffer(char* buffer, char* reverse, unsigned size, unsigned targetSize);
static void ReverseBuffer(Byte* buffer, Byte* reverse, std::size_t size, std::size_t targetSize);
template<typename T>
static T ToType(char* buffer, bool reverse = true)
static T ToType(Byte* buffer, bool reverse = true)
{
T result {0};
if(reverse)
@ -54,17 +50,17 @@ public:
return result;
}
static Word ToWord(char* buffer, bool reverse = true);
static Word ToWord(Byte* buffer, bool reverse = true);
static DWord ToDWord(char* buffer, bool reverse = true);
static DWord ToDWord(Byte* buffer, bool reverse = true);
static QWord ToQWord(char* buffer, bool reverse = true);
static QWord ToQWord(Byte* buffer, bool reverse = true);
static bool Compare(char* buffer, const char* tag, unsigned size);
static bool Compare(Byte* buffer, const char* tag, std::size_t size);
static bool CompareDWords(char* buffer, const char* tag);
static bool CompareDWords(Byte* buffer, const char* tag);
static bool CompareWords(char* buffer, const char* tag);
static bool CompareWords(Byte* buffer, const char* tag);
static const int BYTE_FIRST_BIT = 0x40; // 1000 0000
static const Word WORD_FIRST_BIT = static_cast<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
#include "ByteTypes.h"
#include <string>
#include <vector>

View file

@ -1,30 +1,84 @@
#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;
if (std::filesystem::is_directory(path))
Vector<FileSystemPath> ret;
auto dirp = ::opendir(path.as_string().raw());
while(auto ep = ::readdir(dirp))
{
for (const auto& entry : std::filesystem::directory_iterator(path))
auto rel_path = String(ep->d_name);
if (rel_path == "." || rel_path == "..")
{
if (std::filesystem::is_regular_file(entry) && entry.path().extension() == extension)
continue;
}
auto full_path = path.join(rel_path);
struct stat sb;
auto rc = lstat(full_path.as_string().raw(), &sb);
if (rc == -1)
{
printf("Got error");
}
if (S_ISDIR(sb.st_mode))
{
printf("Adding full path: %s\n", full_path.as_string().raw());
ret.push_back(full_path);
}
}
::closedir(dirp);
return ret;
}
Vector<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.path());
paths.push_back(entry);
}
else if(recursive && std::filesystem::is_directory(entry))
else if(recursive && entry.is_directory())
{
const auto child_paths = getFilesWithExtension(entry, extension, recursive);
paths.insert(paths.end(), child_paths.begin(), child_paths.end());
const auto child_paths = getFiles(entry, recursive);
paths.extend(child_paths);
}
}
}
return paths;
}
void Directory::createIfNotExisting(const Path& path)
Vector<FileSystemPath> Directory::getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive)
{
Path working_path;
if (std::filesystem::is_directory(path))
Vector<FileSystemPath> paths;
if (path.is_directory())
{
for (const auto& entry : getSubdirectories(path))
{
if (entry.is_regular_file() && entry.extension() == extension)
{
paths.push_back(entry);
}
else if(recursive && entry.is_directory())
{
const auto child_paths = getFilesWithExtension(entry, extension, recursive);
paths.extend(child_paths);
}
}
}
return paths;
}
void Directory::create(const FileSystemPath& path, bool existsOk)
{
(void)existsOk;
FileSystemPath working_path;
if (path.is_directory())
{
working_path = path;
}
@ -33,8 +87,8 @@ void Directory::createIfNotExisting(const Path& path)
working_path = path.parent_path();
}
if (!std::filesystem::exists(working_path))
if (!working_path.exists())
{
std::filesystem::create_directories(working_path);
//std::filesystem::create_directories(working_path);
}
}

View file

@ -1,14 +1,16 @@
#pragma once
#include <vector>
#include <filesystem>
using Path = std::filesystem::path;
#include "Vector.h"
#include "FileSystemPath.h"
class Directory
{
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 "FileLogger.h"
//#include "FileLogger.h"
#include "ByteUtils.h"
#include "Directory.h"
#include "Result.h"
#include <streambuf>
#include <sstream>
#include <fcntl.h>
#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)
: mFullPath(path),
mInHandle(),
mOutHandle()
class FileImpl
{
public:
void do_open(const FileSystemPath& path, File::AccessMode accessMode)
{
int flags{0};
if (accessMode == File::AccessMode::Read)
{
flags |= O_RDONLY;
}
else
{
flags |= O_WRONLY;
flags |= O_CREAT;
}
m_fd = ::open(path.as_string().raw(), flags);
if (accessMode == File::AccessMode::Read)
{
m_open_for_read = true;
}
else
{
m_open_for_write = true;
}
}
void do_close()
{
::close(m_fd);
m_open_for_read = false;
m_open_for_write = false;
}
bool is_ok() const
{
return m_valid;
}
bool is_open_for_read() const
{
return m_open_for_read;
}
bool is_open_for_write() const
{
return m_open_for_write;
}
Result<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()
@ -19,145 +118,149 @@ File::~File()
close();
}
std::string File::getExtension() const
String File::getExtension() const
{
return mFullPath.extension().string();
return m_path.extension();
}
std::string File::dumpBinary()
bool File::readBinary(VecBytes& buffer)
{
auto ok = open(AccessMode::Read, true);
if (!ok)
{
return false;
}
m_impl->update_size();
buffer.resize(m_impl->m_size);
const auto result = m_impl->do_read(buffer);
buffer.resize(result.value());
return true;
}
String File::readText()
{
VecBytes buffer;
auto ok = open(AccessMode::Read, true);
if (!ok)
{
return {};
}
m_impl->update_size();
buffer.resize(m_impl->m_size);
const auto result = m_impl->do_read(buffer);
if (!result.ok())
{
printf("Got error: %s\n", result.error().msg());
return {};
}
buffer.resize(result.value());
return String(buffer);
}
String File::dumpBinary()
{
open(AccessMode::Read);
std::stringstream sstr;
sstr << "Count | Binary | Decimal | ASCII \n";
String sstr;
sstr << "Count | Binary | Decimal | Hex | ASCII \n";
VecBytes buffer;
readBinary(buffer);
unsigned count = 0;
while(mInHandle->peek() != EOF)
/*
for(const auto byte : buffer)
{
const unsigned char val = static_cast<unsigned char>(mInHandle->get());
const unsigned char ascii_val = std::isalpha(val) ? val : '.';
sstr << count << " | " << ByteUtils::toString(val) << " | " << static_cast<int>(val) << " | " << ascii_val << '\n';
const auto ascii_val = std::isalpha(byte) ? byte : '.';
String hex_sstr;
hex_sstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(byte);
sstr << count << " | " << ByteUtils::toString(byte) << " | " << static_cast<int>(byte) << " | " << hex_sstr.str() << " | " << ascii_val << '\n';
if (count % 10 == 0)
{
sstr << "\n";
}
count++;
}
const auto out = sstr.str();
*/
close();
return out;
return sstr;
}
std::ifstream* File::getInHandle() const
Optional<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
{
return val;
return buffer[0];
}
}
else
{
return std::nullopt;
return {};
}
}
bool File::open(AccessMode accessMode)
bool File::open(AccessMode accessMode, bool binary)
{
if (mFullPath.is_absolute() && !std::filesystem::exists(mFullPath.parent_path()))
if (m_path.is_absolute() && !m_path.parent_path().exists())
{
std::filesystem::create_directories(mFullPath.parent_path());
Directory::create(m_path.parent_path(), true);
}
if(accessMode == AccessMode::Read)
{
auto flags = std::ifstream::in;
mInHandle = std::make_unique<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;
}
}
m_impl->do_open(m_path, accessMode);
return true;
}
void File::close()
{
if(mOutHandle)
{
mOutHandle->close();
}
if(mInHandle)
{
mInHandle->close();
}
m_impl->do_close();
}
FileFormat::Format File::inferFormat() const
{
const auto extension = getExtension();
return FileFormat::inferFormat(extension);
//const auto extension = getExtension();
//return FileFormat::inferFormat(extension);
return {};
}
void File::writeText(const std::string& text)
void File::writeText(const String& text)
{
bool had_to_open{false};
if (!mOutHandle)
if (!m_impl->is_open_for_write())
{
had_to_open = true;
if (!open(File::AccessMode::Write))
{
return;
}
m_impl->do_open(m_path, File::AccessMode::Write);
}
(*mOutHandle) << text;
m_impl->do_write(text.data(), text.data().size() - 1);
if (had_to_open)
{
close();
m_impl->do_close();
}
}
std::vector<std::string> File::readLines()
Vector<String> File::readLines()
{
std::vector<std::string> content;
Vector<String> content;
/*
if (!pathExists())
{
return {};
@ -168,18 +271,20 @@ std::vector<std::string> File::readLines()
return {};
}
std::string str;
String str;
while(std::getline(*mInHandle, str))
{
content.push_back(str);
}
close();
*/
return content;
}
std::string File::read()
String File::read()
{
/*
if (!pathExists())
{
return {};
@ -190,31 +295,16 @@ std::string File::read()
return {};
}
std::stringstream buffer;
String buffer;
buffer << mInHandle->rdbuf();
close();
return buffer.str();
}
std::string File::readText()
{
if (!pathExists())
{
return {};
}
if(!open(AccessMode::Read))
{
return {};
}
std::string str((std::istreambuf_iterator<char>(*mInHandle)),
std::istreambuf_iterator<char>());
return str;
*/
String buffer;
return buffer;
}
bool File::pathExists() const
{
return std::filesystem::exists(mFullPath);
return m_path.exists();
}

View file

@ -1,57 +1,53 @@
#pragma once
#include "FileFormats.h"
#include "FileSystemPath.h"
#include "Optional.h"
#include "String.h"
#include "ByteTypes.h"
#include "Pointer.h"
#include <filesystem>
#include <string>
#include <fstream>
#include <memory>
#include <vector>
#include <optional>
using Path = std::filesystem::path;
class FileImpl;
class File
{
public:
enum class AccessMode{
Read,
Write
Write,
ReadWrite
};
public:
File(std::filesystem::path fullPath);
File(const FileSystemPath& path);
~File();
void close();
std::string dumpBinary();
String dumpBinary();
std::string getExtension() const;
std::ifstream* getInHandle() const;
std::ofstream* getOutHandle() const;
String getExtension() const;
FileFormat::Format inferFormat() const;
std::string readText();
String readText();
std::vector<std::string> readLines();
Vector<String> readLines();
std::string read();
String read();
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:
std::filesystem::path mFullPath;
std::unique_ptr<std::ifstream> mInHandle;
std::unique_ptr<std::ofstream> mOutHandle;
Ptr<FileImpl> m_impl;
FileSystemPath m_path;
};

View file

@ -1,7 +1,7 @@
#pragma once
#include <map>
#include <string>
#include "Map.h"
#include "String.h"
class FileFormat{
@ -24,13 +24,13 @@ public:
Unknown
};
using ExtensionMap = std::map<Format, std::string>;
using ExtensionMap = Map<Format, String>;
public:
static bool isFormat(const std::string& extension, Format format);
static bool isFormat(const String& extension, Format format);
static Format inferFormat(const std::string& query);
static Format inferFormat(const String& query);
static std::string getExtension(Format format);
static String getExtension(Format format);
private:
static ExtensionMap mExtensions;

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 <time.h>
#include <iomanip>
#include <iostream>
#include <filesystem>
FileLogger::FileLogger()
:mWorkDirectory(),
mFileName("MT_Log.txt")
{
}
FileLogger& FileLogger::GetInstance()
{
static FileLogger instance;
return instance;
}
FileLogger::~FileLogger()
{

View file

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

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

View file

@ -9,10 +9,10 @@ bool BufferBitStream::isFinished() const
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);
unsigned count = 0;
ret.resize(n, 0);
std::size_t count = 0;
int start = mByteOffset;
if (start<0)
@ -28,12 +28,11 @@ std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const
}
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()))
{
@ -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;
}
void BufferBitStream::writeByte(unsigned char data, bool checkOverflow)
void BufferBitStream::writeByte(uint8_t data, bool checkOverflow)
{
unsigned char out_byte{0};
uint8_t out_byte{0};
if (checkOverflow && mBitOffset > 0)
{
out_byte = ByteUtils::getLowerNBits(mCurrentByte, mBitOffset);
@ -76,12 +75,12 @@ void BufferBitStream::writeByte(unsigned char data, bool checkOverflow)
}
void BufferBitStream::writeBytes(const std::vector<unsigned char> data)
void BufferBitStream::writeBytes(const VecBytes& data)
{
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;
}

View file

@ -2,28 +2,25 @@
#include "BitStream.h"
#include <vector>
#include <iterator>
class BufferBitStream : public BitStream
{
public:
const std::vector<unsigned char>& getBuffer() const;
const VecBytes& getBuffer() const;
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 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:
std::vector<unsigned char> mBuffer;
VecBytes mBuffer;
};

View file

@ -12,16 +12,15 @@ bool InputBitStream::isFinished() const
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())
{
return static_cast<unsigned char>(mStream->get());
return static_cast<Byte>(mStream->get());
}
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;
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;
}
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;
}
void OutputBitStream::writeByte(unsigned char data, bool)
void OutputBitStream::writeByte(uint8_t data, bool)
{
(*mStream) << data;
}
void OutputBitStream::writeBytes(const std::vector<unsigned char> data)
void OutputBitStream::writeBytes(const VecBytes& data)
{
for(auto byte : data)
{

View file

@ -11,13 +11,13 @@ public:
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:
std::basic_ostream<char>* mStream{nullptr};

View file

@ -12,7 +12,7 @@ public:
this->mData->initializeTo(numPointsX * numPointsY * numPointsZ, T());
}
T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx) const override
T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx = 1) const override
{
return this->mData->getItem(getOffset(idx, jdx, kdx));
}
@ -37,3 +37,40 @@ public:
return this->mData->getLength();
}
};
template<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,7 +5,8 @@ list(APPEND HEADERS
BasicWebApp.h)
list(APPEND SOURCES
BasicWebApp.cpp
TermInfo.cpp
BasicWebApp.cpp
MainApplication.cpp)
add_library(${MODULE_NAME} SHARED ${SOURCES} ${HEADERS})
@ -17,4 +18,4 @@ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)
target_link_libraries(${MODULE_NAME} PUBLIC core audio network database web graphics publishing)
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)

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
Image.h
Pixel.h
IImageWriter.h
PlatformImage.h
PlatformImageWriter.h
@ -14,6 +15,7 @@ list(APPEND image_HEADERS
list(APPEND image_LIB_INCLUDES
Image.cpp
Pixel.cpp
ImageBitStream.cpp
PlatformImage.cpp
png/BasicPngWriter.cpp
@ -21,6 +23,7 @@ list(APPEND image_LIB_INCLUDES
png/PngReader.cpp
png/PngHeader.cpp
png/PngInfo.cpp
png/PngFilter.cpp
)
if(WIN32)

View file

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

View file

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

View file

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

View file

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

View file

@ -22,7 +22,9 @@ public:
virtual ~BasicPngWriter();
static std::unique_ptr<BasicPngWriter> Create();
using Ptr = std::unique_ptr<BasicPngWriter>;
static BasicPngWriter::Ptr Create();
void setCompressionMethod(Deflate::CompressionMethod method);
@ -44,7 +46,7 @@ private:
std::unique_ptr<BitStream> mInStream;
std::unique_ptr<BitStream> mOutStream;
unsigned mPngInfoUserSet{ false };
bool mPngInfoUserSet{ false };
PngInfo mPngInfo;
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
};
PngFilter(BitStream* inputStream, BitStream* outputStream)
: mInputStream(inputStream),
mOutputStream(outputStream)
PngFilter(BitStream* inputStream, BitStream* outputStream);
{
void encode();
}
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++;
}
}
void decode();
private:
FilterType mFilterType{FilterType::NONE};
BitStream* mInputStream{nullptr};
BitStream* mOutputStream{nullptr};

View file

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

View file

@ -8,35 +8,23 @@
class PngHeader
{
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
{
return mWidth;
}
DWord getWidth() const;
uint32_t getHeight() const
{
return mHeight;
}
DWord getHeight() const;
unsigned char getBitDepth() const
{
return mBitDepth;
}
Byte getBitDepth() const;
const PngInfo& getPngInfo() const
{
return mPngInfo;
}
const PngInfo& getPngInfo() const;
unsigned char getHighBitCheck() const;
Byte getHighBitCheck() const;
std::vector<unsigned char> getSignature() const;
void getSignature(VecBytes& sig) const;
std::string getFileName() const;
@ -44,20 +32,20 @@ public:
void setPngInfo(const PngInfo& info);
void setImageData(uint32_t width, uint32_t height, unsigned char bitDepth);
void setImageData(DWord width, DWord height, Byte bitDepth);
std::string toString() const;
void updateData();
private:
uint32_t mWidth{0};
uint32_t mHeight{0};
unsigned char mBitDepth{0};
DWord mWidth{0};
DWord mHeight{0};
Byte mBitDepth{0};
PngInfo mPngInfo;
std::string mName{"IHDR"};
uint32_t mCachedCrc{0};
DWord mCachedCrc{0};
std::vector<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)
{
case ColorType::GREYSCALE:
return 1;
case ColorType::RGB:
return 3;
case ColorType::PALETTE:
return 1;
case ColorType::GREYSCALE_ALPHA:
return 2;
case ColorType::RGB_ALPHA:
return 4;
default:
return 1;
}
return mColorType;
}
std::string PngInfo::toString(CompressionMethod method) const
@ -73,7 +59,7 @@ std::string PngInfo::toString(InterlaceMethod method) const
}
}
bool PngInfo::bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const
bool PngInfo::bitDepthIsValid(ColorType colorType, Byte bitDepth) const
{
switch(colorType)
{
@ -92,12 +78,12 @@ bool PngInfo::bitDepthIsValid(ColorType colorType, unsigned char bitDepth) const
}
}
bool PngInfo::compressionMethodIsValid(unsigned char method)
bool PngInfo::compressionMethodIsValid(Byte method)
{
return method == 0;
}
bool PngInfo::filterMethodIsValid(unsigned char method)
bool PngInfo::filterMethodIsValid(Byte method)
{
return method == 0;
}

View file

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

View file

@ -26,6 +26,15 @@ std::unique_ptr<PngWriter> PngWriter::Create()
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)
{
mWriterImpl->write(path, image);

View file

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

View file

@ -12,6 +12,7 @@
#include <cstring>
#include <sstream>
#include <iostream>
void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
@ -41,6 +42,7 @@ void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry
void WaylandInterface::registryHandleGlobalRemoveEvent(void *data, struct wl_registry *registry, uint32_t name)
{
std::cout << "remove handler called " << std::endl;
(void)data;
(void)registry;
(void)name;
@ -90,7 +92,7 @@ void WaylandInterface::initialize()
addWindow(mDesktopManager->getWindowManager()->getWindow(idx));
}
mDesktopManager->getWindowManager()->getMainWindow()->show();
mDesktopManager->getWindowManager()->getMainWindow()->show();
}
void WaylandInterface::initializeHardwareRendering()

View file

@ -6,6 +6,8 @@
#include "DrawingContext.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)
{
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)
{
xdg_surface_ack_configure(xdg_surface, serial);
beforePaint(nullptr);
mWindow->doPaint(nullptr);
}
void WaylandSurface::beforePaint(mt::Screen* screen)
@ -124,21 +126,30 @@ void WaylandSurface::beforePaintSoftware()
const auto height = mWindow->getHeight();
const int stride = width * mWorkingBitDepth;
std::cout << "before paint" << std::endl;
const int shm_pool_size = getImageBufferSize();
mBuffer->initializeSharedBuffer(shm_pool_size);
mBuffer->setUpPool(shm_pool_size, width, height, stride);
//int offset{0};
mWindow->getImage()->toBuffer(mBuffer->getPoolData(), width*height*stride, Image::Format::ARGB);
//ImagePrimitives::drawCheckerboard(mBuffer->getPoolData(), width, height, offset);
std::cout << "checkerboard drawn" << std::endl;
}
void WaylandSurface::afterPaintSoftware()
{
std::cout << "after paint" << std::endl;
const int shm_pool_size = getImageBufferSize();
mBuffer->tearDownPool(shm_pool_size);
wl_surface_attach(mSurface, mBuffer->getWorkingBuffer(), 0, 0);
//wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
wl_surface_commit(mSurface);
}

View file

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

View file

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

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

View file

@ -1,6 +1,7 @@
#include "TestFramework.h"
#include "CommandLineArgs.h"
#include "ConsoleLogger.h"
#ifdef _WIN32
#include <windows.h>
@ -13,10 +14,12 @@ int main(int argc, char *argv[])
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
#endif
auto args = CommandLineArgs::Create();
args->process(argc, argv);
CommandLineArgs args;
args.process(argc, argv);
TestCaseRunner::getInstance().run(args->getUserArgs());
ConsoleLogger::logLine("Starting test run.");
TestCaseRunner::getInstance().run(args.getUserArgs());
ConsoleLogger::logLine("Finished test run.");
#ifdef _WIN32
CoUninitialize();

View file

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

View file

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

View file

@ -2,8 +2,8 @@
#include "TestCase.h"
#include <vector>
#include <string>
#include "Vector.h"
#include "String.h"
class TestUiApplication;
@ -16,20 +16,20 @@ public:
~TestCaseRunner();
TestUiApplication* getTestApplication();
//TestUiApplication* getTestApplication();
void addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func);
void addTestCase(const String& label, const String& tag, TestCase::TestCaseFunction func);
void markTestFailure(const std::string& line);
void markTestFailure(const String& line);
bool run(const std::vector<std::string>& args);
bool run(const Vector<String>& args);
void setTestApplication(TestUiApplication* app);
//void setTestApplication(TestUiApplication* app);
private:
TestUiApplication* mTestApplication{ nullptr };
std::vector<std::string> mFailingTests;
//TestUiApplication* mTestApplication{ nullptr };
Vector<String> mFailingTests;
static bool sLastTestFailed;
static std::string sFailureLine;
std::vector<TestCase*> mCases;
static String sFailureLine;
Vector<TestCase*> mCases;
};

View file

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

View file

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

View file

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